205
Appendix A
Exercise Solutions
Appendix A of Essential C++ by Stanley Lippman
Copyright 2000, Addison Wesley Longman
Stanley Lippman contact information:
homepage: www.objectwrite.com
email: slippman@objectwrite.com
AWL: www.aw.com/cseng/series/indepth
Exercise 1.4
Try to extend the program: (1) Ask the user to enter both a first and last name, and
(2) modify the output to write out both names.
We need two strings for our extended program: one to hold the user’s first name and
a second to hold the user’s last name. By the end of Chapter 1, we know three ways to
support this. We can define two individual string objects:
string first_name, last_name;
We can define an array of two string objects:
string usr_name[ 2 ];
Or we can define a vector of two string objects:
vector<string> usr_name(2);
At this point in the text, arrays and vectors have not yet been introduced, so I’ve
chosen to use the two string objects:
#include <iostream>
#include <string>
using namespace std;
206 Appendix A
int main()
{
string first_name, last_name;
cout << "Please enter your first name: ";
cin >> first_name;
cout << "hi, " << first_name
<< " Please enter your last name: ";
cin >> last_name;
cout << '\n';
<< "Hello, "
<< first_name << ' ' << last_name
<< " ... and goodbye!\n";
}
When compiled and executed, this program generates the following output (my
responses are highlighted in bold):
Please enter your first name: stan
hi, stan Please enter your last name: lippman
Hello, stan lippman ... and goodbye!
Exercise 1.5
Write a program to ask the user his or her name. Read the response. Confirm that the
input is at least two characters in length. If the name seems valid, respond to the us-
er. Provide two implementations: one using a C-style character string, and the other
using a string class object.
The two primary differences between a string class object and a C-style character
string are that (1) the string class object grows dynamically to accommodate its char-
acter string, whereas the C-style character string must be given a fixed size that is
(hopefully) large enough to contain the assigned string, and (2) the C-style character
string does not know its size. To determine the size of the C-style character string, we
must iterate across its elements, counting each one up to but not including the termi-
nating null. The
strlen() standard library routine provides this service for us:
int strlen( const char* );
To use strlen(), we must include the cstring header file.
However, before we get to that, let’s look at the string class implementation. Par-
ticularly for beginners, I recommend that the string class be used in favor of the C-style
character string.
#include <iostream>
#include <string>
using namespace std;
Exercise Solutions 207
int main()
{
string user_name;
cout << "Please enter your name: ";
cin >> user_name;
switch ( user_name.size() ){
case 0:
cout << "Ah, the user with no name. "
<< "Well, ok, hi, user with no name\n";
break;
case 1:
cout << "A 1-character name? Hmm, have you read Kafka?: "
<< "hello, " << user_name << endl;
break;
default:
// any string longer than 1 character
cout << "Hello, " << user_name
<< " -- happy to make your acquaintance!\n";
break;
}
return 0;
}
The C-style character string implementation differs in two ways. First, we must de-
cide on a fixed size to declare
user_name; I’ve arbitrarily chosen 128, which seems more
than adequate. Second, we use the the standard library
strlen() function to discover
the size of
user_name. The cstring header file holds the declaration of strlen(). If the
user enters a string longer than 127 characters, there will be no room for the terminat-
ing null character. To prevent that, I use the
setw() iostream manipulator to guarantee
that we do not read in more than 127 characters. To use the
setw() manipulator, we
must include the
iomanip header file.
#include <iostream>
#include <iomanip>
#include <cstring>
using namespace std;
int main()
{
// must allocate a fixed size
const int nm_size = 128;
char user_name[ nm_size ];
cout << "Please enter your name: ";
cin >> setw( nm_size ) >> user_name;
208 Appendix A
switch ( strlen( user_name ))
{
// same case labels for 0, 1
case 127:
// maybe string was truncated by setw()
cout << "That is a very big name, indeed -- "
<< "we may have needed to shorten it!\n"
<< "In any case,\n";
// no break -- we fall through ...
default:
// the 127 case drops through to here -- no break
cout << "Hello, " << user_name
<< " -- happy to make your acquaintance!\n";
break;
}
return 0;
}
Exercise 1.6
Write a program to read in a sequence of integers from standard input. Place the val-
ues, in turn, in a built-in array and a vector. Iterate over the containers to sum the
values. Display the sum and average of the entered values to standard output.
The built-in array and the vector class differ in primarily the same ways as the C-style
character string (which is implemented as an array of
char elements) and the string
class: (1) The built-in array must be of a fixed size, whereas the vector can grow
dynamically as elements are inserted, and (2) the built-in array does not know its size.
The fixed-size nature of the built-in array means that we must be concerned with
potentially overflowing its boundary. Unlike the C-style string, the built-in array has
no sentinel value (the null) to indicate its end. Particularly for beginners, I recom-
mend that the vector class be used in favor of the built-in array. Here is the program
using the vector class:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> ivec;
int ival;
while ( cin >> ival )
ivec.push_back( ival );
Exercise Solutions 209
// we could have calculated the sum as we entered the
// values, but the idea is to iterate over the vector ...
for ( int sum = 0, ix = 0; ix < ivec.size(); ++ix )
sum += ivec[ ix ];
int average = sum / ivec.size();
cout << "Sum of " << ivec.size()
<< " elements: " << sum
<< ". Average: " << average << endl;
}
The primary difference in the following built-in array implementation is the need
to monitor the number of elements being read to ensure that we don’t overflow the ar-
ray boundary:
#include <iostream>
using namespace std;
int main()
{
const int array_size = 128;
int ia[ array_size ];
int ival, icnt = 0;
while ( cin >> ival &&
icnt < array_size )
ia[ icnt++ ] = ival;
for ( int sum = 0, ix = 0; ix < icnt; ++ix )
sum += ia[ ix ];
int average = sum / icnt;
cout << "Sum of " << icnt
<< " elements: " << sum
<< ". Average: " << average << endl;
}
Exercise 1.7
Using your favorite editor, type two or more lines of text into a file. Write a program to
open the file, reading each word into a
vector<string> object. Iterate over the vector, dis-
playing it to
cout. That done, sort the words using the sort() generic algorithm.
#include <algorithm>
sort( container.begin(), container.end() );
Then print the sorted words to an output file.