{"id":6082,"date":"2023-11-04T00:01:53","date_gmt":"2023-11-04T07:01:53","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=6082"},"modified":"2024-10-12T16:07:47","modified_gmt":"2024-10-12T23:07:47","slug":"checking-your-spelling","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=6082","title":{"rendered":"Checking Your Spelling"},"content":{"rendered":"<p>At the basic level, a spell-checker works as a simple comparison program: The word in question is compared with each word in the dictionary. When the source word isn&#8217;t found, it&#8217;s assumed to be misspelled. With a dictionary file on your computer, it&#8217;s easy for a C programmer to code this type of program.<br \/>\n<!--more--><br \/>\nBorrowing code from <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6078\">last week&#8217;s Lesson<\/a> makes this task easier, as the dictionary is already scanned. What must be added are the steps to prompt for a word to input and then compare it with each word found in the dictionary file. By hand, such a chore would take hours. But with a computer, comparing words is quick and accurate.<\/p>\n<p>The key is to use the <em>strcmp()<\/em> function. Even so, the dictionary file is case-sensitive. For example, if you search for &#8220;kentucky&#8221; it won&#8217;t match the word &#8220;Kentucky.&#8221; Yes, it is misspelled if it&#8217;s not capitalized. Then again, the purpose of this week&#8217;s Lesson isn&#8217;t to fuzzy-match words, rather to match them verbatim.<\/p>\n<p>The following code prompts for input. The input word is compared with each word in the dictionary &mdash; tens of thousands of them in nanoseconds &mdash; and any match is reported.<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2023_11_04-Lesson.c\" rel=\"noopener\" target=\"_blank\">2023_11_04-Lesson.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;string.h&gt;\r\n\r\n<span class=\"comments\">\/* this code assumes the following path is valid *\/<\/span>\r\n#define DICTIONARY \"\/usr\/share\/dict\/words\"\r\n#define SIZE 32\r\n#define FALSE 0\r\n#define TRUE 1\r\n\r\nint main()\r\n{\r\n    FILE *dict;\r\n    int found,x;\r\n    char input[SIZE],word[SIZE],*r;\r\n\r\n    <span class=\"comments\">\/* gather user input *\/<\/span>\r\n    printf(\"Spell check a word: \");\r\n    fgets(input,SIZE,stdin);\r\n\r\n    <span class=\"comments\">\/* open the dictionary *\/<\/span>\r\n    dict = fopen(DICTIONARY,\"r\");\r\n    if( dict==NULL )\r\n    {\r\n        fprintf(stderr,\"Unable to open %s\\n\",DICTIONARY);\r\n        exit(1);\r\n    }\r\n\r\n    <span class=\"comments\">\/* scan for matching word (including newline) *\/<\/span>\r\n    found = FALSE;\r\n    while( !feof(dict) )\r\n    {\r\n        r = fgets(word,SIZE,dict);    <span class=\"comments\">\/* read a word *\/<\/span>\r\n        if( r==NULL )\r\n            break;\r\n        if( strcmp(input,word)==0 )\r\n        {\r\n            found = TRUE;\r\n            break;\r\n        }\r\n    }\r\n\r\n    <span class=\"comments\">\/* remove newline from input *\/<\/span>\r\n    for( x=0; x&lt;SIZE; x++ )\r\n    {\r\n        if( input[x]=='\\n' )\r\n        {\r\n            input[x] = '\\0';\r\n            break;\r\n        }\r\n    }\r\n\r\n    <span class=\"comments\">\/* output results *\/<\/span>\r\n    if(found)\r\n        printf(\"'%s' is in the dictionary!\\n\",input);\r\n    else\r\n        printf(\"I cannot locate '%s' in the dictionary.\\n\",input);\r\n\r\n    <span class=\"comments\">\/* close *\/<\/span>\r\n    fclose(dict);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>This code sets a few defined constants: <code>DICTIONARY<\/code> for the word file&#8217;s path; <code>SIZE<\/code> for the input buffer size; <code>FALSE<\/code> and <code>TRUE<\/code> to make the code more readable.<\/p>\n<p>First, user input is gathered, a word to scan for in the dictionary.<\/p>\n<p>Second, the dictionary file is opened, which is code pulled from previous Lessons.<\/p>\n<p>Third, variable <code>found<\/code> is set to <code>FALSE<\/code>; the input word isn&#8217;t yet found. A <em>while<\/em> loop then scans the dictionary. The <em>strcmp()<\/em> function compares each entry with the input word. Both words terminate with a newline, which is a feature of the <em>fgets()<\/em> function. If <em>strcmp()<\/em> returns zero, the words match, the <em>while<\/em> loop is broken and variable <code>found<\/code> is reset to <code>TRUE<\/code>.<\/p>\n<p>Fourth, the newline is stripped from the input word. I added this code to clean up the output, which is the final step: to show the found word or report that it&#8217;s misspelled.<\/p>\n<p>Here&#8217;s a sample run:<\/p>\n<p><code>Spell check a word: receive<br \/>\n'receive' is in the dictionary!<\/code><\/p>\n<p>And:<\/p>\n<p><code>Spell check a word: seperate<br \/>\nI cannot locate 'seperate' in the dictionary.<\/code><\/p>\n<p>Obviously more coding is required for a professional, real-time spellchecker. I believe such dictionaries also list common incorrect spellings and perform various fuzzy matching techniques. Now if only such technology were available with my texting app&#8217;s autocorrect feature . . .<\/p>\n<p>I have even more fun with the dictionary in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6098\">next week&#8217;s Lesson<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Obviously the digital dictionary exists to check spelling. Why not put its primary purpose to work? <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6082\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-6082","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6082","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6082"}],"version-history":[{"count":4,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6082\/revisions"}],"predecessor-version":[{"id":6637,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6082\/revisions\/6637"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6082"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6082"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6082"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}