Lab 4: Classes and string Objects
Introduction
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 | essmay |
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.
The Problem
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.
Getting Started
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:
-
For storing a sequence of characters,
C++ provides the type
string.
Variable or constant objects of type string
can be defined in the same manner as other objects:
string englishWord,
piglatinWord;
-
A
string value can be read from the keyboard
(via cin) into a string variable using
the extraction operator (>>),
just like any other kind of value:
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.
-
A
string value can be displayed on the screen
(via cout) using the insertion operator (<<).
cout << piglatinWord;
-
Functions can be written that take
string values as arguments,
and return string values:
piglatinWord = Piglatin(englishWord);
-
Unlike most of the types we have examined thus far,
string is the name of a class.
A class is a container whose name creates a new type,
in which can be stored both data and operations (i.e., functions).
The objects in a class that store data are called data members,
and the objects in a class that provide operations are called
function members.
-
In addition to
string, the types istream
and ostream are both classes.
The main function of translate.cpp uses the get()
function member of class istream, which reads a single
character from the stream, without skipping white space,
and passes it back to its caller through its argument:
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.
-
One way to understand a call to function member is the
message metaphor.
Think of this call as your main function sending
cin
the message get(), with separator as its argument.
When it receives the get() message and an argument,
cin reads the next character from the keyboard and stores it
in that argument, regardless of whether it is white space or not.
Our task is to write function Piglatin() that,
given an English word, returns its Pig-latin equivalent.
Function Design
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.
Function Coding
Some of these operations in our algorithm are familiar ones (e.g., 0, 5),
and require no further work on our part.
Others (e.g., 1-4) are less familiar.
If we want to avoid "reinventing the wheel", we must investigate the
operations (i.e., function members) provided by the string class.
To make this easier to do, we have provided a
string Library Quick Reference
containing some of the string function members.
(You may want to print a hard copy of it and store it in a convenient place.)
As it happens all of the less familiar operations in our algorithm can be
performed using string function members.
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
int 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.
<!-- To check that its logic is correct, run the debugger (gdb), set a breakpoint at the call to function PigLatin(), and then run your program from within gdb. Use the step command to step into PigLatin(), and examine the value of vowelPosition after the call to find_first_of(). When you are satisified with the correctness of what you have written, continue to the next step.-->
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?
Pig-latin Translation: Part II
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.
Phrases you should now understand:
String, Substring, Concatenation, String Input, String Output,
String Length, String Replacement, String Searching,
String Pattern Matching (Forward and Reverse).
|
|
|
|
Home
Help
Lab 0
Lab 1
Lab 2
Lab 3a
Lab 3b
Lab 4
Lab 5
Lab 6
Lab 7
Lab 8
Lab 9
Lab 10
Lab 11
Lab 12
Lab 13
Membership
Login |