9 Strings9.1 AN ARRAY TYPE FOR STRINGS 351 C-String Values and C-String Variables 351 Pitfall: Using = and == with C-strings 355 Other Functions in 357 C-String Input and Output 360 9.2
Trang 17.//Uses cstdlib:
const Money operator -( const Money& amount1,
const Money& amount2) {
int allCents1 = amount1.cents + amount1.dollars*100;
int allCents2 = amount2.cents + amount2.dollars*100;
int diffAllCents = allCents1 - allCents2;
int absAllCents = abs(diffAllCents);
int finalDollars = absAllCents/100;
int finalCents = absAllCents%100;
if (diffAllCents < 0) {
finalDollars = -finalDollars;
finalCents = -finalCents;
} return Money(finalDollars, finalCents);
}
8 Add the following declaration and function definition:
friend bool operator <( const Money& amount1,
const Money& amount2);
bool operator <( const Money& amount1,
const Money& amount2) {
return ((amount1.dollars < amount2.dollars) ||
((amount1.dollars == amount2.dollars) &&
(amount1.cents < amount2.cents)));
}
9 To understand why it is not circular, you need to think about the basic message of over-loading: A single function or operator name can have two or more definitions That means that two or more different operators (or functions) can share a single name In the line
outputStream << "$-";
the operator << is the name of an operator defined in the library iostream to be used when the second argument is a quoted string The operator named << that we define in Display 8.5 is a different operator that works when the second argument is of type Money
10 If << and >> are to work as we want, then the first operand (first argument) must be cout
or cin (or some file I/O stream) But if we want to overload the operators as members of, say, the class Money, then the first operand would have to be the calling object and so would have to be of type Money, and that is not what we want
Trang 2Programming Projects 345
11.//Uses iostream:
istream& operator >>(istream& inputStream, Percent& aPercent) {
char percentSign;
inputStream >> aPercent.value;
inputStream >> percentSign; //Discards the % sign.
return inputStream;
} //Uses iostream:
ostream& operator <<(ostream& outputStream,
const Percent& aPercent) {
outputStream << aPercent.value << ’%’;
return outputStream;
}
12 It is legal, but the meaning is not what you might want (a++) increases the value of the member variables in a by one, but (a++)++ raises the value of the member variables in a++
by one, and a++ is a different object from a (It is possible to define the increment operator
so that (a++)++ will increase the value of the member variables by two but that requires use
of the this pointer which is not discussed until Chapter 10.)
PROGRAMMING PROJECTS
1 Modify the definition of the class Money shown in Display 8.5 so that the following are added:
a The operators <, <=, >, and >= have each been overloaded to apply to the type Money (Hint: See Self-Test Exercise 8.)
b The following member function has been added to the class definition (We show the function declaration as it should appear in the class definition The definition of the function itself will include the qualifier Money::.)
const Money percent( int percentFigure) const ; //Returns a percentage of the money amount in the calling object.
//For example, if percentFigure is 10, then the value returned is //10% of the amount of money represented by the calling object.
For example, if purse is an object of type Money whose value represents the amount
$100.10, then the call
purse.percent(10);
returns 10% of $100.10; that is, it returns a value of type Money that represents the amount
$10.01
Trang 32 Define a class for rational numbers A rational number is a number that can be represented
as the quotient of two integers For example, 1/2, 3/4, 64/2, and so forth are all rational numbers (By 1/2 and so on we mean the everyday fraction, not the integer division this expression would produce in a C++ program.) Represent rational numbers as two values of type int, one for the numerator and one for the denominator Call the class Rational Include a constructor with two arguments that can be used to set the member variables of
an object to any legitimate values Also include a constructor that has only a single parame-ter of type int; call this single parameter wholeNumber and define the constructor so that the object will be initialized to the rational number wholeNumber/1 Include a default con-structor that initializes an object to 0 (that is, to 0/1) Overload the input and output oper-ators >> and << Numbers are to be input and output in the form 1/2, 15/32, 300/401, and so forth Note that the numerator, the denominator, or both may contain a minus sign,
so -1/2, 15/-32, and -300/-401 are also possible inputs Overload all the following operators so that they correctly apply to the type Rational: ==, <, <=, >, >=, +, -, *, and / Write a test program to test your class Hints: Two rational numbers a/b and c/d are equal
if a*d equals c*b If b and d are positive rational numbers, a/b is less than c/d provided a*d
is less than c*b You should include a function to normalize the values stored so that, after normalization, the denominator is positive and the numerator and denominator are as small as possible For example, after normalization 4/-8 would be represented the same as
-1/2
3 Define a class for complex numbers A complex number is a number of the form
a + b*i
where for our purposes, a and b are numbers of type double, and i is a number that repre-sents the quantity Represent a complex number as two values of type double Name the member variables real and imaginary (The variable for the number that is multiplied by i is the one called imaginary.) Call the class Complex Include a constructor with two parameters of type double that can be used to set the member variables of an object to any values Include a constructor that has only a single parameter of type double; call this parameter realPart and define the constructor so that the object will be initial-ized to realPart + 0*i Include a default constructor that initializes an object to 0 (that
is, to 0 + 0*i) Overload all the following operators so that they correctly apply to the type
Complex: ==, +, -, *, >>, and << You should also write a test program to test your class
Hints: To add or subtract two complex numbers, add or subtract the two member variables
of type double The product of two complex numbers is given by the following formula:
(a + b*i)*(c + d*i) == (a*c - b*d) + (a*d + b*c)*i
In the interface file, you should define a constant i as follows:
const Complex i(0, 1);
This defined constant i will be the same as the i discussed above
4 (Cumulatively modify the example from Display 8.7 as follows
1 –
a
b
c
Trang 4Programming Projects 347
a In Display 8.7, replace the private char members first and second with an array of char
of size 100 and a private data member named size Provide a default constructor that initializes size to 10 and sets the first 10 of the char
positions to ’#’ (This only uses 10 of the possible 100 slots.) Provide an accessor function that returns the value of the private member size Test
b Add an operator[] member that returns a char& that allows the user to access or to set any member of the private data array using a non-negative index that is less than size Test
c Add a constructor that takes an int argument, sz, that sets the first sz members of the
char array to ’#’ Test
d Add a constructor that takes an int argument, sz, and an array of char of size sz The constructor should set the first sz members of the private data array to the sz members of the argument array of char
Test
NOTES: When you test, you should test with known good values, with data on boundaries and with deliberately bad values You are not required to put checks for index out of bounds errors in your code, but that would be a nice touch Error handling alternatives: Issue an error message then die (that is, call exit(1)) or give the user another chance to make a correct entry
Trang 59 Strings
9.1 AN ARRAY TYPE FOR STRINGS 351
C-String Values and C-String Variables 351 Pitfall: Using = and == with C-strings 355 Other Functions in <cstring> 357 C-String Input and Output 360
9.2 CHARACTER MANIPULATION TOOLS 363
Character I/O 363 The Member Functions get and put 364 Example: Checking Input Using a Newline Function 366 Pitfall: Unexpected ’\n’ in Input 368
The putback , peek , and ignore Member Functions 369 Character-Manipulating Functions 372
Pitfall: toupper and tolower Return int Values 374
9.3 THE STANDARD CLASS string 375 Introduction to the Standard Class string 376 I/O with the Class string 379
Tip: More Versions of getline 382 Pitfall: Mixing cin >> variable ; and getline 383 String Processing with the Class string 384 Example: Palindrome Testing 388
Converting between string Objects and C-Strings 392
CHAPTER SUMMARY 393 ANSWERS TO SELF-TEST EXERCISES 393 PROGRAMMING PROJECTS 397
09_CH09.fm Page 349 Wednesday, August 13, 2003 1:04 PM
Trang 69 Strings
Polonius: What do you read my lord?
Hamlet: Words, words, words
William Shakespeare, Hamlet
INTRODUCTION
This chapter discusses two types whose values represent strings of characters, such as "Hello" One type is just an array with base type char that stores strings of characters in the array and marks the end of the string with the null character, ’\0’ This is the older way of representing strings, which C++ inherited from the C programming language These sorts of strings are called C-strings Although C-strings are an older way of representing strings, it is difficult to
do any sort of string processing in C++ without at least passing contact with C-strings For example, quoted strings, such as "Hello", are implemented as C-strings in C++
The ANSI/ISO C++ standard includes a more modern string handling facility in the form of the class string The class string is the second string type that we will discuss in this chapter The full class string uses templates and so is similar to the template classes in the Standard Template Library (STL) Templates are covered in Chapter 16 and the STL is covered in Chap-ter 19 This chapChap-ter covers basic uses of the class string that do not require a knowledge of templates
This material does not require extensive knowledge of arrays, but you should be familiar with basic array notation, such as a[i] Section 5.1 of Chapter 5 covers more than enough material about arrays to allow you to read the material of this chapter This material also does not require extensive knowledge of classes Section 9.1 on C-strings and Section 9.2 on character manipulation can be covered before Chapters 6, 7, and 8, which cover classes However, before reading Section 9.3 on the standard class string, you should read Chapter 6 and the following parts of Chapter 7: Section 7.1 and the sub-section of Section 7.2 entitled “The const Parameter Modifier” along with its accompanying pitfall section
09_CH09.fm Page 350 Wednesday, August 13, 2003 1:04 PM
Trang 7An Array Type for Strings 351
An Array Type for Strings
In everything one must consider the end.
Jean de La Fontaine, Fables, book III (1668)
This section describes one way to represent strings of characters, which C++ inherited from the C language Section 9.3 describes a string class that is a more modern way to represent strings Although the string type described here may be a bit “old fashioned,”
it is still widely used and is an integral part of the C++ language
■ C-STRING VALUES AND C-STRING VARIABLES
One way to represent a string is as an array with base type char However, if the string
is "Hello", it is handy to represent it as an array of characters with six indexed variables:
five for the five letters in "Hello" plus one for the character ’\0’, which serves as an end marker The character ’\0’ is called the null character and is used as an end marker because it is distinct from all the “real” characters The end marker allows your program to read the array one character at a time and know that it should stop reading when it reads the ’\0’ A string stored in this way (as an array of characters terminated with ’\0’) is called a C-string
We spell ’\0’ with two symbols when we write it in a program, but just like the newline character ’\n’, the character ’\0’ is really only a single character value Like any other character value, ’\0’ can be stored in one variable of type char or one indexed variable of an array of characters
You have already been using C-strings In C++, a literal string, such as "Hello" is stored as a C-string, although you seldom need to be aware of this detail
T HE N ULL C HARACTER , '\0'
The null character, ’\0’ , is used to mark the end of a C-string that is stored in an array of charac-ters When an array of characters is used in this way, the array is often called a C-string variable
Although the null character ’\0’ is written using two symbols, it is a single character that fits in one variable of type char or one indexed variable of an array of characters.
9.1
null character,
’\0’
C-string
Trang 8352 Strings
A C-string variable is just an array of characters Thus, the following array declara-tion provides us with a C-string variable capable of storing a C-string value with nine
or fewer characters:
char s[10];
The 10 is for the 9 letters in the string plus the null character ’\0’ to mark the end of the string
A C-string variable is a partially filled array of characters Like any other partially filled array, a C-string variable uses positions starting at indexed variable 0 through as many as are needed However, a C-string variable does not use an int variable to keep track of how much of the array is currently being used Instead, a string variable places the special symbol ’\0’ in the array immediately after the last character of the C-string
Thus, if s contains the string "Hi Mom!", the array elements are filled as shown below:
The character ’\0’ is used as a sentinel value to mark the end of the C-string If you read the characters in the C-string starting at indexed variable s[0], proceed to s[1], then to s[2], and so forth, you know that when you encounter the symbol ’\0’ you have reached the end of the C-string Since the symbol ’\0’ always occupies one ele-ment of the array, the length of the longest string that the array can hold is one less than the size of the array
The thing that distinguishes a C-string variable from an ordinary array of characters
is that a C-string variable must contain the null character ’\0’ at the end of the C-string value This is a distinction regarding how the array is used rather than a distinction
regarding what the array is A C-string variable is an array of characters, but it is used in a different way.
You can initialize a C-string variable when you declare it, as illustrated by the follow-ing example:
char myMessage[20] = "Hi there.";
Notice that the C-string assigned to the C-string variable need not fill the entire array
When you initialize a C-string variable, you can omit the array size and C++ will automatically make the size of the C-string variable one more than the length of the quoted string (The one extra indexed variable is for ’\0’.) For example:
char shortString[] = "abc";
is equivalent to char shortString[4] = "abc";
C-string
variables
C-string
variables vs.
arrays of
characters
initializing
C-string
variables
09_CH09.fm Page 352 Wednesday, August 13, 2003 1:04 PM
Trang 9Be sure you do not confuse the following initializations:
char shortString[] = "abc";
and char shortString[] = {’a’, ’b’, ’c’};
They are not equivalent The first of these two possible initializations places the null
character ’\0’ in the array after the characters ’a’, ’b’, and ’c’ The second one does not put a ’\0’ anyplace in the array
C-S TRING V ARIABLE D ECLARATION
A C-string variable is the same thing as an array of characters, but it is used differently A C-string variable is declared to be an array of characters in the usual way.
S YNTAX
char Array_Name [ Maximum_C-string_Size + 1];
E XAMPLE
char myCstring[11];
The + 1 allows for the null character ’\0’ , which terminates any C-string stored in the array For example, the C-string variable myCstring in the above example can hold a C-string that is ten
or fewer characters long.
I NITIALIZING A C-S TRING V ARIABLE
A C-string variable can be initialized when it is declared, as illustrated by the following example: char yourString[11] = "Do Be Do";
Initializing in this way automatically places the null character, ’\0’ , in the array at the end of the C-string specified
If you omit the number inside the square brackets, [] , then the C-string variable will be given a size one character longer than the length of the C-string For example, the following declares
myString to have nine indexed variables (eight for the characters of the C-string "Do Be Do"
and one for the null character ’\0’ ):
char myString[] = "Do Be Do";
Trang 10354 Strings
A C-string variable is an array, so it has indexed variables that can be used just like those of any other array For example, suppose your program contains the following C-string variable declaration:
char ourString[5] = "Hi";
With ourString declared as above, your program has the following indexed variables:
ourString[0], ourString[1], ourString[2], ourString[3], and ourString[4] For example, the following will change the C-string value in ourString to a C-string of the same length consisting of all ’X’ characters:
int index = 0;
while (ourString[index] != ’\0’) {
ourString[index] = ’X’;
index++;
}
When manipulating these indexed variables you should be very careful not to replace the null character ’\0’ with some other value If the array loses the value ’\0’ it will no longer behave like a C-string variable For example, the following will change the array happyString so that it no longer contains a C-string:
char happyString[7] = "DoBeDo";
happyString[6] = ’Z’;
After the above code is executed, the array happyString will still contain the six letters
in the C-string "DoBeDo", but happyString will no longer contain the null character
’\0’ to mark the end of the C-string Many string-manipulating functions depend crit-ically on the presence of ’\0’ to mark the end of the C-string value
As another example, consider the above while loop that changes characters in the C-string variable ourString That while loop changes characters until it encounters a
’\0’ If the loop never encounters a ’\0’, then it could change a large chunk of mem-ory to some unwanted values, which could make your program do strange things As a safety feature, it would be wise to rewrite the above while loop as follows, so that if the null character ’\0’ is lost, the loop will not inadvertently change memory locations beyond the end of the array:
int index = 0;
while ( (ourString[index] != ’\0’) && (index < SIZE) ) {
ourString[index] = ’X’;
index++;
} SIZE is a defined constant equal to the declared size of the array ourString
indexed
variables
for C-string
variables
Do not destroy
the ’\0’.