In today's exercise, we examine a simple language translation problem: converting a word from English into the children's language Pig-latin. Here are some examples of English words and their Pig-latin translation:
| English | Pig-latin | English | Pig-latin |
|---|---|---|---|
| alphabet | alphabetyay | nerd | erdnay |
| billygoat | illygoatbay | orthodox | orthodoxyay |
| crazy | azycray | prickly | icklypray |
| dripping | ippingdray | quasimodo | asimodoquay |
| eligible | eligibleyay | rhythm | ythmrhay |
| farm | armfay | spry | yspray |
| ghost | ostghay | three | eethray |
| happy | appyhay | ugly | uglyyay |
| illegal | illegalyay | vigilant | igilantvay |
| jury | uryjay | wretched | etchedwray |
| killjoy | illjoykay | xerxes | erxesxay |
| limit | imitlay | yellow | ellowyay |
| messy | essymay | zippy | ippyzay |
Study the examples given, looking for a "rule" that you can use to translate a word from English into Pig-latin. When you think you have found one, record it and then continue.
Today's problem is to complete a program to translate sentences from English into Pig-latin. To do so, we will use a new data type named string. A declaration of the form:
string englishWord = "farm";builds the object englishWord as an indexed variable capable of storing multiple characters:
The numbers 0, 1, 2 and 3 are the index values of the characters within englishWord, and can be used to access the individual characters within the string object.
To begin today's exercise, create a 4 subdirectory within labsand change directory to it. Then save a copy of translate.cpp in your new directory. This file contains the skeleton of a program for translating a sentence from English into Pig-latin. Using your text editor, open translate.cpp, and familiarize yourself with its contents.
Within translate.cpp, we can see several points of interest:
string englishWord,
piglatinWord;
cin >> englishWord;
The >> operator skips leading white space,
reads characters into the string object,
and stops when it encounters more white space.
The effect of operator >> is thus to
read the next word of input into the string object.
cout << piglatinWord;
piglatinWord = Piglatin(englishWord);
cin.get(separator);
Since this call occurs after a string value has been read,
separator will at the end of this call contain whatever
white space character caused the extraction operator to stop.
As usual, we begin by applying object-centered design to our problem.
Function Behavior, Part I. If we ignore the cases where the vowel is the first character in a word, we might describe the behavior of a function to translate an English word into Pig-latin as follows:
Receive an English word. Find the position of the first vowel in that word, checking that a vowel was actually present. (If not, our program should display a diagnostic and terminate.) The Pig-latin word is the portion of the word from the first vowel to its end, followed by the consonants at the beginning of the word, followed by "ay". Return the Pig-latin word.Note that in trying to anticipate what might go wrong, a user might enter a word with no vowels, and so we should check for this possibility.
Function Objects. From this description, we can identify the following objects:
| Description | Type | Kind | Movement | Name |
|---|---|---|---|---|
| The English word | string | varying | received | englishWord |
| Position of the first vowel | int | varying | local | vowelPosition |
| The Pig-latin word | string | varying | returned | piglatinWord |
| Portion of the English word from its first vowel until its end |
string | varying | local | lastPart |
| Consonants at the beginning of the English word | string | varying | local | firstPart |
| "ay" | string | constant | local | -- |
This gives us the following specification for our function:
Receive: englishWord, a string. Return: piglatinWord, a string.Use this specification to create a stub for a function named Piglatin() in translate.cpp; then add a prototype for Piglatin() above the main function.
Function Operations. Our behavioral description lists these operations:
| Description | Defined? | Name | Library? | |
|---|---|---|---|---|
| 1 | Receive englishWord (a string) from caller | yes | function call mechanism |
built-in |
| 2 | Find the position of the first vowel in a string | yes | find_first_of() | string |
| 3 | Check that the word actually contains a vowel | yes | assert() | cassert |
| 4 | Access the substring of a word from its first vowel to its end |
yes | substr() | string |
| 5 | Access the substring of a word from its beginning until just before its first vowel |
yes | substr() | string |
| 6 | Combine two substrings into a single string | yes | + | string |
| 7 | Return a string to the caller | yes | return | built-in |
Function Algorithm. Organizing these operations gives us this algorithm:
0. Receive englishWord from the caller.
1. Find vowelPosition, the position of the first vowel in englishWord;
check that a vowel was found.
2. Build lastPart, the substring of englishWord starting at
vowelPosition and running to its end.
3. Build firstPart, the substring of englishWord starting at
its beginning and ending just before vowelPosition.
4. Build piglatinWord by concatenating lastPart, firstPart, and "ay".
5. Return piglatinWord.
1. Find vowelPosition, the position of the first vowel in englishWord; check that a vowel was actually found. Since we want to find the first vowel in englishWord, we search the preceding list for a string operation to perform this operation. In the list, we see the find_first_of() function member which can be used for this purpose. The required pattern is a string listing each vowel, and we should begin searching at the first character, whose index is zero. The first line in our function is thus
unsigned vowelPosition = englishWord.find_first_of("aeiouyAEIOUY", 0);
That is, if englishWord is as follows:
then this statement will search englishWord for the first occurrence of a, e, i, o, u, y, A, E, I, O, U, or Y; beginning with the character at index 0, and will thus return 1, the index of a. Add this statement to the stub of Piglatin().
Our list of string function members also tells us that find_first_of() returns the special constant string::npos if none of the characters in pattern occur in the target. We can use this in an assert() to check that a vowel was found, so add a call to assert() to check that vowelPosition is not equal to string::npos. Then use the compiler to check the syntax of your program thus far. When its syntax is correct (aside from not returning a value), continue to the next part of the exercise.
2. Build lastPart, the substring of englishWord starting at its first vowel and running to its end. If we again search through the list of string operations, we see that the substr() operation provides a way to accomplish this step. In our case, we want to grab the substring of englishWord beginning at vowelPosition, and whose length is the number of characters between vowelPosition and the end of englishWord. (Calculating this length is the tricky part.) Since the string function member size() gives us the total number of characters in the string, and the index of the first character is always zero, we can get the length of the substring by subtracting vowelPosition from the size() of the string:
So the second step of our algorithm can be encoded like this:
string lastPart = englishWord.substr(vowelPosition,
englishWord.size() - vowelPosition);
As before, use the compiler to check the syntax of this statement.
Then continue on to the next step.
3. Build firstPart, the substring of initial consonants of englishWord. To perform step 3, we can again use the subst() function member of class string. Since we want to grab the consonants at the beginning of the string, we should start grabbing at index 0. As before, computing the number of characters to grab is the hard part: Since vowelPosition contains the index of the first vowel, and index values start at zero, the value of vowelPosition is also the number of consonants at the beginning of the string:
Using this information, add a statement to Piglatin() that encodes step 3, using the substr() function member. Test its syntax using the compiler, and continue when it is correct.
4. Build piglatinWord by concatenating lastPart, firstPart, and "ay". The operation of combining two or more string values into a single string is called concatenation. For example, the concatenation of the string values "en" and "list" produces the string "enlist", while the concatenation of "list" and "en" produces "listen". Order is thus significant in performing concatenation.
Examining the list of string operations, we see that string concatenation can be performed using the plus (+) operator. This step is thus easily coded as follows:
string pigLatinWord = lastPart + firstPart + "ay";Add this statement to Piglatin(), and use the compiler to check the correctness of its syntax; then continue to the last step.
5. Return pigLatinWord. This is a simple return statement, with which you should be familiar. Add the necessary return statement, and then compile and run your program, testing it with words that do not begin with a vowel. If your program compiles correctly but does not correctly translate words beginning with consonants into pig-late, track down your logic error before continuing.
What happens if you enter a word that begins with a vowel? Why?
In this part of the exercise, you are to extend function Piglatin() with the necessary code to handle words that begin with a vowel. Whereas Part I "led you by the hand", you are to figure out what must be done in Part II (feel free to consult with your lab partner).
Begin by describing how the function's behavior must differ from its current behavior. List any additional objects and/or operations that are required to achieve this new behavior. Modify the algorithm from Part I accordingly and then use it to update the code in Piglatin().
Pictures are often helpful, especially when figuring out proper index values, so try drawing a picture of a sample string if you get stuck.
String, Substring, Concatenation, String Input, String Output, String Length, String Replacement, String Searching, String Pattern Matching (Forward and Reverse).
Forward to the Homework Projects