The Pig Latin Translator, Part II

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.

Leave a Reply