From last week’s Lesson, the piglatin() 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.
When a word starts with a consonant, you could just move that single consonant to the end of the word, add -ay
, and be good. This approach is what I took with the Pig Latin filter that appeared in my old C programming book. But it’s not exactly correct: The goal is to move the first consonant cluster.
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 break into Pig Latin reak-bay, the word eak-bray is better. Therefore, finishing the code from last week’s Lesson requires a routine to hunt for the first vowel in a word.
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’t available as a ctype function, so I wrote my own, isvowel(). This update to the code includes this new function, and also a test to ensure that the program can properly isolate a consonant cluster:
2024_12_21-Lesson-a.c
#include <stdio.h> #include <stdlib.h> #include <string.h> /* test for vowels */ int isvowel(char a) { if( a=='A' || a=='a' ) return 1; if( a=='E' || a=='e' ) return 1; if( a=='I' || a=='i' ) return 1; if( a=='O' || a=='o' ) return 1; if( a=='U' || a=='u' ) return 1; return 0; } /* translate a word into piglatin */ char *piglatin(char *s) { char *si,*pig; /* word starts with a vowel, add -hay */ if( isvowel(*s) ) { pig = malloc( strlen(s)+4+1 ); /* "-hay" + '\0' */ if( pig==NULL ) return("Memory Error"); strcpy(pig,s); strcat(pig,"-hay"); } else { /* move first consonant/consonant cluster add -ay */ si = s; while( !isvowel(*si) ) { si++; if( *si=='\0' ) return("Invalid word"); } printf("%s, first vowel is %c\n",s,*si); pig = s; /* temp assignment */ } return pig; } int main() { char word[32]; char *s,*pl; printf("Original word: "); fgets(word,32,stdin); /* remove newline */ s = word; while(*s++) if( *s=='\n') *s='\0'; /* translate to pig latin */ pl = piglatin(word); printf("Translated word: %s\n",pl); return 0; }
The isvowel() 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.)
I replaced the switch-case structure in the piglatin() function with an isvowel() condition in an if statement. When the first character in the word is a vowel, the same processing takes place as last week’s code.
For the else condition, the string is processed until a non-vowel character is found. A printf() statement then outputs the original string and its first vowel. This test confirms that the code runs as intended, but it doesn’t translate the word into Pig Latin.
Here’s a sample run:
Original word: break
break, first vowel is e
Translated word: break
The next step is to replace these statements in the else condition, which run the test:
printf("%s, first vowel is %c\n",s,*si);
pig = s;
With these statements to process the word into Pig Latin:
pig = malloc( strlen(s)+3+1 ); /* "-ay" + '\0' */
if( pig==NULL )
return("Memory Error");
strcpy(pig,si);
strcat(pig,"-");
strncat(pig,s,si-s);
strcat(pig,"ay");
As with the if part of the piglatin() function, the word is copied into the buffer, but starting at the first consonant, strcpy(pig,si)
. The dash is added, strcat(pig,"-");
. Then only the consonant cluster is appended: strncat(pig,s,si-s)
. Finally, the ending is added: strcat(pig,"ay")
Click here to view the full code on GitHub. Here’s sample output:
Original word: break
Translated word: eak-bray
The piglatin() function works as intended, but it processes only a single word at a time. In next week’s Lesson, I update the code to churn through an entire sentence.