{"id":6723,"date":"2024-12-28T00:01:30","date_gmt":"2024-12-28T08:01:30","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=6723"},"modified":"2024-12-21T09:55:52","modified_gmt":"2024-12-21T17:55:52","slug":"the-pig-latin-translator-part-iii","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=6723","title":{"rendered":"The Pig Latin Translator, Part III"},"content":{"rendered":"<p>The final step in my Pig Latin journey is to process an entire English language sentence. The <em>piglatin()<\/em> function, finished in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6718\">last week&#8217;s Lesson<\/a>, requires no updates. But chopping a sentence into words and sending them off to be processed individually proved to be an interesting exercise.<br \/>\n<!--more--><br \/>\nTo parse words from a sentence, I process the input string from beginning to end. A <em>while<\/em> loop churns through each character. To find words in the sentence, an <em>if<\/em> test uses the <em>isalapha()<\/em> ctype function to check for letters of the alphabet, upper- or lowercase:<\/p>\n<p><code>while(start-sentence&lt;len)<br \/>\n{<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;if( isalpha(*start) )<\/code><\/p>\n<p>Pointer variable <code>start<\/code> is initialized to the input string&#8217;s address, <code>sentence<\/code>; <code>len<\/code> is the string&#8217;s length.<\/p>\n<p>When the <em>isalpha()<\/em> test is true, pointer <code>start<\/code> references the start of a word. Pointer <code>end<\/code> is assigned the address stored in <code>start<\/code>. Then a nested <em>while<\/em> loop continues processing alphabetic characters to locate the end of the word, moving pointer <code>end<\/code> along the way:<\/p>\n<p><code>end = start;<br \/>\nwhile( isalpha(*end) || *end=='\\'' )<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;end++;<\/code><\/p>\n<p>The loop ends when a word is found. The non-alpha character after the word is saved in <em>char<\/em> variable <code>save<\/code>, then the word referenced by pointer <code>start<\/code> is capped:<\/p>\n<p><code>save = *end;<br \/>\n*end = '\\0';<\/code><\/p>\n<p>The word is now parsed and can be processed by the <em>piglatin()<\/em> function:<\/p>\n<p><code>printf(\"%s\",piglatin(start));<\/code><\/p>\n<p>After the Pig Latin translation is output, variable <code>start<\/code> is updated to look for another word. The non-alpha character saved in variable <code>save<\/code> is output to ensure consistency between the original and Pig Latin string:<\/p>\n<p><code>start = end+1;<br \/>\nputchar(save);<\/code><\/p>\n<p>Here is the full code:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2024_12_28-Lesson.c\" rel=\"noopener\" target=\"_blank\">2024_12_28-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#include &lt;ctype.h&gt;\r\n\r\n<span class=\"comments\">\/* test for vowels *\/<\/span>\r\nint isvowel(char a)\r\n{\r\n    if( a=='A' || a=='a' )\r\n        return 1;\r\n    if( a=='E' || a=='e' )\r\n        return 1;\r\n    if( a=='I' || a=='i' )\r\n        return 1;\r\n    if( a=='O' || a=='o' )\r\n        return 1;\r\n    if( a=='U' || a=='u' )\r\n        return 1;\r\n    return 0;\r\n}\r\n\r\n<span class=\"comments\">\/* translate a word into piglatin *\/<\/span>\r\nchar *piglatin(char *s)\r\n{\r\n    char *si,*pig;\r\n\r\n    <span class=\"comments\">\/* word starts with a vowel, add -hay *\/<\/span>\r\n    if( isvowel(*s) )\r\n    {\r\n        pig = malloc( strlen(s)+4+1 );    <span class=\"comments\">\/* \"-hay\" + '\\0' *\/<\/span>\r\n        if( pig==NULL )\r\n            return(\"Memory Error\");\r\n        strcpy(pig,s);\r\n        strcat(pig,\"-hay\");\r\n    }\r\n    else\r\n    {\r\n    <span class=\"comments\">\/* move first consonant\/consonant cluster\r\n       add -ay *\/<\/span>\r\n        si = s;\r\n        while( !isvowel(*si) )\r\n        {\r\n            si++;\r\n            if( *si=='\\0' )\r\n                return(\"Invalid word\");\r\n        }\r\n        pig = malloc( strlen(s)+3+1 );    <span class=\"comments\">\/* \"-ay\" + '\\0' *\/<\/span>\r\n        if( pig==NULL )\r\n        return(\"Memory Error\");\r\n        strcpy(pig,si);\r\n        strcpy(pig,\"-\");\r\n        strncat(pig,s,si-s);\r\n        strcat(pig,\"ay\");\r\n    }\r\n\r\n    return pig;\r\n}\r\n\r\nint main()\r\n{\r\n    char sentence[BUFSIZ];\r\n    char *start,*end;\r\n    char save;\r\n    int len;\r\n\r\n    printf(\"Original sentence: \");\r\n    fgets(sentence,BUFSIZ,stdin);\r\n    printf(\"Piglatin sentence: \");\r\n\r\n    <span class=\"comments\">\/* chop sentence into word chunks *\/<\/span>\r\n    start = sentence;\r\n    len = strlen(sentence);\r\n    while(start-sentence&lt;len)\r\n    {\r\n        if( isalpha(*start) )\r\n        {\r\n            end = start;\r\n            while( isalpha(*end) || *end=='\\'' )\r\n                end++;\r\n            save = *end;\r\n            *end = '\\0';\r\n            printf(\"%s\",piglatin(start));\r\n            start = end+1;\r\n            putchar(save);\r\n        }\r\n        else\r\n        {\r\n            putchar(*start);\r\n            start++;\r\n        }\r\n    }\r\n\r\n    return 0;\r\n}<\/pre>\n<p>The <em>isvowel()<\/em> and <em>piglatin()<\/em> functions are unchanged from last week&#8217;s code. The only modifications are in the <em>main()<\/em> function, as described earlier. Here is a sample run:<\/p>\n<p><code>Original sentence: Greetings from Dan Gookin!<br \/>\nPiglatin sentence: eetings-Gray om-fray an-Day ookin-Gay!<\/code><\/p>\n<p>I suppose another modification I could make would be to transform this code into a filter, as presented in my book <em>C All-In-One Desk Reference For Dummies<\/em>. But I&#8217;m weary of the whole Pig Latin thing, so I&#8217;ll save this task for a future Lesson.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This final installment of the series translates a full sentence into Pig Latin. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6723\">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-6723","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\/6723","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=6723"}],"version-history":[{"count":6,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6723\/revisions"}],"predecessor-version":[{"id":6775,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6723\/revisions\/6775"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6723"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6723"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}