Pig Latin translator - reverse translation error

1.2k views Asked by At

So I have full functionality of a program that translates from English into Pig Latin. I have about 80% functionality on the reverse translation.

I have two issues:

First, when translating back to English from Pig Latin, it adds some gibberish at the end of the very first input word it runs into that is longer than 7 chars. It doesn't do it again for any other words in the phrase, and only does it when converting from Pig Latin to English.

The second is more of a logic question. I can't think of how to check for a case where the English word starts with a T and ends with a vowel. For example: time translated into P. L. would be imetay. However, while not an actual word, eim would also translate to imetay in P. L. Without checking against an original English phrase, how could one tell whether imetay should be time or eim?

There are some debugging lines left in there to show what happens with the gibberish in the reverse translation.

//Matthew Gerton
//Project 3 - Pig latin translator
//11/26/14

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>

//structures for Node and Queue
typedef struct node
{
    char word[20];
    struct node * link;
}node;

typedef struct queue
{
    node * front;
    node * rear;
} queue;
queue *input = NULL, *trans = NULL;

//method prototypes
void break_and_translate(char * phrase, int z);
queue * buildPhrase(queue * abcd, char data[20]);
node * translate(node * data);
node * translateBack(node * nextWord);
void displayP(node * abcd);
int isWordSep(char a);
int isVowel(char a);


//main function drives switch statement method for entering, translating, displaying and clearing the queues
int main()
{
    int ch, ch2;

    char dummy;
    char * phrase;
    do
    {
        printf("\n\n1.\tInput phrase\n2.\tTranslate phrase\n3.\tDisplay phrase\n4.\tDisplay Translation\n5.\tClear current phrase and translation\n6.\tExit\n");
        printf("\nEnter your choice: ");
        scanf("%d", &ch);
        scanf("%c", &dummy);

        switch(ch)
         {

             //mallocs memory for the input phrase and scans the input phrase.   breaks the phrase into a queue and translates it.
             //then frees the memory for the phrase.
             case 1:
                phrase = (char *)malloc(1024 * sizeof(char));
                printf("Input the phrase to be translated.\n");
                gets(phrase);
                if(phrase==NULL)
                    printf("Sorry, cant read the phrase. Try again.");
                else
                  printf("Phrase recieved!!!!\n");

              break;

             //calls the method to translate the input stored in phrase
             case 2:
                printf("Are you tanslating from:\n1. English into pig latin\n2. Pig latin to english\n");
                scanf("%d", &ch2);
                scanf("%c", &dummy);
                break_and_translate(phrase, ch2);
                if(input ==NULL || trans ==NULL)
                {
                    printf("Translation uncessful. Rerun the program and try again!\n");
                    exit(0);
                }
                else
                    printf("Translation sucessfull!!!!\n");
             break;

             //Display the input phrase.
             case 3:
                if(phrase==NULL)
                    printf("No phrase entered.  Please enter a phrase to translate\n");
                else
                    printf("%s\n", phrase);
             break;

             //Display the translated phrase
             case 4:
                if(input==NULL)
                    printf("Translation has not been prepared yet.\nPlease either enter a phrase to translate, or translate the current phrase.\n");
                else
                    displayP(trans->front);
             break;

             //sets the queues back to null and frees the memory allocated to the phrase.
             case 5:
                 if(input ==NULL && trans ==NULL)
                 {
                     if(phrase == NULL)
                        printf("\nNothing to reset yet!  Enter and translate a phrase!\n");
                     else
                        printf("No tanslation yet, clearing the input phrase.\n");
                  }
                input = trans = NULL;
                free(phrase);
                phrase = NULL;
                printf("Reset sucessfull!!!!\n");
              break;

             //exit
             case 6:
                printf("Goodbye!!!!\n");
                 exit(0);

            default:
                 printf("\n\nInvalid choice. Please try again...\n");
         }
    } while(1);

    return (ch);
}

//initializes memory for a new queue
queue * new_queue()
{
    queue *s = (queue *)malloc(sizeof(queue));
    s->front = NULL;
    s->rear = NULL;
    return s;
}

//takes a queue input and string and adds a node the rear of the queue containing that string
//returns a pointer to the queue;
queue * buildPhrase(queue * abcd, char data[20])
{
    if(abcd==NULL)
    {
        abcd=new_queue();
    }
    if(abcd->rear == NULL)
    {
        abcd ->rear = (node *)malloc(sizeof(node));
        strcpy(abcd->rear->word, data);
        abcd -> rear->link = NULL;
        abcd ->front = abcd ->rear;
    }
    else
    {
        abcd ->rear->link = (node *)malloc(sizeof(node));
        abcd ->rear = abcd ->rear->link;
        strcpy(abcd->rear->word, data);
        abcd ->rear->link = NULL;
    }
    return abcd;
}

//Takes a node as an input.  Allocates memory for a new node for the latin word
//Takes the first letter from the input nodes word, moves shifts everyting left one char into the latin word
//Checks to see if the first letter was a capital letter.  If so, adds the lowecase char to the end and capitalizes the first
//Then checks to see if the first char was a vowel or capital vowel.  if so, adds t to the end of the latin word. then adds 'a' and 'y' regardless
//then returns the node for the latin translation.
node * translate(node * nextWord)
{
    char a; int b, c=0;
    a=nextWord ->word[0];
    node * latin = (node *)malloc(sizeof(node));

    if(isWordSep(a)==0)
    {
        for(b=1; b<strlen(nextWord->word); b++)
        {
            latin->word[b-1] = nextWord->word[b];
            c=b;
        }
        if((a>=65) && (a<= 91))
        {
            latin->word[0] = (latin->word[0]-32);
            latin->word[c++] = (a+32);
        }
        else
            latin->word[c++] = a;

        if(isVowel(a)==1)
        {
            latin->word[c++]='t';
        }
        latin->word[c++]='a';
        latin->word[c++]='y';
    }
    return latin;
}

//takes the input phrase as a parameter.  goes through the phrase until a "whitespace char" is found
//when one is found allocates memory for 2 node pointers, coppies the word up until that point to one pointer
//passes that pointer to the trsanslate method, translates it an returns it as the second pointer.  It then adds the punctuation
//to the end of each word then passes each node to the build queue method.  Then frees the memory for the nodes and resets the word array
void break_and_translate(char * phrase, int z)
{
    int space =0, b=0, c=0;
    char end, word[20];
    memset(word, '\0', strlen(word));
    end = phrase[0];

    while(end != '\0')
    {
        end = phrase[b];
        printf("END: %c\n", end);
        if(isWordSep(end)==0)
        {
            word[space]= end;
            space++;
            printf("WORD: %s\nstrlen WORD: %d\n", word, strlen(word));
        }
        else
        {

            node * temp = (node *)malloc(sizeof(node));
            node * temp2 = (node *)malloc(sizeof(node));

            strcpy(temp->word, word);
            if(z==1)
                temp2 = translate(temp);
            else
                temp2 = translateBack(temp);
            c = strlen(temp2->word);
            temp2->word[c]= word[space] = end;
            strcpy(temp->word, word);
           // printf("\n%s temp word\n%s temp2 word\n", temp->word, temp2->word);
            input = buildPhrase(input, temp->word);
            trans = buildPhrase(trans, temp2->word);
            memset(word, '\0', strlen(word));
            free(temp);
            free(temp2);
            space=0;
            printf("WORD: %s\n", word);
        }
        b++;
    }
}

//takes a pointer to the head of a queue and prints each word of each node.
void displayP(node * abcd)
{
    int a = 0;
    node *ptr =  (node *) malloc(sizeof(node));
    ptr = abcd;
    printf("\n");
    while(ptr != NULL)
    {
        printf("%s",ptr->word);
        a++;
        ptr = ptr->link;
    }
    free(ptr);
}
node * translateBack(node * nextWord)
{
    char a, x, y, z; int b, c=0, d;
    node * latinBack = (node *)malloc(sizeof(node));
    strcpy(latinBack->word, nextWord->word);
    z = latinBack->word[0];
    d = strlen(latinBack ->word);
    if(isWordSep(z)==0)
    {
        a=latinBack ->word[d-3];
        if((isVowel(a)==0)&&(a!='t'))
        {
            latinBack->word[d-2] = latinBack->word[d];
        }
        else if(a=='t')
        {
            x = nextWord ->word[d-4];
            y = nextWord ->word[d-5];
            if((isVowel(x)==1)&&(isVowel(y)==1))
            {
                latinBack->word[d-3] = latinBack->word[d];
                latinBack->word[d-2] = '\0';
                a=x;
            }
            else
                 latinBack->word[d-2] = latinBack->word[d];
        }
        latinBack->word[d-1] = '\0';
        latinBack->word[d] = '\0';
        for(b=strlen(latinBack->word); b>0; b--)
            latinBack->word[b] = latinBack->word[b-1];
        latinBack->word[0] = a;
        latinBack->word[strlen(latinBack->word)-1]='\0';
        z=latinBack->word[1];
        if((z>=65) && (z<= 91))
        {
            latinBack->word[0]= (latinBack->word[0]-32);
            latinBack->word[1]= (latinBack->word[1]+32);
        }
    }
    return latinBack;
}
int isWordSep(char a)
{
    if ((a==' ')||(a=='.')||(a==',')||(a=='!')||(a==';')||(a=='?')||(a=='\n')||(a=='\0'))
    return 1;
    else
    return 0;
}
int isVowel(char a)
{
    if((a == 'a')||(a=='e')||(a=='i')||(a=='o')||(a=='u')||(a == 'A')||(a=='E')||(a=='I')||(a=='O')||(a=='U'))
    return 1;
    else
    return 0;
}

1

There are 1 answers

0
Geoff Nixon On

As I learned Pig Latin, 'eim' would not be translated as imetay, but imeway. This seems to be reflected here, but I'm certainly not going to assert pedagogical superiority here, so I'm not sure if that helps.

A couple other things that might be useful:

  • I believe the latest release of cld2 detects Pig Latin — perhaps you might find some useful code there.

  • For the non-technical side of things like this, I highly recommend the wordreference.com forums. Don't know if they have a board specifically for Pig Latin, so maybe try the "English Only" one.

Awesome project!