{"id":6718,"date":"2024-12-21T00:01:40","date_gmt":"2024-12-21T08:01:40","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=6718"},"modified":"2024-12-28T09:13:50","modified_gmt":"2024-12-28T17:13:50","slug":"the-pig-latin-translator-part-ii","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=6718","title":{"rendered":"The Pig Latin Translator, Part II"},"content":{"rendered":"<p>From <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6704\">last week&#8217;s Lesson<\/a>, the <em>piglatin()<\/em> function swallows a word and returns its Pig Latin translation, but only for words starting with a vowel. The operation for words that begin with a consonant is more complex.<br \/>\n<!--more--><br \/>\nWhen a word starts with a consonant, you could just move that single consonant to the end of the word, add <code>-ay<\/code>, and be good. This approach is what I took with the Pig Latin filter that appeared in my old C programming book. But it&#8217;s not exactly correct: The goal is to move the first <em>consonant cluster<\/em>.<\/p>\n<p>A consonant cluster is a group of consonants, specifically all the consonants that start a word up until the first vowel. While you could translate English <em>break<\/em> into Pig Latin <em>reak-bay<\/em>, the word <em>eak-bray<\/em> is better. Therefore, finishing the code from last week&#8217;s Lesson requires a routine  to hunt for the first vowel in a word.<\/p>\n<p>As finding vowels appears to be a common issue in this code, a vowel-detection function is required. It surprised me that such a function isn&#8217;t available as a ctype function, so I wrote my own, <em>isvowel()<\/em>. This update to the code includes this new function, and also a test to ensure that the program can properly isolate a consonant cluster:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2024_12_21-Lesson-a.c\" rel=\"noopener\" target=\"_blank\">2024_12_21-Lesson-a.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\">\/* 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        printf(\"%s, first vowel is %c\\n\",s,*si);\r\n        pig = s;    <span class=\"comments\">\/* temp assignment *\/<\/span>\r\n    }\r\n\r\n    return pig;\r\n}\r\n\r\nint main()\r\n{\r\n    char word[32];\r\n    char *s,*pl;\r\n\r\n    printf(\"Original word: \");\r\n    fgets(word,32,stdin);\r\n    <span class=\"comments\">\/* remove newline *\/<\/span>\r\n    s = word;\r\n    while(*s++)\r\n        if( *s=='\\n') *s='\\0';\r\n\r\n    <span class=\"comments\">\/* translate to pig latin *\/<\/span>\r\n    pl = piglatin(word);\r\n\r\n    printf(\"Translated word: %s\\n\",pl);\r\n\r\n    return 0;\r\n}<\/pre>\n<p>The <em>isvowel()<\/em> function accepts a single character, which is compared against all vowels, upper- and lowercase. When a vowel is encountered, 1 is returned, zero otherwise. (I know other ways are available to write this code, something I may look at again in the future.)<\/p>\n<p>I replaced the <em>switch-case<\/em> structure in the <em>piglatin()<\/em> function with an <em>isvowel()<\/em> condition in an <em>if<\/em> statement. When the first character in the word is a vowel, the same processing takes place as last week&#8217;s code.<\/p>\n<p>For the <em>else<\/em> condition, the string is processed until a non-vowel character is found. A <em>printf()<\/em> statement then outputs the original string and its first vowel. This test confirms that the code runs as intended, but it doesn&#8217;t translate the word into Pig Latin.<\/p>\n<p>Here&#8217;s a sample run:<\/p>\n<p><code>Original word: break<br \/>\nbreak, first vowel is e<br \/>\nTranslated word: break<\/code><\/p>\n<p>The next step is to replace these statements in the <em>else<\/em> condition, which run the test:<\/p>\n<p><code>printf(\"%s, first vowel is %c\\n\",s,*si);<br \/>\npig = s;<\/code><\/p>\n<p>With these statements to process the word into Pig Latin:<\/p>\n<p><code>pig = malloc( strlen(s)+3+1 );    <span class=\"comments\">\/* \"-ay\" + '\\0' *\/<\/span><br \/>\nif( pig==NULL )<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;return(\"Memory Error\");<br \/>\nstrcpy(pig,si);<br \/>\nstrcat(pig,\"-\");<br \/>\nstrncat(pig,s,si-s);<br \/>\nstrcat(pig,\"ay\");<\/code><\/p>\n<p>As with the <em>if<\/em> part of the <em>piglatin()<\/em> function, the word is copied into the buffer, but starting at the first consonant, <code>strcpy(pig,si)<\/code>. The dash is added, <code>strcat(pig,\"-\");<\/code>. Then only the consonant cluster is appended: <code>strncat(pig,s,si-s)<\/code>. Finally, the ending is added: <code>strcat(pig,\"ay\")<\/code><\/p>\n<p><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2024_12_21-Lesson-b.c\" target=\"_blank\">Click here<\/a> to view the full code on GitHub. Here&#8217;s sample output:<\/p>\n<p><code>Original word: break<br \/>\nTranslated word: eak-bray<\/code><\/p>\n<p>The <em>piglatin()<\/em> function works as intended, but it processes only a single word at a time. In <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6723\">next week&#8217;s Lesson<\/a>, I update the code to churn through an entire sentence.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My <em>piglatin<\/em> function is improved to handle all types of words. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6718\">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-6718","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\/6718","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=6718"}],"version-history":[{"count":7,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6718\/revisions"}],"predecessor-version":[{"id":6783,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6718\/revisions\/6783"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6718"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6718"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6718"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}