The final step in my Pig Latin journey is to process an entire English language sentence. The piglatin() function, finished in last week’s Lesson, requires no updates. But chopping a sentence into words and sending them off to be processed individually proved to be an interesting exercise.
To parse words from a sentence, I process the input string from beginning to end. A while loop churns through each character. To find words in the sentence, an if test uses the isalapha() ctype function to check for letters of the alphabet, upper- or lowercase:
while(start-sentence<len)
{
if( isalpha(*start) )
Pointer variable start
is initialized to the input string’s address, sentence
; len
is the string’s length.
When the isalpha() test is true, pointer start
references the start of a word. Pointer end
is assigned the address stored in start
. Then a nested while loop continues processing alphabetic characters to locate the end of the word, moving pointer end
along the way:
end = start;
while( isalpha(*end) || *end=='\'' )
end++;
The loop ends when a word is found. The non-alpha character after the word is saved in char variable save
, then the word referenced by pointer start
is capped:
save = *end;
*end = '\0';
The word is now parsed and can be processed by the piglatin() function:
printf("%s",piglatin(start));
After the Pig Latin translation is output, variable start
is updated to look for another word. The non-alpha character saved in variable save
is output to ensure consistency between the original and Pig Latin string:
start = end+1;
putchar(save);
Here is the full code:
2024_12_28-Lesson.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.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"); } pig = malloc( strlen(s)+3+1 ); /* "-ay" + '\0' */ if( pig==NULL ) return("Memory Error"); strcpy(pig,si); strcpy(pig,"-"); strncat(pig,s,si-s); strcat(pig,"ay"); } return pig; } int main() { char sentence[BUFSIZ]; char *start,*end; char save; int len; printf("Original sentence: "); fgets(sentence,BUFSIZ,stdin); printf("Piglatin sentence: "); /* chop sentence into word chunks */ start = sentence; len = strlen(sentence); while(start-sentence<len) { if( isalpha(*start) ) { end = start; while( isalpha(*end) || *end=='\'' ) end++; save = *end; *end = '\0'; printf("%s",piglatin(start)); start = end+1; putchar(save); } else { putchar(*start); start++; } } return 0; }
The isvowel() and piglatin() functions are unchanged from last week’s code. The only modifications are in the main() function, as described earlier. Here is a sample run:
Original sentence: Greetings from Dan Gookin!
Piglatin sentence: eetings-Gray om-fray an-Day ookin-Gay!
I suppose another modification I could make would be to transform this code into a filter, as presented in my book C All-In-One Desk Reference For Dummies. But I’m weary of the whole Pig Latin thing, so I’ll save this task for a future Lesson.