C:\s And Settings\administrator\Desktop\cpphtp3e_IM\Frame\cpphtp3_im.ps Solution Manual For C++ How To Program (3e)

User Manual:

Open the PDF directly: View PDF PDF.
Page Count: 577 [warning: Documents this large are best viewed by clicking the View PDF Link!]

©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Instructor’s Manual
for
C++ How to Program, 3/e
Deitel, Deitel & Nieto
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
C++ How to Program: Third Edition
Instructor’s Manual Contents
Preface iii
Chapter 1 Introduction to Computers and C++ Programming: Solutions 1
Chapter 2 Control Structures: Solutions 15
Chapter 3 Functions: Solutions 66
Chapter 4 Arrays Solutions: 120
Chapter 5 Pointers and Strings: Solutions 170
Chapter 6 Classes and Data Abstraction: Solutions 235
Chapter 7 Classes: Part II: Solutions 264
Chapter 8 Operator Overloading: Solutions 276
Chapter 9 Inheritance: Solutions 299
Chapter 10 Virtual Functions and Polymorphism: Solutions 318
Chapter 11 C++ Stream Input/Output: Solutions 333
Chapter 12 Templates: Solutions 348
Chapter 13 Exception Handling: Solutions 359
Chapter 14 File Processing: Solutions 370
Chapter 15 Data Structures: Solutions 390
Chapter 16 Bits, Characters, Strings and Structures: Solutions 498
Chapter 17 The Preprocessor: Solutions 524
Chapter 18 C Legacy Code Topics: Solutions 531
Chapter 19 Class string and String Stream Processing: Solutions 541
Chapter 20 Standard Template Library (STL): Solutions 559
Chapter 21 Standard C++ Language Additions: Solutions 565
Appendix C++ Multimedia Cyber Classroom Solutions Provided on CD 573
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Preface
Thank you for considering and/or adopting our text C++ How to Program: Third Edition. If you have not read
the preface to C++ How to Program: Third Edition, please do so. The preface contains a careful walkthrough of
the book’s key features, including our new Unified Modeling Language (UML) case study, which carefully
introduces the reader to the UML and object-oriented design (OOD). Students are presented with a detailed prob-
lem statement and guided through a simplified, UML-based object-oriented design process. The complete 1000-
line C++ program solution for the case study is presented in the book and provided on the CD-ROM in the back
of the textbook.
We have worked hard to produce a textbook and ancillaries that we hope you and your students will find valu-
able. The following ancillary resources are available:
C++ How to Program: Third Edition’s 250 program examples are included on the CD-ROM in the back
of the textbook. This helps instructors prepare lectures faster and helps students master C++. The examples
are also available for download at www.deitel.com. When extracting the source code from the ZIP file,
you must use a ZIP-file reader such as WinZip (www.winzip.com) or PKZIP (www.pkware.com)
that understands directories. The file should be extracted into a separate directory (e.g.,
cpphtp3e_examples).
Microsoft Visual C++ 6 Introductory Edition software is provided on the textbook’s CD-ROM. This soft-
ware allows students to edit, compile and debug C++ programs. We have provided at no charge a short Vi-
sual C++ 6 tutorial (in Adobe PDF format) on our Web site (www.deitel.com).
This C++ How to Program: Third Edition Instructor’s Manual on CD contains answers to most of the ex-
ercises in the textbook. The programs are separated into directories by chapter and exercise number.
The optional C++ Multimedia Cyber Classroom: Third Edition is an interactive multimedia CD version of
the book for Windows. Its features include audio walkthroughs of programs, section review questions (which
are available only on the C++ Multimedia Cyber Classroom: Third Edition), a text-search engine, the ability
to execute example programs, and more. The Cyber Classroom helps students get more out of their courses.
The Cyber Classroom is also useful for students who miss a lecture and have to catch up quickly. The Cyber
Classroom is available as a stand-alone product (see the last few pages of the textbook for the ISBN number)
or bundled with the textbook (at a discount) in a product called The Complete C++ Training Course: Third
Edition (ISBN# 0-13-089563-6).
Companion Web site (www.prenhall.com/deitel) provides instructor and student resources. In-
structor resources include textbook appendices (e.g., Appendix D, "C++ Internet and Web Resources") and
a syllabus manager for lesson planning. Student resources include chapter objectives, true/false questions,
chapter highlights, reference materials and a message board.
Customizable Powerpoint Instructor Lecture Notes, with many complete features including source code,
and key discussion points for each program and major illustration. These lecture notes are available for in-
structors and students at no charge at our Web site www.deitel.com.
Lab Manual (available Spring 2001)—a for-sale item containing closed-lab sessions.
We would sincerely appreciate your questions, comments, criticisms and corrections addressed to us at:
deitel@deitel.com
IV
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
We will respond immediately. Please read the latest copy of the Deitel Buzz (published every April and
November) for information on forthcoming Deitel publications, ancillaries, product options and ordering infor-
mation. To receive the Deitel Buzz, please contact Jennie Burger (jennie_burger@prenhall.com).
Watch our Deitel & Associates, Inc. Web site (www.deitel.com) and our Prentice Hall Web site
(www.prenhall.com/deitel) for the latest publication updates.
We would like to thank the extraordinary team of publishing professionals at Prentice Hall who made C++
How to Program: Third Edition and its ancillaries possible. Our Computer Science editor, Petra Recter, worked
closely with us to ensure the timely availability and professional quality of these ancillaries.
We would also like to thank two of our student interns—Aftab Bukhari (a Computer Science major at Boston
University) and Jason Rosenfeld (a Computer Science major at Northwestern University) for their assistance in
preparing this Instructor’s Manual.
Harvey M. Deitel
Paul J. Deitel
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1
Introduction to Computers and
C++ Programming
Solutions
SOLUTIONS
1.10 Categorize each of the following items as either hardware or software:
a) CPU
ANS: hardware.
b) C++ compiler
ANS: software.
c) ALU
ANS: hardware.
d) C++ preprocessor
ANS: software.
e) input unit
ANS: hardware.
f) an editor program
ANS: software.
1.11 Why might you want to write a program in a machine-independent language instead of a machine-dependent language?
Why might a machine-dependent language be more appropriate for writing certain types of programs?
ANS: Machine independent languages are useful for writing programs to be executed on multiple computer platforms.
Machine dependent languages are appropriate for writing programs to be executed on a single platform. Machine dependent
languages tend to exploit the efficiencies of a particular machine.
1.12 Fill in the blanks in each of the following statements:
a) Which logical unit of the computer receives information from outside the computer for use by the computer?
.
ANS: input unit.
b) The process of instructing the computer to solve specific problems is called .
ANS: computer programming.
c) What type of computer language uses English-like abbreviations for machine language instructions? .
ANS: high-level language.
d) Which logical unit of the computer sends information that has already been processed by the computer to various de-
vices so that the information may be used outside the computer? .
ANS: output unit.
e) Which logical unit of the computer retains information? .
ANS: memory unit and secondary storage unit.
f) Which logical unit of the computer performs calculations? .
2 Introduction to Computers and C++ Programming Solutions Chapter 1
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
ANS: arithmetic and logical unit.
g) Which logical unit of the computer makes logical decisions? .
ANS: arithmetic and logical unit.
h) The level of computer language most convenient to the programmer for writing programs quickly and easily is
.
ANS: high-level language.
i) The only language that a computer can directly understand is called that computer's .
ANS: machine language.
j) Which logical unit of the computer coordinates the activities of all the other logical
units? .
ANS: central processing unit.
1.13 Discuss the meaning of each of the following objects:
a) cin
ANS: This object refers to the standard input device that is normally connected to the keyboard.
b) cout
ANS: This object refers to the standard output device that is normally connected to the computer screen.
c) cerr
ANS: This object refers to the standard error device that is normally connected to the computer screen.
1.14 Why is so much attention today focused on object-oriented programming in general and C++ in particular?
ANS: Object-oriented programming enables the programmer to build reusable software components that model items in
the real world. Building software quickly, correctly, and economically has been an elusive goal in the software industry.
The modular, object-oriented design and implementation approach has been found to increase productivity 10 to 100 times
over conventional programming languages while reducing development time, errors, and cost. C++ is extremely popular
because it is a superset of the widely used C programming language. Programmers already familiar with C have an easier
time learing C++.
1.15 Fill in the blanks in each of the following:
a) are used to document a program and improve its readability.
ANS: comments
b) The object used to print information on the screen is .
ANS: cout
c) A C++ statement that makes a decision is .
ANS: if
d) Calculations are normally performed by statements.
ANS: assignment
e) The object inputs values from the keyboard.
ANS: cin
1.16 Write a single C++ statement or line that accomplishes each of the following:
a) Print the message "Enter two numbers".
ANS: cout << "Enter two numbers";
b) Assign the product of variables b and c to variable a.
ANS: a = b * c;
c) State that a program performs a sample payroll calculation (i.e., use text that helps to document a program).
ANS: // Sample Payroll Calculation Program
d) Input three integer values from the keyboard and into integer variables a, b and c.
ANS: cin >> a >> b >> c;
1.17 State which of the following are true and which are false. If false, explain your answers.
a) C++ operators are evaluated from left to right.
ANS: False. Some operators are evaluated from left to right, while other operators are evaluated right to left.
b) The following are all valid variable names: _under_bar_, m928134, t5, j7, her_sales,
his_account_total, a, b, c, z, z2.
ANS: True. All variables begin with an underscore or letter.
c) The statement cout << "a = 5;"; is a typical example of an assignment statement.
ANS: False. The statement is an output statement. a = 5; is output to the screen.
d) A valid C++ arithmetic expression with no parentheses is evaluated from left to right.
Chapter 1 Introduction to Computers and C++ Programming Solutions 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
ANS: False. Arithmetic operators can appear in any order in an expression. Since multiplication, division, and modulus
have higher precendence than addition and subtraction the statement cannot be true.
e) The following are all invalid variable names: 3g, 87, 67h2, h22, 2h.
ANS: False. h22 is a valid variable name.
1.18 Fill in the blanks in each of the following:
a) What arithmetic operations are on the same level of precedence as multiplication? .
ANS: division and modulus.
b) When parentheses are nested, which set of parentheses is evaluated first in an arithmetic expression? .
ANS: innermost.
c) A location in the computer's memory that may contain different values at various times throughout the execution of a
program is called a .
ANS: variable.
1.19 What, if anything, prints when each of the following C++ statements is performed? If nothing prints, then answer “nothing.”
Assume x = 2 and y = 3.
a) cout << x;
ANS: 2
b) cout << x + x;
ANS: 4
c) cout << "x=";
ANS: x=
d) cout << "x = " << x;
ANS: x = 2
e) cout << x + y << " = " << y + x;
ANS: 5 = 5
f) z = x + y;
ANS: nothing.
g) cin >> x >> y;
ANS: 23.
h) // cout << "x + y = " << x + y;
ANS: nothing.
i) cout << "\n";
ANS: A newline is output which positions the cursor at the beginning of the next line on the screen.
1.20 Which of the following C++ statements contain variables whose values are replaced?
a) cin >> b >> c >> d >> e >> f;
b) p = i + j + k + 7;
c) cout << "variables whose values are destroyed";
d) cout << "a = 5";
ANS: Parts (a) and (b).
1.21 Given the algebraic equation y = ax3 + 7, which of the following, if any, are correct C++ statements for this equation?
a) y = a * x * x * x + 7;
b) y = a * x * x * ( x + 7 );
c) y = ( a * x ) * x * ( x + 7 );
d) y = (a * x) * x * x + 7;
e) y = a * ( x * x * x ) + 7;
f) y = a * x * ( x * x + 7 );
ANS: Parts (a), (d) and (e).
1.22 State the order of evaluation of the operators in each of the following C++ statements and show the value of x after each
statement is performed.
a) x = 7 + 3 * 6 / 2 - 1;
ANS: *, /, +, -, =, 15
b) x = 2 % 2 + 2 * 2 - 2 / 2;
ANS: %, *, /, +, -, =, 3
c) x = ( 3 * 9 * ( 3 + ( 9 * 3 / ( 3 ) ) ) );
ANS: *, /, +, *, *, 324
4 Introduction to Computers and C++ Programming Solutions Chapter 1
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1.23 Write a program that asks the user to enter two numbers, obtains the two numbers from the user and prints the sum, product,
difference, and quotient of the two numbers.
1.24 Write a program that prints the numbers 1 to 4 on the same line with each pair of adjacent numbers separated by one space.
Write the program using the following methods:
a) Using one output statement with one stream insertion operator.
b) Using one output statement with four stream insertion operators.
c) Using four output statements.
1// Exercise 1.23 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int num1, num2; // declare variables
11
12 cout << "Enter two integers: "; // prompt user
13 cin >> num1 >> num2; // read values from keyboard
14
15 // output the results
16 cout << "The sum is " << num1 + num2
17 << "\nThe product is " << num1 * num2
18 << "\nThe difference is " << num1 - num2
19 << "\nThe quotient is " << num1 / num2 << endl;
20
21 return 0; // indicate successful termination
22 }
Enter two integers: 8 22
The sum is 30
The product is 176
The difference is -14
The quotient is 0
1// Exercise 1.24 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main ()
8{
9 // Part A
10 cout << "1 2 3 4\n";
11
12 // Part B
13 cout << "1 " << "2 " << "3 " << "4\n";
14
15 // Part C
16 cout << "1 ";
17 cout << "2 ";
18 cout << "3 ";
19 cout << "4" << endl;
20
21 return 0;
Chapter 1 Introduction to Computers and C++ Programming Solutions 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1.25 Write a program that asks the user to enter two integers, obtains the numbers from the user, then prints the larger number
followed by the words "is larger." If the numbers are equal, print the message “These numbers are equal.”
1.26 Write a program that inputs three integers from the keyboard and prints the sum, average, product, smallest and largest of
these numbers. The screen dialogue should appear as follows:
22 }
1 2 3 4
1 2 3 4
1 2 3 4
1// Exercise 1.25 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int num1, num2; // declaration
11
12 cout << "Enter two integers: "; // prompt
13 cin >> num1 >> num2; // input to numbers
14
15 if ( num1 == num2 )
16 cout << "These numbers are equal." << endl;
17
18 if ( num1 > num2 )
19 cout << num1 << " is larger." << endl;
20
21 if ( num2 > num1 )
22 cout << num2 << " is larger." << endl;
23
24 return 0;
25 }
Enter two integers: 22 8
22 is larger.
Input three different integers: 13 27 14
Sum is 54
Average is 18
Product is 4914
Smallest is 13
Largest is 27
1// Exercise 1.26 Solution
2#include <iostream>
3
4using std::cout;
6 Introduction to Computers and C++ Programming Solutions Chapter 1
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1.27 Write a program that reads in the radius of a circle and prints the circle’s diameter, circumference and area. Use the constant
value 3.14159 for π. Do these calculations in output statements. (Note: In this chapter, we have discussed only integer constants
and variables. In Chapter 3 we will discuss floating-point numbers, i.e., values that can have decimal points.)
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int num1, num2, num3, smallest, largest; // declaration
11
12 cout << "Input three different integers: "; // prompt
13 cin >> num1 >> num2 >> num3; // input
14
15 largest = num1; // assume first number is largest
16
17 if ( num2 > largest ) // is num2 larger?
18 largest = num2;
19
20 if ( num3 > largest ) // is num3 larger?
21 largest = num3;
22
23 smallest = num1; // assume first number is smallest
24
25 if ( num2 < smallest )
26 smallest = num2;
27
28 if ( num3 < smallest )
29 smallest = num3;
30
31 cout << "Sum is " << num1 + num2 + num3
32 << "\nAverage is " << (num1 + num2 + num3) / 3
33 << "\nProduct is " << num1 * num2 * num3
34 << "\nSmallest is " << smallest
35 << "\nLargest is " << largest << endl;
36
37 return 0;
38 }
Input three different integers: 13 27 14
Sum is 54
Average is 18
Product is 4914
Smallest is 13
Largest is 27
1// Exercise 1.27 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int radius; // declaration
11
12 cout << "Enter the circle radius: "; // prompt
13 cin >> radius; // input
Chapter 1 Introduction to Computers and C++ Programming Solutions 7
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1.28 Write a program that prints a box, an oval, an arrow and a diamond as follows:
1.29 What does the following code print?
cout << "*\n**\n***\n****\n*****\n";
14
15 cout << "Diameter is " << radius * 2.0
16 << "\nCircumference is " << 2 * 3.14159 * radius
17 << "\nArea is " << 3.14159 * radius * radius << endl;
18
19 return 0;
20 }
Enter the circle radius: 8
Diameter is 16
Circumference is 50.2654
Area is 201.062
**************
*********
***********
*******
*******
*******
*******
*******
**************
1// Exercise 1.28 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7main()
8{
9 cout << "********* *** * *\n"
10 << "* * * * *** * *\n"
11 << "* * * * ***** * *\n"
12 << "* * * * * * *\n"
13 << "* * * * * * *\n"
14 << "* * * * * * *\n"
15 << "* * * * * * *\n"
16 << "* * * * * * *\n"
17 << "********* *** * *" << endl;
18
19 return 0;
20 }
8 Introduction to Computers and C++ Programming Solutions Chapter 1
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
ANS:
1.30 Write a program that reads in five integers and determines and prints the largest and the smallest integers in the group. Use
only the programming techniques you learned in this chapter.
*
**
***
****
*****
1// Exercise 1.30 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int num1, num2, num3, num4, num5, largest, smallest;
11
12 cout << "Enter five integers: ";
13 cin >> num1 >> num2 >> num3 >> num4 >> num5;
14
15 largest = num1;
16 smallest = num1;
17
18 if ( num1 > largest )
19 largest = num1;
20
21 if ( num2 > largest )
22 largest = num2;
23
24 if ( num3 > largest )
25 largest = num3;
26
27 if ( num4 > largest )
28 largest = num4;
29
30 if ( num5 > largest )
31 largest = num5;
32
33 if ( num1 < smallest )
34 smallest = num1;
35
36 if ( num2 < smallest )
37 smallest = num2;
38
39 if ( num3 < smallest )
40 smallest = num3;
41
42 if ( num4 < smallest )
43 smallest = num4;
44
45 if ( num5 < smallest )
46 smallest = num5;
47
48 cout << "Largest is " << largest
Chapter 1 Introduction to Computers and C++ Programming Solutions 9
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1.31 Write a program that reads an integer and determines and prints whether it is odd or even. (Hint: Use the modulus operator.
An even number is a multiple of two. Any multiple of two leaves a remainder of zero when divided by 2.)
1.32 Write a program that reads in two integers and determines and prints if the first is a multiple of the second. (Hint: Use the
modulus operator.)
49 << "\nSmallest is " << smallest << endl;
50
51 return 0;
52 }
Enter five integers: 88 22 8 78 21
Largest is 88
Smallest is 8
1// Exercise 1.31 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int num;
11
12 cout << "Enter a number: ";
13 cin >> num;
14
15 if ( num % 2 == 0 )
16 cout << "The number " << num << " is even." << endl;
17
18 if ( num % 2 != 0 )
19 cout << "The number " << num << " is odd." << endl;
20
21 return 0;
22 }
Enter a number: 73
The number 73 is odd.
1// Exercise 1.32 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int num1, num2;
11
12 cout << "Enter two integers: ";
13 cin >> num1 >> num2;
14
15 if ( num1 % num2 == 0 )
16 cout << num1 << " is a multiple of " << num2 << endl;
10 Introduction to Computers and C++ Programming Solutions Chapter 1
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1.33 Display a checkerboard pattern with eight output statements, then display the same pattern with as few output statements
as possible.
17
18 if ( num1 % num2 != 0 )
19 cout << num1 << " is not a multiple of " << num2 << endl;
20
21 return 0;
22 }
Enter two integers: 22 8
22 is not a multiple of 8
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
1// Exercise 1.33 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 // Eight output statements
10 cout << "* * * * * * * *\n";
11 cout << " * * * * * * * *\n";
12 cout << "* * * * * * * *\n";
13 cout << " * * * * * * * *\n";
14 cout << "* * * * * * * *\n";
15 cout << " * * * * * * * *\n";
16 cout << "* * * * * * * *\n";
17 cout << " * * * * * * * *\n\n";
18
19 // One output statement; 3 parts
20 cout << "* * * * * * * *\n * * * * * * * *\n* * * * * * * *\n"
21 << " * * * * * * * *\n* * * * * * * *\n * * * * * * * *\n"
22 << "* * * * * * * *\n * * * * * * * *\n";
23
24 cout << endl; // ensure everything is displayed
25
26 return 0;
27 }
Chapter 1 Introduction to Computers and C++ Programming Solutions 11
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1.34 Distinguish between the terms fatal error and non–fatal error. Why might you prefer to experience a fatal error rather than
a non–fatal error?
ANS: A fatal error causes a program to terminate prematurely. A nonfatal error occurs when the logic of the program is
incorrect, and the program does not work properly. A fatal error is preferred for debugging purposes. A fatal error imme-
diately lets you know there is a problem with the program, whereas a nonfatal error can be subtle and possibly go unde-
tected.
1.35 Here is a peek ahead. In this chapter you learned about integers and the type int. C++ can also represent uppercase letters,
lowercase letters and a considerable variety of special symbols. C++ uses small integers internally to represent each different char-
acter. The set of characters a computer uses and the corresponding integer representations for those characters is called that com-
puter’s character set. You can print a character by simply enclosing that character in single quotes as with
cout << 'A';
You can print the integer equivalent of a character using static_cast as follows:
cout << static_cast< int >( 'A' );
This is called a cast operation (we formally introduce casts in Chapter 2). When the preceding statement executes, it prints the
value 65 (on systems that use the ASCII character set). Write a program that prints the integer equivalents of some uppercase let-
ters, lowercase letters, digits and special symbols. At a minimum, determine the integer equivalents of the following: A B C a b
c 0 1 2 $ * + / and the blank character.
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
1// Exercise 1.35 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 char symbol;
11
12 cout << "Enter a character: ";
13 cin >> symbol;
14
15 cout << symbol << "'s integer equivalent is "
16 << static_cast< int > ( symbol ) << endl;
17
18 return 0;
12 Introduction to Computers and C++ Programming Solutions Chapter 1
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1.36 Write a program that inputs a five-digit number, separates the number into its individual digits and prints the digits sepa-
rated from one another by three spaces each. (Hint: Use the integer division and modulus operators.) For example, if the user types
in 42339 the program should print
19 }
Enter a character: A
A's integer equivalent is 65
4 2 3 3 9
1// Exercise 1.36 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int num;
11
12 cout << "Enter a five-digit number: ";
13 cin >> num;
14
15 cout << num / 10000 << " ";
16 num = num % 10000;
17 cout << num / 1000 << " ";
18 num = num % 1000;
19 cout << num / 100 << " ";
20 num = num % 100;
21 cout << num / 10 << " ";
22 num = num % 10;
23 cout << num << endl;
24
25 return 0;
26 }
Enter a five-digit number: 42339
4 2 3 3 9
Chapter 1 Introduction to Computers and C++ Programming Solutions 13
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1.37 Using only the techniques you learned in this chapter, write a program that calculates the squares and cubes of the numbers
from 0 to 10 and uses tabs to print the following table of values:
number square cube
0 0 0
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
1// Exercise 1.37 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 int num;
10
11 num = 0;
12 cout << "\nnumber\tsquare\tcube\n"
13 << num << '\t' << num * num << '\t' << num * num * num << "\n";
14
15 num = num + 1;
16 cout << num << '\t' << num * num << '\t' << num * num * num << "\n";
17
18 num = num + 1;
19 cout << num << '\t' << num * num << '\t' << num * num * num << "\n";
20
21 num = num + 1;
22 cout << num << '\t' << num * num << '\t' << num * num * num << "\n";
23
24 num = num + 1;
25 cout << num << '\t' << num * num << '\t' << num * num * num << "\n";
26
27 num = num + 1;
28 cout << num << '\t' << num * num << '\t' << num * num * num << "\n";
29
30 num = num + 1;
31 cout << num << '\t' << num * num << '\t' << num * num * num << "\n";
32
33 num = num + 1;
34 cout << num << '\t' << num * num << '\t' << num * num * num << "\n";
35
36 num = num + 1;
37 cout << num << '\t' << num * num << '\t' << num * num * num << "\n";
38
39 num = num + 1;
40 cout << num << '\t' << num * num << '\t' << num * num * num << "\n";
41
42 num = num + 1;
43 cout << num << '\t' << num * num << '\t' << num * num * num << endl;
14 Introduction to Computers and C++ Programming Solutions Chapter 1
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1.38 Give a brief answer to each of the following “object think” questions:
a) Why does this text choose to discuss structured programming in detail before proceeding with an in-depth treatment of
object-oriented programming?
ANS: Objects are composed in part by structured program pieces.
b) What are the typical steps (mentioned in the text) of an object-oriented design process?
ANS: (1) Determine which objects are needed to implement the system. (2) Determine’s each object’s attributes. (3) Deter-
mine each object’s behaviors. (4) Determine the interaction between the objects.
c) How is multiple inheritance exhibited by human beings?
ANS: Children. A child receives genes from both parents.
d) What kinds of messages do people send to one another?
ANS: People send messages through body language, speech, writings, email, telephones, etc.
e) Objects send messages to one another across well-defined interfaces. What interfaces does a car radio (object) present
to its user (a person object)?
ANS: Dials and buttons that allow the user to select a station, adjust the volume, adjust bass and treble, play a CD or tape,
etc.
1.39 You are probably wearing on your wrist one of the world’s most common types of objects—a watch. Discuss how each of
the following terms and concepts applies to the notion of a watch: object, attributes, behaviors, class, inheritance (consider, for ex-
ample, an alarm clock), abstraction, modeling, messages, encapsulation, interface, information hiding, data members and member
functions.
ANS: The entire watch is an object that is composed of many other objects (such as the moving parts, the band, the face,
etc.) Watch attributes are time, color, band, style (digital or analog), etc. The behaviors of the watch include setting the time
and getting the time. A watch can be considered a specific type of clock (as can an alarm clock). With that in mind, it is
possible that a class called Clock could exist from which other classes such as watch and alarm clock can inherit the basic
features in the clock. The watch is an abstraction of the mechanics needed to keep track of the time. The user of the watch
does not need to know the mechanics of the watch in order to use it; the user only needs to know that the watch keeps the
proper time. In this sense, the mechanics of the watch are encapsulated (hidden) inside the watch. The interface to the watch
(its face and controls for setting the time) allows the user to set and get the time. The user is not allowed to directly touch
the internal mechanics of the watch. All interaction with the internal mechanics is controlled by the interface to the watch.
The data members stored in the watch are hidden inside the watch and the member functions (looking at the face to get the
time and setting the time) provide the interface to the data.
44
45 return 0;
46 }
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2
Control
Structures
Solutions
Solutions
Exercises 2.14 through 2.38 correspond to Sections 2.1 through 2.12.
Exercises 2.39 through 2.63 correspond to Sections 2.13 through 2.21.
2.14 Identify and correct the error(s) in each of the following:
a) if ( age >= 65 );
cout << "Age is greater than or equal to 65" << endl;
else
cout << "Age is less than 65 << endl";
ANS: The semicolon at the end of the if should be removed. The closing double quote after the second endl should be
placed after 65.
b) if ( age >= 65 )
cout << "Age is greater than or equal to 65" << endl;
else;
cout << "Age is less than 65 << endl";
ANS: The semicolon after the else should be removed. The closing double quote after the second endl should be placed
after 65.
c) int x = 1, total;
while ( x <= 10 ) {
total += x;
++x;
}
ANS: Variable total should be initialized to 0.
d) While ( x <= 100 )
total += x;
++x;
ANS: The W in while should be lowercase. The while’s body should be enclosed in braces {}.
e) while ( y > 0 ) {
cout << y << endl;
++y;
}
ANS: The variable y should be decremented (i.e., --y;) not incremented ( ++y;).
16 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.15 What does the following program print?
For Exercises 2.16 to 2.19, perform each of these steps:
a) Read the problem statement.
b) Formulate the algorithm using pseudocode and top-down, stepwise refinement.
c) Write a C++ program.
d) Test, debug and execute the C++ program.
1#include <iostream>
2
3using std::cout;
4using std::endl;
5
6int main()
7{
8 int y, x = 1, total = 0;
9
10 while ( x <= 10 ) {
11 y = x * x;
12 cout << y << endl;
13 total += y;
14 ++x;
15 }
16
17 cout << "Total is " << total << endl;
18 return 0;
19 }
1
4
9
16
25
36
49
64
81
100
Total is 385
Chapter 2 Control Structures Solutions 17
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.16 Drivers are concerned with the mileage obtained by their automobiles. One driver has kept track of several tankfuls of gas-
oline by recording miles driven and gallons used for each tankful. Develop a C++ program that will input the miles driven and gal-
lons used for each tankful. The program should calculate and display the miles per gallon obtained for each tankful. After processing
all input information, the program should calculate and print the combined miles per gallon obtained for all tankfuls.
ANS:
Top:
Determine the average miles/gallon for each tank of gas, and the overall miles/gallons for an arbitrary number
of tanks of gas.
First refinement:
Initialize variables.
Input the gallons used and the miles driven, and calculate and print the miles/gallon for each tank of gas. Keep
track of the total miles and total gallons.
Calculate and print the overall average miles/gallon.
Second refinement:
Initialize totalGallons to zero
Initialize totalMiles to zero
Input the gallons used for the first tank
While the sentinel value (-1) has not been entered for the gallons
Add gallons to the running total in totalGallons
Input the miles driven for the current tank
Add miles to the running total in totalMiles
Calculate and print the miles/gallon
Input the gallons used for thenext tank
Print the average miles/gallon
Enter the gallons used (-1 to end): 12.8
Enter the miles driven: 287
The miles / gallon for this tank was 22.421875
Enter the gallons used (-1 to end): 10.3
Enter the miles driven: 200
The miles / gallon for this tank was 19.417475
Enter the gallons used (-1 to end): 5
Enter the miles driven: 120
The miles / gallon for this tank was 24.000000
Enter the gallons used (-1 to end): -1
The overall average miles/gallon was 21.601423
1// Exercise 2.16 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
18 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.17 Develop a C++ program that will determine if a department store customer has exceeded the credit limit on a charge ac-
count. For each customer, the following facts are available:
a) Account number (an integer)
b) Balance at the beginning of the month
c) Total of all items charged by this customer this month
d) Total of all credits applied to this customer's account this month
e) Allowed credit limit
The program should input each of these facts, calculate the new balance (= beginning balance + charges – credits) and deter-
mine if the new balance exceeds the customer's credit limit. For those customers whose credit limit is exceeded, the program
should display the customer's account number, credit limit, new balance and the message “Credit limit exceeded”.
8int main()
9{
10 double gallons, miles, totalGallons = 0.0,
11 totalMiles = 0.0, average;
12
13 cout << "Enter the gallons used (-1 to end): ";
14 cin >> gallons;
15
16 while ( gallons != -1.0 ) {
17 totalGallons += gallons;
18
19 cout << "Enter the miles driven: ";
20 cin >> miles;
21 totalMiles += miles;
22
23 cout << "The Miles / Gallon for this tank was "
24 << miles / gallons
25 << "\n\nEnter the gallons used (-1 to end): ";
26 cin >> gallons;
27 }
28
29 average = totalMiles / totalGallons;
30 cout << "\nThe overall average Miles/Gallon was "
31 << average << endl;
32
33 return 0;
34 }
Enter the gallons used (-1 to end): 16
Enter the miles driven: 220
The Miles / Gallon for this tank was 13.75
Enter the gallons used (-1 to end): 16.5
Enter the miles driven: 272
The Miles / Gallon for this tank was 16.4848
Enter the gallons used (-1 to end): -1
The overall average Miles/Gallon was 15.1385
Chapter 2 Control Structures Solutions 19
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
ANS:
Top:
Determine if each of an arbitrary number of department store customers has exceeded the credit limit on a
charge account.
First refinement:
Input the account number, beginning balance, total charges, total credits, and credit limit for a customer, cal-
culate the customer’s new balance and determine if the balance exceeds the credit limit. Then process the
next customer.
Second refinement:
Input the first customer’s account number
While the sentinel value (-1) has not been entered for the account number
Input the customer’s beginning balance
Input the customer’s total charges
Input the customer’s total credits
Input the customer’s credit limit
Calculate the customer’s new balance
If the balance exceeds the credit limit
Print the account number
Print the credit limit
Print the balance
Print "Credit Limit Exceeded"
Input the next customer’s account number
Enter account number (-1 to end): 100
Enter beginning balance: 5394.78
Enter total charges: 1000.00
Enter total credits: 500.00
Enter credit limit: 5500.00
Account: 100
Credit limit: 5500.00
Balance: 5894.78
Credit Limit Exceeded.
Enter account number (-1 to end): 200
Enter beginning balance: 1000.00
Enter total charges: 123.45
Enter total credits: 321.00
Enter credit limit: 1500.00
Enter account number (-1 to end): 300
Enter beginning balance: 500.00
Enter total charges: 274.73
Enter total credits: 100.00
Enter credit limit: 800.00
Enter account number (-1 to end): -1
20 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1// Exercise 2.17 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setprecision;
12 using std::setiosflags;
13
14 int main()
15 {
16 int accountNumber;
17 double balance, charges, credits, limit;
18
19 cout << "Enter account number (-1 to end): "
20 << setiosflags(ios::fixed | ios::showpoint);
21 cin >> accountNumber;
22
23 while ( accountNumber != -1 ) {
24 cout << "Enter beginning balance: ";
25 cin >> balance;
26 cout << "Enter total charges: ";
27 cin >> charges;
28 cout << "Enter total credits: ";
29 cin >> credits;
30 cout << "Enter credit limit: ";
31 cin >> limit;
32 balance += charges - credits;
33
34 if ( balance > limit )
35 cout << "Account: " << accountNumber
36 << "\nCredit limit: " << setprecision( 2 ) << limit
37 << "\nBalance: " << setprecision( 2 ) << balance
38 << "\nCredit Limit Exceeded.\n";
39
40 cout << "\nEnter account number (-1 to end): ";
41 cin >> accountNumber;
42 }
43
44 cout << endl; // ensure all output is displayed
45
46 return 0;
47 }
Chapter 2 Control Structures Solutions 21
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.18 One large chemical company pays its salespeople on a commission basis. The salespeople receive $200 per week plus 9
percent of their gross sales for that week. For example, a salesperson who sells $5000 worth of chemicals in a week receives $200
plus 9 percent of $5000, or a total of $650. Develop a C++ program that will input each salesperson's gross sales for last week and
calculate and display that salesperson's earnings. Process one salesperson's figures at a time.
ANS:
Top:
For an arbitrary number of salespeople, determine each salesperson’s earnings for the last week.
First refinement:
Initialize variables
Input the salesperson’s sales for the week, calculate and print the salesperson’s wages for the week then
process the next salesperson.
Second refinement:
Input the first salesperson’s sales in dollars
While the sentinel value (-1) has not been entered for the sales
Calculate the salesperson’s wages for the week
Print the salesperson’s wages for the week
Input the next salesperson’s sales in dollars
Enter account number (-1 to end): 88
Enter beginning balance: 900.57
Enter total charges: 324.78
Enter total credits: 100
Enter credit limit: 1500
Enter account number (-1 to end): 89
Enter beginning balance: 2789.65
Enter total charges: 1540.55
Enter total credits: 25
Enter credit limit: 1500
Account: 89
Credit limit: 1500.00
Balance: 4305.20
Credit Limit Exceeded.
Enter account number (-1 to end): -1
Enter sales in dollars (-1 to end): 5000.00
Salary is: $650.00
Enter sales in dollars (-1 to end): 6000.00
Salary is: $740.00
Enter sales in dollars (-1 to end): 7000.00
Salary is: $830.00
Enter sales in dollars (-1 to end): -1
22 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1// Exercise 2.18 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6using std::ios;
7
8#include <iomanip>
9
10 using std::setprecision;
11 using std::setiosflags;
12
13 int main()
14 {
15 double sales, wage;
16
17 cout << "Enter sales in dollars (-1 to end): "
18 << setiosflags( ios::fixed | ios::showpoint );
19 cin >> sales;
20
21 while ( sales != -1.0 ) {
22 wage = 200.0 + 0.09 * sales;
23 cout << "Salary is: $" << setprecision( 2 ) << wage
24 << "\n\nEnter sales in dollars (-1 to end): ";
25 cin >> sales;
26 }
27
28 return 0;
29 }
Enter sales in dollars (-1 to end): 7000
Salary is: $830.00
Enter sales in dollars (-1 to end): 500
Salary is: $245.00
Enter sales in dollars (-1 to end): -1
Chapter 2 Control Structures Solutions 23
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.19 Develop a C++ program that will determine the gross pay for each of several employees. The company pays “straight-time”
for the first 40 hours worked by each employee and pays “time-and-a-half” for all hours worked in excess of 40 hours. You are
given a list of the employees of the company, the number of hours each employee worked last week and the hourly rate of each
employee. Your program should input this information for each employee and should determine and display the employee's gross
pay.
ANS:
Top:
Determine the gross pay for an arbitrary number of employees
Second refinement:
Input the hours worked for the first employee
While the sentinel value (-1) has not been entered for the hours
Input the employee’s hourly rate
If the hours input is less than or equal to 40
Calculate gross pay by multiplying hours worked by hourly rate
Else
Calculate gross pay by multiplying hours worked above forty by 1.5 times the hourly rate and
adding 40 hours worked by the hourly rate.
Display the employee’s gross pay.
Input the hours worked for thenext employee
Print the average miles/gallon
Enter hours worked (-1 to end): 39
Enter hourly rate of the worker ($00.00): 10.00
Salary is $390.00
Enter hours worked (-1 to end): 40
Enter hourly rate of the worker ($00.00): 10.00
Salary is $400.00
Enter hours worked (-1 to end): 41
Enter hourly rate of the worker ($00.00): 10.00
Salary is $415.00
Enter hours worked (-1 to end): -1
1// Exercise 2.19 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6using std::ios;
7
8#include <iomanip>
9
10 using std::setprecision;
11 using std::setiosflags;
12
13 int main()
14 {
15 double hours, rate, salary;
24 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.20 The process of finding the largest number (i.e., the maximum of a group of numbers) is used frequently in computer appli-
cations. For example, a program that determines the winner of a sales contest would input the number of units sold by each sales-
person. The salesperson who sells the most units wins the contest. Write a pseudocode program, then a C++ program that inputs a
series of 10 numbers, and determines and prints the largest of the numbers. Hint: Your program should use three variables, as fol-
lows:
counter: A counter to count to 10 (i.e., to keep track of how many numbers have
been input and to determine when all 10 numbers have been processed).
number: The current number input to the program.
largest: The largest number found so far.
16
17 cout << "Enter hours worked (-1 to end): "
18 << setiosflags( ios::fixed | ios::showpoint );
19 cin >> hours;
20
21 while ( hours != -1.0 ) {
22 cout << "Enter hourly rate of the worker ($00.00): ";
23 cin >> rate;
24
25 if ( hours <= 40 )
26 salary = hours * rate;
27 else
28 salary = 40.0 * rate + ( hours - 40.0 ) * rate * 1.5;
29
30 cout << "Salary is $" << setprecision( 2 ) << salary
31 << "\n\nEnter hours worked (-1 to end): ";
32 cin >> hours;
33 }
34
35 return 0;
36 }
Enter hours worked (-1 to end): 40
Enter hourly rate of the worker ($00.00): 10
Salary is $400.00
Enter hours worked (-1 to end): 50
Enter hourly rate of the worker ($00.00): 10
Salary is $550.00
Enter hours worked (-1 to end): -1
1// Exercise 2.20 solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int counter = 0, number, largest;
11
12 cout << "Enter the first number: ";
13 cin >> largest;
14
15 while ( ++counter < 10 ) {
16 cout << "Enter the next number : ";
Chapter 2 Control Structures Solutions 25
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.21 Write a C++ program that utilizes looping and the tab escape sequence \t to print the following table of values:
17 cin >> number;
18
19 if ( number > largest )
20 largest = number;
21 }
22
23 cout << "Largest is " << largest << endl;
24
25 return 0;
26 }
Enter the first number: 78
Enter the next number : 19
Enter the next number : 99
Enter the next number : 33
Enter the next number : 22
Enter the next number : 10
Enter the next number : 8
Enter the next number : 88
Enter the next number : 22
Enter the next number : 34
Largest is 99
N 10*N 100*N 1000*N
1 10 100 1000
2 20 200 2000
3 30 300 3000
4 40 400 4000
5 50 500 5000
1// Exercise 2.21 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 int n = 0;
10
11 cout << "N\t10 * N\t100 * N\t1000 * N\n\n";
12
13 while ( ++n <= 5 )
14 cout << n << '\t' << 10 * n << '\t' << 100 * n
15 << '\t' << 1000 * n << '\n';
16
17 cout << endl;
18
19 return 0;
20 }
26 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.22 Using an approach similar to Exercise 2.20, find the two largest values among the 10 numbers. Note: You must input each
number only once.
N 10 * N 100 * N 1000 * N
1 10 100 1000
2 20 200 2000
3 30 300 3000
4 40 400 4000
5 50 500 5000
1// Exercise 2.22 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int counter = 0, number, largest, secondLargest = 0;
11
12 cout << "Enter the first number: ";
13 cin >> largest;
14
15 while ( ++counter < 10 ) {
16 cout << "Enter next number: ";
17 cin >> number;
18
19 if ( number > largest ) {
20 secondLargest = largest;
21 largest = number;
22 }
23 else if ( number > secondLargest )
24 secondLargest = number;
25 }
26
27 cout << "\nLargest is " << largest
28 << "\nSecond largest is " << secondLargest << endl;
29
30 return 0;
31 }
Enter the first number: 77
Enter next number: 33
Enter next number: 44
Enter next number: 73
Enter next number: 79
Enter next number: 45
Enter next number: 2
Enter next number: 22
Enter next number: 21
Enter next number: 8
Largest is 79
Second largest is 77
Chapter 2 Control Structures Solutions 27
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.23 Modify the program in Fig. 2.11 to validate its inputs. On any input, if the value entered is other than 1 or 2, keep looping
until the user enters a correct value.
1// Exercise 2.23 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int passes = 0, failures = 0, student = 0, result;
11
12 while ( ++student <= 10 ) {
13 cout << "Enter result (1=pass, 2=fail): ";
14 cin >> result;
15
16 while ( result != 1 && result != 2 ) {
17 cout << "Invalid result"
18 << "\nEnter result (1=pass, 2=fail): ";
19 cin >> result;
20 }
21
22 if ( result == 1 )
23 ++passes;
24 else
25 ++failures;
26 }
27
28 cout << "Passed: " << passes
29 << "\nFailed: " << failures;
30
31 if ( passes >= 8 )
32 cout << "\nRaise tuition\n";
33
34 cout << endl;
35
36 return 0;
37 }
Enter result (1=pass, 2=fail): 1
Enter result (1=pass, 2=fail): 4
Invalid result
Enter result (1=pass, 2=fail): 1
Enter result (1=pass, 2=fail): 1
Enter result (1=pass, 2=fail): 5
Invalid result
Enter result (1=pass, 2=fail): 2
Enter result (1=pass, 2=fail): 1
Enter result (1=pass, 2=fail): 1
Enter result (1=pass, 2=fail): 1
Enter result (1=pass, 2=fail): 2
Enter result (1=pass, 2=fail): 2
Enter result (1=pass, 2=fail): 2
Passed: 6
Failed: 4
28 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.24 What does the following program print?
2.25 What does the following program print?
1#include <iostream>
2
3using std::cout;
4using std::endl;
5
6int main()
7{
8 int count = 1;
9
10 while ( count <= 10 ) {
11 cout << (count % 2 ? "****" : "++++++++")
12 << endl;
13 ++count;
14 }
15
16 return 0;
17 }
****
++++++++
****
++++++++
****
++++++++
****
++++++++
****
++++++++
1#include <iostream>
2
3using std::cout;
4using std::endl;
5
6int main()
7{
8 int row = 10, column;
9
10 while ( row >= 1 ) {
11 column = 1;
12
13 while ( column <= 10 ) {
14 cout << ( row % 2 ? "<" : ">" );
15 ++column;
16 }
17
18 --row;
19 cout << endl;
20 }
21
22 return 0;
23 }
Chapter 2 Control Structures Solutions 29
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.26 (Dangling Else Problem) Determine the output for each of the following when x is 9 and y is 11 and when x is 11 and y
is 9. Note that the compiler ignores the indentation in a C++ program. Also, the C++ compiler always associates an else with the
previous if unless told to do otherwise by the placement of braces {}. Because, on first glance, the programmer may not be sure
which if an else matches, this is referred to as the “dangling else” problem. We have eliminated the indentation from the follow-
ing code to make the problem more challenging. (Hint: Apply indentation conventions you have learned.)
a) if ( x < 10 )
if ( y > 10 )
cout << "*****" << endl;
else
cout << "#####" << endl;
cout << "$$$$$" << endl;
ANS: x = 9, y = 11
b) if ( x < 10 ) {
if ( y > 10 )
cout << "*****" << endl;
}
else {
cout << "#####" << endl;
cout << "$$$$$" << endl;
}
ANS: x = 11, y = 9
2.27 (Another Dangling Else Problem) Modify the following code to produce the output shown. Use proper indentation tech-
niques. You must not make any changes other than inserting braces. The compiler ignores indentation in a C++ program. We have
eliminated the indentation from the following code to make the problem more challenging. Note: It is possible that no modification
is necessary.
if ( y == 8 )
if ( x == 5 )
cout << "@@@@@" << endl;
else
cout << "#####" << endl;
cout << "$$$$$" << endl;
cout << "&&&&&" << endl;
>>>>>>>>>>
<<<<<<<<<<
>>>>>>>>>>
<<<<<<<<<<
>>>>>>>>>>
<<<<<<<<<<
>>>>>>>>>>
<<<<<<<<<<
>>>>>>>>>>
<<<<<<<<<<
*****
$$$$$
#####
$$$$$
30 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
a) Assuming x = 5 and y = 8, the following output is produced.
ANS:
b) Assuming x = 5 and y = 8, the following output is produced.
ANS:
c) Assuming x = 5 and y = 8, the following output is produced.
ANS:
@@@@@
$$$$$
&&&&&
1if ( y == 8 )
2 if ( x == 5 )
3 cout << "@@@@@\n";
4 else
5 cout << "#####\n";
6
7cout << "$$$$$\n";
8cout << "&&&&&\n";
@@@@@
1if ( y == 8 )
2 if ( x == 5 )
3 cout << "@@@@@\n";
4 else {
5 cout << "#####\n";
6 cout << "$$$$$\n";
7 cout << "&&&&&\n";
8 }
@@@@@
&&&&&
1if ( y == 8 )
2 if ( x == 5 )
3 cout << "@@@@@\n";
4 else {
5 cout << "#####\n";
6 cout << "$$$$$\n";
7 }
8
9cout << "&&&&&\n";
Chapter 2 Control Structures Solutions 31
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
d) Assuming x = 5 and y = 7, the following output is produced. Note: The last three output statements after the else are
all part of a compound statement.
ANS:
2.28 Write a program that reads in the size of the side of a square and then prints a hollow square of that size out of asterisks and
blanks. Your program should work for squares of all side sizes between 1 and 20. For example, if your program reads a size of 5, it
should print
#####
$$$$$
&&&&&
1if ( y == 8 ) {
2 if ( x == 5 )
3 cout << "@@@@@\n";
4}
5else {
6 cout << "#####\n";
7 cout << "$$$$$\n";
8 cout << "&&&&&\n";
9}
*****
* *
* *
* *
*****
1// Exercise 2.28 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int side, rowPosition, size;
11
12 cout << "Enter the square side: ";
13 cin >> side;
14
15 size = side;
16
17 while ( side > 0 ) {
18 rowPosition = size;
19
20 while ( rowPosition > 0 ) {
21
22 if ( size == side || side == 1 || rowPosition == 1 ||
23 rowPosition == size )
24
25 cout << '*';
26 else
32 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.29 A palindrome is a number or a text phrase that reads the same backwards as forwards. For example, each of the following
five-digit integers is a palindrome: 12321, 55555, 45554 and 11611. Write a program that reads in a five-digit integer and determines
whether it is a palindrome. (Hint: Use the division and modulus operators to separate the number into its individual digits.)
27 cout << ' ';
28
29 --rowPosition;
30 }
31
32 cout << '\n';
33 --side;
34 }
35
36 cout << endl;
37
38 return 0;
39 }
Enter the square side: 8
********
* *
* *
* *
* *
* *
* *
********
1// Exercise 2.29 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int number, firstDigit, secondDigit, fourthDigit, fifthDigit;
11
12 cout << "Enter a five-digit number: ";
13 cin >> number;
14
15 firstDigit = number / 10000;
16 secondDigit = number % 10000 / 1000;
17 fourthDigit = number % 10000 % 1000 % 100 / 10;
18 fifthDigit = number % 10000 % 1000 % 10;
19
20 if ( firstDigit == fifthDigit && secondDigit == fourthDigit )
21 cout << number << " is a palindrome" << endl;
22 else
23 cout << number << " is not a palindrome" << endl;
24
25 return 0;
26 }
Enter a five-digit number: 57475
57475 is a palindrome
Chapter 2 Control Structures Solutions 33
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.30 Input an integer containing only 0s and 1s (i.e., a “binary” integer) and print its decimal equivalent. (Hint: Use the modulus
and division operators to pick off the “binary” number’s digits one at a time from right to left. Just as in the decimal number system
where the rightmost digit has a positional value of 1 and the next digit left has a positional value of 10, then 100, then 1000, etc., in
the binary number system, the rightmost digit has a positional value of 1, the next digit left has a positional value of 2, then 4, then
8, etc. Thus the decimal number 234 can be interpreted as 4 * 1 + 3 * 10 + 2 * 100. The decimal equivalent of binary 1101 is 1 * 1
+ 0 * 2 + 1 * 4 + 1 * 8 or 1 + 0 + 4 + 8, or 13.)
2.31 Write a program that displays the following checkerboard pattern
1// Exercise 2.30 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int binary, number, decimal = 0, highBit = 16, factor = 10000;
11
12 cout << "Enter a binary number (5 digits maximum): ";
13 cin >> binary;
14
15 number = binary;
16
17 while ( highBit >= 1 ) {
18 decimal += binary / factor * highBit;
19 highBit /= 2;
20 binary %= factor;
21 factor /= 10;
22 }
23
24 cout << "The decimal equivalent of "
25 << number << " is " << decimal << endl;
26
27 return 0;
28 }
Enter a binary number (5 digits maximum): 10010
The decimal equivalent of 10010 is 18
********
********
********
********
********
********
********
********
34 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Your program must use only three output statements, one of each of the following forms:
cout << "* ";
cout << ' ';
cout << endl;
2.32 Write a program that keeps printing the multiples of the integer 2, namely 2, 4, 8, 16, 32, 64, etc. Your loop should not
terminate (i.e., you should create an infinite loop). What happens when you run this program?
1// Exercise 2.31 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 int side = 8, row;
10
11 while ( side-- > 0 ) {
12 row = 8;
13
14 if ( side % 2 == 0 )
15 cout << ' ';
16
17 while ( row-- > 0 )
18 cout << "* ";
19
20 cout << '\n';
21 }
22
23 cout << endl;
24
25 return 0;
26 }
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
1// Exercise 2.32 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 int multiple = 1;
10
11 while ( multiple *= 2 )
12 cout << multiple << "\n";
13
14 cout << endl;
Chapter 2 Control Structures Solutions 35
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.33 Write a program that reads the radius of a circle (as a double value) and computes and prints the diameter, the circumfer-
ence and the area. Use the value 3.14159 for π.
2.34 What's wrong with the following statement? Provide the correct statement to accomplish what the programmer was prob-
ably trying to do.
15
16 return 0;
17 }
2
4
...
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
33554432
67108864
134217728
268435456
536870912
1073741824
-2147483648
1// Exercise 2.33 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 double radius, pi = 3.14159;
11
12 cout << "Enter the radius: ";
13 cin >> radius;
14
15 cout << "The diameter is " << radius * 2.0
16 << "\nThe circumference is " << 2.0 * pi * radius
17 << "\nThe area is " << pi * radius * radius << endl;
18
19 return 0;
20 }
Enter the radius: 5
The diameter is 10
The circumference is 31.4159
The area is 78.5397
36 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
cout << ++( x + y );
ANS: The ++ operator must be used in conjuction with variables. The programmer probably intended to write the state-
ment: cout << x + y + 1;.
2.35 Write a program that reads three nonzero double values and determines and prints if they could represent the sides of a
right triangle.
2.36 Write a program that reads three nonzero integers and determines and prints if they could be the sides of a right triangle.
1// Exercise 2.35 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 double a, b, c;
11
12 cout << "Enter three floating point numbers: ";
13 cin >> a >> b >> c;
14
15 if ( c * c == a * a + b * b )
16 cout << "The three numbers could"
17 << " be sides of a right triangle" << endl;
18 else
19 cout << "The three numbers probably"
20 << " are not the sides of a right triangle" << endl;
21
22 return 0;
23 }
Enter three floating point numbers: 4.5 7.7 6.6
The three numbers probably are not the sides of a right triangle
1// Exercise 2.36 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int a, b, c;
11
12 do {
13 cout << "Enter three integers: ";
14 cin >> a >> b >> c;
15 } while ( a <= 0 || b <= 0 || c <= 0 );
16
17 if ( c * c == a * a + b * b )
18 cout << "The three integers are the"
19 << " sides of a right triangle\n";
20 else
21 cout << "The three integers are not the"
22 << " sides of a right triangle\n";
23
Chapter 2 Control Structures Solutions 37
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.37 A company wants to transmit data over the telephone, but they are concerned that their phones may be tapped. All of their
data are transmitted as four-digit integers. They have asked you to write a program that encrypts their data so that it can be trans-
mitted more securely. Your program should read a four-digit integer and encrypt it as follows: Replace each digit by (the sum of
that digit plus 7) modulus 10. Then, swap the first digit with the third, swap the second digit with the fourth and print the encrypted
integer. Write a separate program that inputs an encrypted four-digit integer and decrypts it to form the original number.
24 cout << endl;
25
26 return 0;
27 }
Enter three integers: 3 4 5
The three integers are the sides of a right triangle
1// Exercise 2.37 Part A Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int first, second, third, fourth, digit, temp;
11 int encryptedNumber;
12
13 cout << "Enter a four digit number to be encrypted: ";
14 cin >> digit;
15
16 first = ( digit / 1000 + 7 ) % 10;
17 second = ( digit % 1000 / 100 + 7 ) % 10;
18 third = ( digit % 1000 % 100 / 10 + 7 ) % 10;
19 fourth = ( digit % 1000 % 100 % 10 + 7 ) % 10;
20
21 temp = first;
22 first = third * 1000;
23 third = temp * 10;
24
25 temp = second;
26 second = fourth * 100;
27 fourth = temp * 1;
28
29 encryptedNumber = first + second + third + fourth;
30 cout << "Encrypted number is " << encryptedNumber << endl;
31
32 return 0;
33 }
Enter a four digit number to be encrypted: 1009
Encrypted number is 7687
1// Exercise 2.37 Part B Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
38 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.38 The factorial of a nonnegative integer n is written n! (pronounced “n factorial”) and is defined as follows:
n! = n · (n - 1) · (n - 2) · … · 1 (for values of n greater than or equal to 1)
and
n! = 1 (for n = 0).
For example, 5! = 5 · 4 · 3 · 2 · 1, which is 120.
a) Write a program that reads a nonnegative integer and computes and prints its factorial.
b) Write a program that estimates the value of the mathematical constant e by using the formula:
c) Write a program that computes the value of ex by using the formula
7
8int main()
9{
10 int first, second, third, fourth, decrypted, temp, num;
11
12 cout << "Enter a four digit encrypted number: ";
13 cin >> num;
14
15 first = num / 1000;
16 second = num % 1000 / 100;
17 third = num % 1000 % 100 / 10;
18 fourth = num % 1000 % 100 % 10;
19
20 temp = ( first + 3 ) % 10;
21 first = ( third + 3 ) % 10;
22 third = temp;
23
24 temp = ( second + 3 ) % 10;
25 second = ( fourth + 3 ) % 10;
26 fourth = temp;
27
28 decrypted = first * 1000 + second * 100 + third * 10 + fourth;
29 cout << "Decrypted number is " << decrypted << endl;
30
31 return 0;
32 }
Enter a four digit encrypted number: 7687
Decrypted number is 1009
e11
1!
----- 1
2!
----- 1
3!
----- ++++=
ex1x
1!
----- x2
2!
----- x3
3!
----- ++++=
1// Exercise 2.38 Part A Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int n = 0, number;
11 unsigned factorial = 1;
12
Chapter 2 Control Structures Solutions 39
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
13 do {
14 cout << "Enter a positive integer: ";
15 cin >> number;
16 } while ( number < 0 );
17
18 while ( n++ < number )
19 factorial *= n == 0 ? 1 : n;
20
21 cout << number << "! is " << factorial << endl;
22
23 return 0;
24 }
Enter a positive integer: 8
8! is 40320
1// Exercise 2.38 Part B Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 int n = 0, fact = 1, accuracy = 10;
10 double e = 1;
11
12 while ( ++n < accuracy ) {
13 fact *= n;
14 e += 1.0 / fact;
15 }
16
17 cout << "e is " << e << endl;
18
19 return 0;
20 }
e is 2.71828
1// Exercise 2.38 Part C Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10 using std::setw;
11 using std::setprecision;
12 using std::setiosflags;
13
14 int main()
15 {
16 int n = 0, accuracy = 15, x = 3.0, times = 0, count;
17 double e = 1.0, exp = 0.0, fact = 1.0;
18
40 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.39 Find the error(s) in each of the following:
a) For ( x = 100, x >= 1, x++ )
cout << x << endl;
ANS: For should be for. The commas should be semicolons. The ++ should be a decrement such as --.
b) The following code should print whether integer value is odd or even:
switch ( value % 2 ) {
case 0:
cout << "Even integer" << endl;
case 1:
cout << "Odd integer" << endl;
}
ANS: case 0 needs a break statement.
c) The following code should output the odd integers from 19 to 1:
for ( x = 19; x >= 1; x += 2 )
cout << x << endl;
ANS: += should be -=.
d) The following code should output the even integers from 2 to 100:
counter = 2;
do {
cout << counter << endl;
counter += 2;
} While ( counter < 100 );
ANS: While should be while. Operator < should be <=.
2.40 Write a program that sums a sequence of integers. Assume that the first integer read specifies the number of values remain-
ing to be entered. Your program should read only one value per input statement. A typical input sequence might be
5 100 200 300 400 500
where the 5 indicates that the subsequent 5 values are to be summed.
19 while ( n++ <= accuracy ) {
20 count = n;
21 fact *= n == 0 ? 1.0 : n;
22
23 while ( times < count ) {
24
25 if ( times == 0 )
26 exp = 1.0;
27
28 exp *= x;
29 ++times;
30 }
31
32 e += exp / fact;
33 }
34
35 cout << setiosflags( ios::fixed | ios::showpoint )
36 << "e raised to the " << x << " power is "
37 << setprecision( 4 ) << e << endl;
38
39 return 0;
40 }
e raised to the 3 power is 20.0855
Chapter 2 Control Structures Solutions 41
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.41 Write a program that calculates and prints the average of several integers. Assume the last value read is the sentinel 9999.
A typical input sequence might be
10 8 11 7 9 9999
indicating that the average of all the values preceding 9999 is to be calculated.
1// Exercise 2.40 Solution
2#include <iostream>
3
4
5using std::cout;
6using std::endl;
7using std::cin;
8
9int main()
10 {
11 int sum = 0, number, value;
12
13 cout << "Enter the number of values to be processed: ";
14 cin >> number;
15
16 for ( int i = 1; i <= number; i++ ) {
17 cout << "Enter a value: ";
18 cin >> value;
19 sum += value;
20 }
21
22 cout << "Sum of the " << number << " values is "
23 << sum << endl;
24
25 return 0;
26 }
Enter the number of values to be processed: 3
Enter a value: 7
Enter a value: 8
Enter a value: 9
Sum of the 3 values is 24
1// Exercise 2.41 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int value, count = 0, total = 0;
11
12 cout << "Enter an integer (9999 to end): ";
13 cin >> value;
14
15 while ( value != 9999 ) {
16 total += value;
17 ++count;
42 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.42 What does the following program do?
18 cout << "Enter next integer (9999 to end): ";
19 cin >> value;
20 }
21
22 if ( count != 0 )
23 cout << "\nThe average is: "
24 << static_cast< double > ( total ) / count << endl;
25 else
26 cout << "\nNo values were entered." << endl;
27
28 return 0;
29 }
Enter an integer (9999 to end): 88
Enter next integer (9999 to end): 65
Enter next integer (9999 to end): 77
Enter next integer (9999 to end): 43
Enter next integer (9999 to end): 90
Enter next integer (9999 to end): 45
Enter next integer (9999 to end): 76
Enter next integer (9999 to end): 2
Enter next integer (9999 to end): 9999
The average is: 60.75
1#include <iostream>
2
3using std::cout;
4using std::cin;
5using std::endl;
6
7int main()
8{
9 int x, y;
10
11 cout << "Enter two integers in the range 1-20: ";
12 cin >> x >> y;
13
14 for ( int i = 1; i <= y; i++ ) {
15
16 for ( int j = 1; j <= x; j++ )
17 cout << '@';
18
19 cout << endl;
20 }
21
22 return 0;
23 }
Enter two integers in the range of 1-20: 3 4
@@@
@@@
@@@
@@@
Chapter 2 Control Structures Solutions 43
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.43 Write a program that finds the smallest of several integers. Assume that the first value read specifies the number of values
remaining and that the first number is not one of the integers to compare.
2.44 Write a program that calculates and prints the product of the odd integers from 1 to 15.
1// Exercise 2.43 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int number, value, smallest;
11
12 cout << "Enter the number of integers to be processed: ";
13 cin >> number;
14 cout << "Enter an integer: ";
15 cin >> smallest;
16
17 for ( int i = 2; i <= number; i++ ) {
18 cout << "Enter next integer: ";
19 cin >> value;
20
21 if ( value < smallest )
22 smallest = value;
23 }
24
25 cout << "\nThe smallest integer is: " << smallest << endl;
26
27 return 0;
28 }
Enter the number of integers to be processed: 5
Enter an integer: 5
Enter next integer: 4
Enter next integer: 3
Enter next integer: 1
Enter next integer: 8
The smallest integer is: 1
1// Exercise 2.44 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 long product = 1;
10
11 for ( long i = 3; i <= 15; i += 2 )
12 product *= i;
13
14 cout << "Product of the odd integers from 1 to 15 is: "
15 << product << endl;
16
44 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.45 The factorial function is used frequently in probability problems. The factorial of a positive integer n (written n! and pro-
nounced “n factorial”) is equal to the product of the positive integers from 1 to n. Write a program that evaluates the factorials of
the integers from 1 to 5. Print the results in tabular format. What difficulty might prevent you from calculating the factorial of 20?
2.46 Modify the compound interest program of Section 2.15 to repeat its steps for interest rates of 5 percent, 6 percent, 7 percent,
8 percent, 9 percent and 10 percent. Use a for loop to vary the interest rate.
17 return 0;
18 }
Product of the odd integers from 1 to 15 is: 2027025
1// Exercise 2.45 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 int factorial;
10
11 cout << "X\tFactorial of X\n";
12
13 for ( int i = 1; i <= 5; ++i ) {
14 factorial = 1;
15
16 for ( int j = 1; j <= i; ++j )
17 factorial *= j;
18
19 cout << i << '\t' << factorial << '\n';
20 }
21
22 cout << endl;
23 return 0;
24 }
X Factorial of X
1 1
2 2
3 6
4 24
5 120
1// Exercise 2.46 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setw;
12 using std::setprecision;
Chapter 2 Control Structures Solutions 45
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.47 Write a program that prints the following patterns separately one below the other. Use for loops to generate the patterns.
All asterisks (*) should be printed by a single statement of the form cout << '*'; (this causes the asterisks to print side by
side). Hint: The last two patterns require that each line begin with an appropriate number of blanks. Extra credit: Combine your code
from the four separate problems into a single program that prints all four patterns side by side by making clever use of nested for
loops.
(A) (B) (C) (D)
**********************
**********************
**********************
**********************
**********************
**********************
**********************
**********************
**********************
**********************
13 using std::setiosflags;
14
15 #include <cmath>
16
17 int main()
18 {
19 double amount, principal = 1000.00;
20
21 cout << setiosflags( ios::fixed | ios::showpoint );
22
23 for ( int rate = 5; rate <= 10; rate++ ) {
24 cout << "Interest Rate: " << setprecision( 2 ) << rate / 100.0
25 << "\nYear\tAmount on deposit\n";
26
27 for ( int year = 1; year <= 10; year++ ) {
28 amount = principal * pow( 1 + ( rate / 100.0 ), year );
29 cout << year << '\t' << setprecision( 2 ) << amount << '\n';
30 }
31
32 cout << '\n';
33 }
34
35 cout << endl;
36
37 return 0;
38 }
...
Interest Rate: 0.10
Year Amount on deposit
1 1100.00
2 1210.00
3 1331.00
4 1464.10
5 1610.51
6 1771.56
7 1948.72
8 2143.59
9 2357.95
10 2593.74
46 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1// Exercise 2.47 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 // Pattern A
10 for ( int row = 1; row <= 10; ++row ) {
11
12 for ( int col = 1; col <= row; ++col )
13 cout << '*';
14
15 cout << '\n';
16 }
17
18 cout << '\n';
19
20 // Pattern B
21 for ( row = 10; row >= 1; --row ) {
22
23 for ( int col = 1; col <= row; ++col )
24 cout << '*';
25
26 cout << '\n';
27 }
28
29 cout << '\n';
30
31 // Pattern C
32 for ( row = 10; row >= 1; --row ) {
33
34 for ( int space = 1; space <= 10 - row; ++space )
35 cout << ' ';
36
37 for ( int col = 1; col <= row; ++col )
38 cout << '*';
39
40 cout << '\n';
41 }
42
43 cout << '\n';
44
45 // Pattern D
46 for ( row = 1; row <= 10; ++row ) {
47
48 for ( int space = 1; space <= 10 - row; ++space )
49 cout << ' ';
50
51 for ( int col = 1; col <= row; ++col )
52 cout << '*';
53
54 cout << '\n';
55 }
56
57 cout << endl;
58
59 return 0;
Chapter 2 Control Structures Solutions 47
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
60 }
*
**
***
****
*****
******
*******
********
*********
**********
**********
*********
********
*******
******
*****
****
***
**
*
**********
*********
********
*******
******
*****
****
***
**
*
*
**
***
****
*****
******
*******
********
*********
**********
1// Exercise 2.47 Extra Credit Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 int row, column, space;
10
11 for ( row = 1; row <= 10; ++row ) {
12
13 // part a
14 for ( column = 1; column <= row; ++column )
48 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.48 One interesting application of computers is drawing graphs and bar charts (sometimes called “histograms”). Write a pro-
gram that reads five numbers (each between 1 and 30). For each number read, your program should print a line containing that num-
ber of adjacent asterisks. For example, if your program reads the number seven, it should print *******.
15 cout << '*';
16
17 for ( space = 1; space <= 10 - row; ++space )
18 cout << ' ';
19
20 cout << '\t';
21
22 // part b
23 for ( column = 10; column >= row; --column )
24 cout << '*';
25
26 for ( space = 1; space < row; ++space )
27 cout << ' ';
28
29 cout << '\t';
30
31 // part c
32 for ( space = 10; space > row; --space )
33 cout << ' ';
34
35 for ( column = 1; column <= row; ++column )
36 cout << '*';
37
38 cout << '\t';
39
40 // part d
41 for ( space = 1; space < row; ++space )
42 cout << ' ';
43
44 for ( column = 10; column >= row; --column )
45 cout << '*';
46
47 cout << endl;
48 }
49
50 return 0;
51 }
* ********** * **********
** ********* ** *********
*** ******** *** ********
**** ******* **** *******
***** ****** ***** ******
****** ***** ****** *****
******* **** ******* ****
******** *** ******** ***
********* ** ********* **
********** * ********** *
1// Exercise 2.48 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
Chapter 2 Control Structures Solutions 49
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.49 A mail order house sells five different products whose retail prices are product 1 — $2.98, product 2—$4.50, product 3—
$9.98, product 4—$4.49 and product 5—$6.87. Write a program that reads a series of pairs of numbers as follows:
a) Product number
b) Quantity sold for one day
Your program should use a switch statement to help determine the retail price for each product. Your program should calculate
and display the total retail value of all products sold last week.
7
8int main()
9{
10 int number;
11
12 cout << "Enter 5 numbers between 1 and 30: ";
13
14 for ( int i = 1; i <= 5; ++i ) {
15 cin >> number;
16
17 for ( int j = 1; j <= number; ++j )
18 cout << '*';
19
20 cout << '\n';
21 }
22
23 cout << endl;
24
25 return 0;
26 }
Enter 5 numbers between 1 and 30: 16 12 8 27 9
****************
************
********
***************************
*********
1// Exercise 2.49 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setprecision;
12 using std::setiosflags;
13
14 int main()
15 {
16 int product, quantity;
17 double total = 0.0;
18
19 cout << "Enter pairs of item numbers and quantities."
20 << "\nEnter -1 for the item number to end input: ";
21 cin >> product;
22
23 while ( product != -1 ) {
24 cin >> quantity;
50 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.50 Modify the program of Fig. 2.22 so that it calculates the grade-point average for the class. A grade of ‘A’ is worth 4 points,
‘B’ is worth 3 points, etc.
25
26 switch ( product ) {
27 case 1:
28 total += quantity * 2.98;
29 break;
30 case 2:
31 total += quantity * 4.50;
32 break;
33 case 3:
34 total += quantity * 9.98;
35 break;
36 case 4:
37 total += quantity * 4.49;
38 break;
39 case 5:
40 total += quantity * 6.87;
41 break;
42 default:
43 cout << "Invalid product code: " << product
44 << "\n Quantity: " << quantity << '\n';
45 break;
46 }
47
48 cout << "Enter pairs of item numbers and quantities.\n"
49 << "Enter -1 for the item number to end input: ";
50 cin >> product;
51 }
52
53 cout << setiosflags( ios::fixed | ios::showpoint )
54 << "The total retail value was: " << setprecision( 2 )
55 << total << endl;
56
57 return 0;
58 }
Enter pairs of item numbers and quantities.
Enter -1 for the item number to end input: 2 10
Enter pairs of item numbers and quantities.
Enter -1 for the item number to end input: 1 5
Enter pairs of item numbers and quantities.
Enter -1 for the item number to end input: -1
The total retail value was: 59.90
1// Exercise 2.50 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <iomanip>
9
10 using std::setw;
11 using std::setprecision;
12 using std::setiosflags;
13
Chapter 2 Control Structures Solutions 51
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
14 int main()
15 {
16 int grade, gradeTotal = 0, gradeCount, aCount = 0,
17 bCount = 0, cCount = 0, dCount = 0, fCount = 0;
18
19 cout << "Enter the letter grades."
20 << "\nEnter the EOF character to end input.\n"
21 << setiosflags(ios::fixed | ios::showpoint);
22
23 while ( ( grade = cin.get() ) != EOF ) {
24
25 switch ( grade ) {
26 case 'A': case 'a':
27 gradeTotal += 4;
28 ++aCount;
29 break;
30 case 'B': case 'b':
31 gradeTotal += 3;
32 ++bCount;
33 break;
34 case 'C': case 'c':
35 gradeTotal += 2;
36 ++cCount;
37 break;
38 case 'D': case 'd':
39 ++gradeTotal;
40 ++dCount;
41 break;
42 case 'F': case 'f':
43 ++fCount;
44 break;
45 case ' ': case '\n':
46 break;
47 default:
48 cout << "Incorrect letter grade entered."
49 << " Enter a new grade.\n";
50 break;
51 }
52 }
53
54 gradeCount = aCount + bCount + cCount + dCount + fCount;
55
56 if ( gradeCount != 0 )
57 cout << "\nThe class average is: " << setprecision( 1 )
58 << static_cast< double > ( gradeTotal ) / gradeCount
59 << endl;
60
61 return 0;
62 }
Enter the letter grades.
Enter the EOF character to end input.
aABcccBbDf
E
Incorrect letter grade entered. Enter a new grade.
F
The class average is: 2.2
52 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.51 Modify the program in Fig. 2.21 so it uses only integers to calculate the compound interest. (Hint: Treat all monetary
amounts as integral numbers of pennies. Then “break” the result into its dollar portion and cents portion by using the division and
modulus operations. Insert a period.)
2.52 Assume i = 1, j = 2, k = 3 and m = 2. What does each of the following statements print? Are the parentheses necessary
in each case?
a) cout << ( i == 1 ) << endl;
ANS: 1, no.
b) cout << ( j == 3 ) << endl;
ANS: 1, no.
c) cout << ( i >= 1 && j < 4 ) << endl;
ANS: 1, no.
d) cout << ( m <= 99 && k < m ) << endl;
ANS: 0, no.
1// Exercise 2.51 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <iomanip>
8using std::setw;
9
10 #include <cmath>
11
12 int main()
13 {
14 int amount, principal = 1000, dollars, cents;
15 double rate = .05;
16
17 cout << "Year" << setw( 24 ) << "Amount on deposit\n";
18
19 for ( int year = 1; year <= 10; ++year ) {
20 amount = principal * pow( 1.0 + rate, year );
21 cents = amount % 100;
22 dollars = amount; // assignment truncates decimal places
23 cout << setw( 4 ) << year << setw( 21 ) << dollars << '.';
24
25 if ( cents < 10 )
26 cout << '0' << cents << endl;
27 else
28 cout << cents << endl;
29 }
30
31 return 0;
32 }
Year Amount on deposit
1 1050.50
2 1102.02
3 1157.57
4 1215.15
5 1276.76
6 1340.40
7 1407.07
8 1477.77
9 1551.51
10 1628.28
Chapter 2 Control Structures Solutions 53
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
e) cout << ( j >= i || k == m ) << endl;
ANS: 1, no.
f) cout << ( k + m < j || 3 - j >= k ) << endl;
ANS: 0, no.
g) cout << ( !m ) << endl;
ANS: 0, no.
h) cout << ( !( j - m ) ) << endl;
ANS: 1, yes. The inner pair of parentheses are required.
i) cout << ( !( k > m ) ) << endl;
ANS: 0, yes. The inner pair of parentheses are required.
2.53 Write a program that prints a table of the binary, octal and hexadecimal equivalents of the decimal numbers in the range 1
through 256. If you are not familiar with these number systems, read Appendix C first.
1// Exercise 2.53 Solution
2// The oct, hex, and dec identifiers are stream manipulators
3// like endl that are defined in Chapter 11. The manipulator
4// oct causes integers to be output in octal, the manipulator
5// hex causes integers to be output in hexadecimal, and the manipulator
6// dec causes integers to be output in decimal.
7#include <iostream>
8
9using std::cout;
10 using std::endl;
11 using std::oct;
12 using std::hex;
13 using std::dec;
14
15 int main()
16 {
17 cout << "Decimal\t\tBinary\t\t\tOctal\tHexadecimal\n";
18
19 for ( int loop = 1; loop <= 256; ++loop ) {
20 cout << dec << loop << "\t\t";
21
22 // Output binary number
23 int number = loop;
24 cout << ( number == 256 ? '1' : '0' );
25 int factor = 256;
26
27 do {
28 cout << ( number < factor && number >= ( factor / 2 ) ? '1' : '0' );
29 factor /= 2;
30 number %= factor;
31 } while ( factor > 2 );
32
33 // Output octal and hexadecimal numbers
34 cout << '\t' << oct << loop << '\t' << hex << loop << endl;
35 }
36
37 return 0;
38 }
54 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.54 Calculate the value of π from the infinite series
Print a table that shows the value of π approximated by 1 term of this series, by two terms, by three terms, etc. How many terms of
this series do you have to use before you first get 3.14? 3.141? 3.1415? 3.14159?
Decimal Binary Octal Hexadecimal
1 00000000 1 1
2 00000001 2 2
...
245 01111010 365 f5
246 01111011 366 f6
247 01111011 367 f7
248 01111100 370 f8
249 01111100 371 f9
250 01111101 372 fa
251 01111101 373 fb
252 01111110 374 fc
253 01111110 375 fd
254 01111111 376 fe
255 01111111 377 ff
256 10000000 400 100
π44
3
---4
5
--- 4
7
---4
9
--- 4
11
------
+++=
1// Exercise 2.54 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::ios;
7
8#include <iomanip>
9
10 using std::setprecision;
11 using std::setiosflags;
12
13 int main()
14 {
15 long double pi = 0.0, num = 4.0, denom = 1.0;
16 long accuracy = 4; // set decimal accuracy
17
18 cout << setiosflags( ios::fixed | ios::showpoint )
19 << "Accuracy set at: " << accuracy
20 << "\nterm\t\t pi\n";
21
22 for ( long loop = 1; loop <= accuracy; ++loop ) {
23
24 if ( loop % 2 != 0 )
25 pi += num / denom;
26 else
27 pi -= num / denom;
28
29 cout << loop << "\t\t" << setprecision( 8 ) << pi << '\n';
30 denom += 2.0;
31 }
32
33 cout << endl;
34
Chapter 2 Control Structures Solutions 55
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.55 (Pythagorean Triples) A right triangle can have sides that are all integers. The set of three integer values for the sides of a
right triangle is called a Pythagorean triple. These three sides must satisfy the relationship that the sum of the squares of two of the
sides is equal to the square of the hypotenuse. Find all Pythagorean triples for side1, side2 and hypotenuse all no larger than
500. Use a triple-nested for-loop that tries all possibilities. This is an example of “brute force” computing. You will learn in more
advanced computer science courses that there are many interesting problems for which there is no known algorithmic approach oth-
er than using sheer brute force.
35 return 0;
36 }
Accuracy set at: 400000
term pi
1 4.00000000
2 2.66666667
3 3.46666667
4 2.89523810
...
236138 3.14158999
236139 3.14159531
236140 3.14159000
...
1// Exercise 2.55 Solution
2#include<iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 int count = 0;
10 long int hyptSquared, sidesSquared;
11
12 for ( long side1 = 1; side1 <= 500; ++side1 ) {
13
14 for ( long side2 = 1; side2 <= 500; ++side2 ) {
15
16 for ( long hypt = 1; hypt <= 500; ++hypt ) {
17 hyptSquared = hypt * hypt;
18 sidesSquared = side1 * side1 + side2 * side2;
19
20 if ( hyptSquared == sidesSquared ) {
21 cout << side1 << '\t' << side2 << '\t'
22 << hypt << '\n';
23 ++count;
24 }
25 }
26 }
27 }
28
29 cout << "A total of " << count << " triples were found." << endl;
30
31 return 0;
32 }
56 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.56 A company pays its employees as managers (who receive a fixed weekly salary), hourly workers (who receive a fixed hour-
ly wage for up to the first 40 hours they work and “time-and-a-half,” i.e., 1.5 times their hourly wage, for overtime hours worked),
commission workers (who receive $250 plus 5.7% of their gross weekly sales), or pieceworkers (who receive a fixed amount of
money per item for each of the items they produce—each pieceworker in this company works on only one type of item). Write a
program to compute the weekly pay for each employee. You do not know the number of employees in advance. Each type of em-
ployee has its own pay code: Managers have paycode 1, hourly workers have code 2, commission workers have code 3 and piece-
workers have code 4. Use a switch to compute each employee’s pay based on that employee’s paycode. Within the switch,
prompt the user (i.e., the payroll clerk) to enter the appropriate facts your program needs to calculate each employee’s pay based on
that employee’s paycode.
...
476 93 485
480 31 481
480 88 488
480 108 492
480 140 500
483 44 485
A total of 772 triples were found.
1// Exercise 2.56 Solution
2#include<iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include<iomanip>
10
11 using std::setprecision;
12 using std::setiosflags;
13
14 int main()
15 {
16 int payCode, managers = 0, hWorkers = 0, cWorkers = 0;
17 int pWorkers = 0, pieces;
18 double mSalary, hSalary, cSalary, pSalary, hours;
19 double pay;
20
21 cout << "Enter paycode (-1 to end): "
22 << setiosflags( ios::fixed | ios::showpoint );
23 cin >> payCode;
24
25 while ( payCode != -1 ) {
26 switch ( payCode ) {
27 case 1:
28 cout << "Manager selected."
29 << "\nEnter weekly salary: ";
30 cin >> mSalary;
31 cout << "The manager's pay is $ "
32 << setprecision( 2 ) << mSalary;
33 ++managers;
34 break;
35 case 2:
36 cout << "Hourly worker selected.\n"
37 << "Enter the hourly salary: ";
38 cin >> hSalary;
39 cout << "Enter the total hours worked: ";
40 cin >> hours;
Chapter 2 Control Structures Solutions 57
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
41
42 pay = hours > 40.0 ? ( hours - 40 ) * 1.5 * hSalary + hSalary * 40.0:
43 hSalary * hours;
44
45 cout << "Worker's pay is $ " << setprecision( 2 ) << pay << '\n';
46 ++hWorkers;
47 break;
48 case 3:
49 cout << "Commission worker selected.\n"
50 << "Enter gross weekly sales: ";
51 cin >> cSalary;
52 pay = 250.0 + 0.057 * cSalary;
53 cout << "Commission Worker's pay is $ " << setprecision( 2 )
54 << pay << '\n';
55 ++cWorkers;
56 break;
57 case 4:
58 cout << "Piece worker selected.\n"
59 << "Enter number of pieces: ";
60 cin >> pieces;
61 cout << "Enter wage per piece: ";
62 cin >> pSalary;
63 pay = pieces * pSalary;
64 cout << "Piece Worker's pay is $ " << setprecision( 2 )
65 << pay << '\n';
66 ++pWorkers;
67 break;
68 default:
69 cout << "Invalid pay code.\n";
70 break;
71 }
72
73 cout << "\nEnter paycode (-1 to end): ";
74 cin >> payCode;
75 }
76
77 cout << "\n\nTotal number of managers paid : "
78 << managers
79 << "\nTotal number of hourly workers paid : "
80 << hWorkers
81 << "\nTotal number of commission workers paid: "
82 << cWorkers
83 << "\nTotal number of piece workers paid : "
84 << pWorkers << endl;
85
86 return 0;
87 }
58 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.57 (De Morgan’s Laws) In this chapter, we discussed the logical operators &&, || and !. De Morgan’s Laws can sometimes
make it more convenient for us to express a logical expression. These laws state that the expression !(condition1 && condition2)
is logically equivalent to the expression (!condition1 || !condition2). Also, the expression !(condition1 || condition2) is log-
ically equivalent to the expression (!condition1 && !condition2). Use De Morgan’s Laws to write equivalent expressions for each
of the following, then write a program to show that both the original expression and the new expression in each case are equivalent:
a) !( x < 5 ) && !( y >= 7 )
b) !( a == b ) || !( g != 5 )
c) !( ( x <= 8 ) && ( y > 4 ) )
d) !( ( i > 4 ) || ( j <= 6 ) )
Enter paycode (-1 to end): 3
Commission worker selected.
Enter gross weekly sales: 4000
Commission Worker's pay is $ 478.00
Enter paycode (-1 to end): 2
Hourly worker selected.
Enter the hourly salary: 4.50
Enter the total hours worked: 20
Worker's pay is $ 90.00
Enter paycode (-1 to end): 4
Piece worker selected.
Enter number of pieces: 50
Enter wage per piece: 3
Piece Worker's pay is $ 150.00
Enter paycode (-1 to end): -1
Total number of managers paid : 0
Total number of hourly workers paid : 1
Total number of commission workers paid: 1
Total number of piece workers paid : 1
1// Exercise 2.57 Solution
2#include<iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 int x = 10, y = 1, a = 3, b = 3,
10 g = 5, Y = 1, i = 2, j = 9;
11
12 cout << "current variable values are:" << endl
13 << "x = " << x << ", y = " << y << ", a = " << a
14 << ", b = " << b << endl << "g = " << g << ", Y = "
15 << Y << ", i = " << i << ", j = " << j << "\n\n";
16
17 if ((!(x < 5) && !(y >= 7)) && (!((x < 5) || (y >= 7))))
18 cout << "!(x < 5) && !(y >= 7) is equivalent to"
19 << " !((x < 5) || (y >= 7))" << endl;
20 else
21 cout << "!(x < 5) && !(y >= 7) is not equivalent to"
22 << " !((x < 5) || (y >= 7))" << endl;
23
24 if ((!(a == b) || !(g != 5)) && (!((a == b) && (g != 5))))
Chapter 2 Control Structures Solutions 59
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.58 Write a program that prints the following diamond shape. You may use output statements that print either a single asterisk
(*) or a single blank. Maximize your use of repetition (with nested for structures) and minimize the number of output statements.
25 cout << "!(a == b) || !(g != 5) is equivalent to"
26 << " !((a == b) && (g != 5))" << endl;
27 else
28 cout << "!(a == b) || !(g != 5) is not equivalent to"
29 << " !((a == b) && (g != 5))" << endl;
30
31 if (!((x <= 8) && (Y > 4)) && (!((x <= 8) || (Y > 4))))
32 cout << "!((x <= 8) && (Y > 4)) is equivalent to"
33 << " !((x <= 8) || (Y > 4))" << endl;
34 else
35 cout << "!((x <= 8) && (Y > 4)) is not equivalent to"
36 << " !((x <= 8) || (Y > 4))" << endl;
37
38 if (!((i > 4) || (j <= 6)) && !((i > 4) && (j <= 6)))
39 cout << "!((i > 4) || (j <= 6)) is equivalent to"
40 << " !((i > 4) && (j <= 6))" << endl;
41 else
42 cout << "!((i > 4) || (j <= 6)) is not equivalent to"
43 << " !((i > 4) && (j <= 6))" << endl;
44
45 return 0;
46 }
current variable values are:
x = 10, y = 1, a = 3, b = 3
g = 5, Y = 1, i = 2, j = 9
!(x < 5) && !(y >= 7) is equivalent to !((x < 5) || (y >= 7))
!(a == b) || !(g != 5) is equivalent to !((a == b) && (g != 5))
!((x <= 8) && (Y > 4)) is equivalent to !((x <= 8) || (Y > 4))
!((i > 4) || (j <= 6)) is equivalent to !((i > 4) && (j <= 6))
*
***
*****
*******
*********
*******
*****
***
*
1// Exercise 2.58 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 // top half
10 for ( int row = 1; row <= 5; ++row ) {
11
60 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.59 Modify the program you wrote in Exercise 2.58 to read an odd number in the range 1 to 19 to specify the number of rows
in the diamond. Your program should then display a diamond of the appropriate size.
12 for ( int space = 1; space <= 5 - row; ++space )
13 cout << ' ';
14
15 for ( int asterisk = 1; asterisk <= 2 * row - 1; ++asterisk )
16 cout << '*';
17
18 cout << '\n';
19 }
20
21 // bottom half
22 for ( row = 4; row >= 1; --row ) {
23
24 for ( int space = 1; space <= 5 - row; ++space )
25 cout << ' ';
26
27 for ( int asterisk = 1; asterisk <= 2 * row - 1; ++asterisk )
28 cout << '*';
29
30 cout << '\n';
31 }
32
33 cout << endl;
34
35 return 0;
36 }
*
***
*****
*******
*********
*******
*****
***
*
1// Exercise 2.59 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
10 int size;
11
12 cout << "Enter an odd number for the diamond size (1-19): \n";
13 cin >> size;
14
15 // top half
16 for ( int rows = 1; rows <= size - 2; rows += 2 ) {
17
18 for ( int space = ( size - rows ) / 2; space > 0; --space )
19 cout << ' ';
20
Chapter 2 Control Structures Solutions 61
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.60 A criticism of the break statement and the continue statement is that each is unstructured. Actually break statements
and continue statements can always be replaced by structured statements, although doing so can be awkward. Describe in general
how you would remove any break statement from a loop in a program and replace that statement with some structured equivalent.
(Hint: The break statement leaves a loop from within the body of the loop. The other way to leave is by failing the loop-continu-
ation test. Consider using in the loop-continuation test a second test that indicates “early exit because of a ‘break’ condition.”) Use
the technique you developed here to remove the break statement from the program of Fig. 2.26.
21 for ( int asterisk = 1; asterisk <= rows; ++asterisk )
22 cout << '*';
23
24 cout << '\n';
25 }
26
27 // bottom half
28 for ( rows = size; rows >= 0; rows -= 2 ) {
29
30 for ( int space = ( size - rows ) / 2; space > 0; --space )
31 cout << ' ';
32
33 for ( int asterisk = 1; asterisk <= rows; ++asterisk )
34 cout << '*';
35
36 cout << '\n';
37 }
38
39 cout << endl;
40
41 return 0;
42 }
Enter an odd number for the diamond size (1-19):
15
*
***
*****
*******
*********
***********
*************
***************
*************
***********
*********
*******
*****
***
*
1// Exercise 2.60 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 bool breakOut = false;
10 int x;
11
62 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.61 What does the following program segment do?
2.62 Describe in general how you would remove any continue statement from a loop in a program and replace that statement
with some structured equivalent. Use the technique you developed here to remove the continue statement from the program of
Fig. 2.27.
12 for ( x = 1; x <= 10 && !breakOut; ++x ) {
13
14 if ( x == 4 )
15 breakOut = true;
16
17 cout << x << ' ';
18 }
19
20 cout << "\nBroke out of loop at x = " << x << endl;
21
22 return 0;
23 }
1 2 3 4
Broke out of loop at x = 5
1for ( i = 1; i <= 5; i++ ) {
2 for ( j = 1; j <= 3; j++ ) {
3 for ( k = 1; k <= 4; k++ )
4 cout << '*';
5 cout << endl;
6 }
7 cout << endl;
8}
****
****
****
****
****
****
****
****
****
****
****
****
****
****
****
1// Exercise 2.62 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
Chapter 2 Control Structures Solutions 63
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
2.63 (“The Twelve Days of Christmas” Song) Write a program that uses repetition and switch structures to print the song “The
Twelve Days of Christmas.” One switch structure should be used to print the day (i.e., “First,” “Second,” etc.). A separate
switch structure should be used to print the remainder of each verse.
6
7int main()
8{
9 for ( int x = 1; x <= 10; ++x ) {
10
11 if ( x == 5 )
12 ++x;
13
14 cout << x << ' ';
15 }
16
17 cout << "\nUsed ++x to skip printing the value 5" << endl;
18
19 return 0;
20 }
1 2 3 4 6 7 8 9 10
Used ++x to skip printing the value 5
1// Exercise 2.63 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 for ( int day = 1; day < 13; day++ ) {
10 cout << "On the ";
11
12 switch ( day ) { // switch for current day
13 case 1:
14 cout << "first";
15 break;
16 case 2:
17 cout << "second";
18 break;
19 case 3:
20 cout << "third";
21 break;
22 case 4:
23 cout << "fourth";
24 break;
25 case 5:
26 cout << "fifth";
27 break;
28 case 6:
29 cout << "sixth";
30 break;
31 case 7:
32 cout << "seventh";
33 break;
34 case 8:
35 cout << "eighth";
36 break;
64 Control Structures Solutions Chapter 2
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
37 case 9:
38 cout << "nineth";
39 break;
40 case 10:
41 cout << "tenth";
42 break;
43 case 11:
44 cout << "eleventh";
45 break;
46 case 12:
47 cout << "twelfth";
48 break;
49 }
50
51 cout << " day of Christmas,\nMy true love sent to me:\n";
52
53 switch ( day ) { // switch for gifts
54 case 12:
55 cout << "\tTwelve drummers drumming,\n";
56 case 11:
57 cout << "\tEleven pipers piping,\n";
58 case 10:
59 cout << "\tTen lords a-leaping,\n";
60 case 9:
61 cout << "\tNine ladies dancing,\n";
62 case 8:
63 cout << "\tEight maids a-milking,\n";
64 case 7:
65 cout << "\tSeven swans a-swimming,\n";
66 case 6:
67 cout << "\tSix geese a-laying,\n";
68 case 5:
69 cout << "\tFive golden rings,\n";
70 case 4:
71 cout << "\tFour calling birds,\n";
72 case 3:
73 cout << "\tThree French hens,\n";
74 case 2:
75 cout << "\tTwo turtle doves, and\n";
76 case 1:
77 cout << "A partridge in a pear tree.\n\n\n";
78 }
79 }
80
81 cout << endl;
82
83 return 0;
84 }
Chapter 2 Control Structures Solutions 65
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Exercise 2.64 corresponds to Section 2.22, “Thinking About Objects.”
2.64 Describe in 200 words or less what an automobile is and does. List the nouns and verbs separately. In the text, we stated
that each noun might correspond to an object that will need to be built to implement a system, in this case a car. Pick five of the
objects you listed, and, for each, list several attributes and several behaviors. Describe briefly how these objects interact with one
another and other objects in your description. You have just performed several of the key steps in a typical object-oriented design.
ANS:
A specific type of vehicle containing 4 wheels, doors, seats, windows, steering wheel, brakes, radio, engine, exhaust
system, transmission, axels, windshield, mirrors, etc.
A car can accelerate, decelerate, turn, move forward, move backward, stop, etc.
Wheels:
Attributes: size, type, tread depth.
Behaviors: rotate forward, rotate backward.
Doors:
Attributes: type (passenger, trunk, etc.), open or closed.
Behaviors: open, close, lock, unlock.
Steering Wheel:
Attributes: adjustible.
Behaviors: turn left, turn right, adjust up, adjust down.
Brakes:
Attributes: pressed or not pressed, pressure of press.
Behaviors: press, antilock.
Engine:
Attributes: cylinders, radiator, timing belts, spark plugs, etc.
Behaviors: accelerate, decelerate, turn on, turn off.
Interactions:
Person turns the steering wheel which causes the wheels to turn in the appropriate direction.
Person presses the accelerator pedal which causes the engine revolutions per minute to increase, resulting in a faster
rotation of the wheels.
Person opens door. Person closes door.
Person releases accelerator pedal which causes engine RPMs to decrease, resulting in a slower rotation of the wheels.
Person presses brake pedal which causes brakes to be applied to wheels slows the rotation of thewheels.
2.65 (Peter Minuit Problem) Legend has it that in 1626 Peter Minuit purchased Manhattan for $24.00 in barter. Did he make a
good investment? To answer this question, modify the compound interest program of Fig. 2.21 to begin with a principal of $24.00
and to calculate the amount of interest on deposit if that money had been kept on deposit until this year (374 years through 2000).
Run the program with interest rates of 5%, 6%, 7%, 8%, 9% and 10% to observe the wonders of compound interest.
...
Three French hens,
Two turtle doves, and
A partridge in a pear tree.
On the twelfth day of Christmas,
My true love sent to me:
Twelve drummers drumming,
Eleven pipers piping,
Ten lords a-leaping,
Nine ladies dancing,
Eight maids a-milking,
Seven swans a-swimming,
Six geese a-laying,
Five golden rings,
Four calling birds,
Three French hens,
Two turtle doves, and
A partridge in a pear tree.
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3
Functions
Solutions
Solutions
3.11 Show the value of x after each of the following statements is performed:
a) x = fabs( 7.5 );
ANS: 7.5
b) x = floor( 7.5 );
ANS: 7.0
c) x = fabs( 0.0 );
ANS: 0.0
d) x = ceil( 0.0 );
ANS: 0.0
e) x = fabs( -6.4 );
ANS: 6.4
f) x = ceil( -6.4 );
ANS: -6.0
g) x = ceil( -fabs( -8 + floor( -5.5 ) ) );
ANS: -14.0
3.12 A parking garage charges a $2.00 minimum fee to park for up to three hours. The garage charges an additional $0.50 per
hour for each hour or part thereof in excess of three hours. The maximum charge for any given 24-hour period is $10.00. Assume
that no car parks for longer than 24 hours at a time. Write a program that will calculate and print the parking charges for each of 3
customers who parked their cars in this garage yesterday. You should enter the hours parked for each customer. Your program
should print the results in a neat tabular format and should calculate and print the total of yesterday's receipts. The program should
use the function calculateCharges to determine the charge for each customer. Your outputs should appear in the following
format:
Car Hours Charge
1 1.5 2.00
2 4.0 2.50
3 24.0 10.00
TOTAL 29.5 14.50
Chapter 3 Functions Solutions 67
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1// Exercise 3.12 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setw;
12 using std::setprecision;
13 using std::setiosflags;
14
15 #include <cmath>
16
17 double calculateCharges( double );
18
19 main()
20 {
21 double hour, currentCharge, totalCharges = 0.0, totalHours = 0.0;
22 int first = 1;
23
24 cout << "Enter the hours parked for 3 cars: ";
25
26 for ( int i = 1; i <= 3; i++ ) {
27 cin >> hour;
28 totalHours += hour;
29
30 if ( first ) {
31 cout << setw( 5 ) << "Car" << setw( 15 ) << "Hours"
32 << setw( 15 ) << "Charge\n";
33 first = 0; // prevents this from printing again
34 }
35
36 totalCharges += ( currentCharge = calculateCharges( hour ) );
37 cout << setiosflags( ios::fixed | ios::showpoint )
38 << setw( 3 ) << i << setw( 17 ) << setprecision( 1 ) << hour
39 << setw( 15 ) << setprecision( 2 ) << currentCharge << "\n";
40 }
41
42 cout << setw( 7 ) << "TOTAL" << setw( 13 ) << setprecision( 1 )
43 << totalHours << setw( 15 ) << setprecision( 2 )
44 << totalCharges << endl;
45
46
47 return 0;
48 }
49
50 double calculateCharges( double hours )
51 {
52 double charge;
53
54 if ( hours < 3.0 )
55 charge = 2.0;
56 else if ( hours < 19.0 )
57 charge = 2.0 + .5 * ceil( hours - 3.0 );
58 else
59 charge = 10.0;
60
61 return charge;
68 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.13 An application of function floor is rounding a value to the nearest integer. The statement
y = floor( x + .5 );
will round the number x to the nearest integer and assign the result to y. Write a program that reads several numbers and uses the
preceding statement to round each of these numbers to the nearest integer. For each number processed, print both the original num-
ber and the rounded number.
62 }
Enter the hours parked for 3 cars: 1 2 3
Car Hours Charge
1 1.0 2.00
2 2.0 2.00
3 3.0 2.00
TOTAL 6.0 6.00
1// Exercise 3.13 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setprecision;
12 using std::setiosflags;
13
14 #include <cmath>
15
16 void roundToIntegers( void );
17
18 int main()
19 {
20 roundToIntegers();
21
22 return 0;
23 }
24
25 void roundToIntegers( void )
26 {
27 double x, y;
28
29 cout << setiosflags( ios::fixed | ios::showpoint );
30
31 for ( int loop = 1; loop <= 5; loop++ ) {
32 cout << "Enter a number: ";
33 cin >> x;
34 y = floor( x + .5 );
35 cout << x << " rounded is " << setprecision( 1 ) << y << endl;
36 }
37 }
Chapter 3 Functions Solutions 69
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.14 Function floor can be used to round a number to a specific decimal place. The statement
y = floor( x * 10 + .5 ) / 10;
rounds x to the tenths position (the first position to the right of the decimal point). The statement
y = floor( x * 100 + .5 ) / 100;
rounds x to the hundredths position (the second position to the right of the decimal point). Write a program that defines four func-
tions to round a number x in various ways:
a) roundToInteger( number )
b) roundToTenths( number )
c) roundToHundredths( number )
d) roundToThousandths( number )
For each value read, your program should print the original value, the number rounded to the nearest integer, the number
rounded to the nearest tenth, the number rounded to the nearest hundredth and the number rounded to the nearest thousandth.
Enter a number: 8.22
8.220000 rounded is 8.0
Enter a number: 7.98
8.0 rounded is 8.0
Enter a number: 4.52
4.5 rounded is 5.0
Enter a number: 6.9999
7.0 rounded is 7.0
Enter a number: 3.345
3.3 rounded is 3.0
1// Exercise 3.14 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6using std::ios;
7
8#include <iomanip>
9
10 using std::setprecision;
11 using std::setiosflags;
12 using std::resetiosflags;
13
14 #include <cmath>
15
16 double roundToInteger( double );
17 double roundToTenths( double );
18 double roundToHundreths( double );
19 double roundToThousandths( double );
20
21 int main()
22 {
23 int count;
24 double number;
25
26 cout << "How many numbers do you want to process? "
27 << setiosflags( ios::fixed );
28 cin >> count;
29
30 for ( int i = 0; i < count; ++i ) {
31 cout << "\nEnter number: ";
70 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.15 Answer each of the following questions.
a) What does it mean to choose numbers “at random?”
ANS: Every number has an equal chance of being chosen at any time.
b) Why is the rand function useful for simulating games of chance?
ANS: Because it produces a sequence of pseudo-random numbers that when scaled appear to be random.
c) Why would you randomize a program by using srand? Under what circumstances is it desirable not to randomize?
ANS: The sequence of numbers produced by the random number generator differ each time function srand is called. Not
randomizing is useful for debugging purposes—the programmer knows the sequence of numbers.
d) Why is it often necessary to scale and/or shift the values produced by rand?
ANS: To produce random values in a specific range.
e) Why is computerized simulation of real-world situations a useful technique?
ANS: It enables more accurate predictions of random events such as cars arriving at a toll booth, people arriving in lines,
birds arriving at a tree, etc. The results of a simulation can help determine how many toll booths to have open or how many
cashiers to have open at specified times.
32 cin >> number;
33 cout << number << " rounded to the nearest integer is: "
34 << setprecision( 0 ) << roundToInteger( number ) << '\n'
35 << setiosflags( ios::showpoint )
36 << number << " rounded to the nearest tenth is: "
37 << setprecision( 1 ) << roundToTenths( number ) << '\n'
38 << number << " rounded to the nearest hundredth is: "
39 << setprecision( 2 ) << roundToHundreths( number ) << '\n'
40 << number << " rounded to the nearest thousandth is: "
41 << setprecision( 3 ) << roundToThousandths( number ) << '\n'
42 << resetiosflags( ios::showpoint );
43 }
44
45 return 0;
46 }
47
48 double roundToInteger( double n )
49 {
50 return floor( n + .5 );
51 }
52
53 double roundToTenths( double n )
54 {
55 return floor( n * 10 + .5 ) / 10;
56 }
57
58 double roundToHundreths( double n )
59 {
60 return floor( n * 100 + .5 ) / 100;
61 }
62
63 double roundToThousandths( double n )
64 {
65 return floor( n * 1000 + .5 ) / 1000.0;
66 }
How many numbers do you want to process? 1
Enter number: 2.564
2.564000 rounded to the nearest integer is: 3
3. rounded to the nearest tenth is: 2.6
2.6 rounded to the nearest hundredth is: 2.56
2.56 rounded to the nearest thousandth is: 2.564
Chapter 3 Functions Solutions 71
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.16 Write statements that assign random integers to the variable n in the following ranges:
a) 1 n 2
ANS: n = 1 + rand() % 2;
b) 1 n 100
ANS: n = 1 + rand() % 100;
c) 0 n 9
ANS: n = rand() % 10;
d) 1000 n 1112
ANS: n = 1000 + rand() % 13;
e) –1 n 1
ANS: n = rand() % 3 - 1;
f) –3 n 11
ANS: n = rand() % 15 - 3;
3.17 For each of the following sets of integers, write a single statement that will print a number at random from the set.
a) 2, 4, 6, 8, 10.
ANS: cout << 2 * ( 1 + rand() % 5 ) ) << ’\n’;
b) 3, 5, 7, 9, 11.
ANS: cout << 1 + 2 * ( 1 + rand() % 5 ) ) << ’\n’;
c) 6, 10, 14, 18, 22.
ANS: cout << 6 + 4 * ( rand() % 5 ) << ’\n’;
3.18 Write a function integerPower( base, exponent ) that returns the value of
base exponent
For example, integerPower( 3, 4 ) = 3 * 3 * 3 * 3. Assume that exponent is a positive, nonzero integer and that
base is an integer. The function integerPower should use for or while to control the calculation. Do not use any math
library functions.
ANS:
1// Exercise 3.18 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int integerPower( int, int );
9
10 int main()
11 {
12 int exp, base;
13
14 cout << "Enter base and exponent: ";
15 cin >> base >> exp;
16 cout << base << " to the power " << exp << " is: "
17 << integerPower( base, exp ) << endl;
18
19 return 0;
20 }
21
22 int integerPower( int b, int e )
23 {
24 int product = 1;
25
26 for ( int i = 1; i <= e; ++i )
27 product *= b;
72 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.19 Define a function hypotenuse that calculates the length of the hypotenuse of a right triangle when the other two sides
are given. Use this function in a program to determine the length of the hypotenuse for each of the following triangles. The function
should take two arguments of type double and return the hypotenuse as a double.
28
29 return product;
30 }
Enter base and exponent: 5 2
5 to the power 2 is: 25
Triangle Side 1 Side 2
1 3.0 4.0
2 5.0 12.0
3 8.0 15.0
1// Exercise 3.19 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setprecision;
12 using std::setiosflags;
13
14 #include <cmath>
15
16 double hypotenuse( double, double );
17
18 int main()
19 {
20 double side1, side2;
21
22 cout << setiosflags( ios::fixed | ios::showpoint );
23
24 for ( int i = 1; i <= 3; ++i ) {
25 cout << "\nEnter 2 sides of right triangle: ";
26 cin >> side1 >> side2;
27 cout << "Hypotenuse: " << setprecision( 1 )
28 << hypotenuse( side1, side2 ) << endl;
29 }
30
31 return 0;
32 }
33
34 double hypotenuse( double s1, double s2 )
35 {
36 return sqrt( s1 * s1 + s2 * s2 );
37 }
Chapter 3 Functions Solutions 73
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.20 Write a function multiple that determines for a pair of integers whether the second integer is a multiple of the first. The
function should take two integer arguments and return true if the second is a multiple of the first, false otherwise. Use this func-
tion in a program that inputs a series of pairs of integers.
Enter 2 sides of right triangle: 4 5
Hypotenuse: 6.4
Enter 2 sides of right triangle: 3 4
Hypotenuse: 5.0
Enter 2 sides of right triangle: 12 7
Hypotenuse: 13.9
1// Exercise 3.20 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8bool multiple( int, int );
9
10 int main()
11 {
12 int x, y;
13
14 for ( int i = 1; i <= 3; ++i ) {
15 cout << "Enter two integers: ";
16 cin >> x >> y;
17
18 if ( multiple( x, y ) )
19 cout << y << " is a multiple of " << x << "\n\n";
20 else
21 cout << y << " is not a multiple of " << x << "\n\n";
22 }
23
24 cout << endl;
25
26 return 0;
27 }
28
29 bool multiple( int a, int b )
30 {
31 return !( b % a );
32 }
Enter two integers: 3 4
4 is not a multiple of 3
Enter two integers: 12 3
3 is not a multiple of 12
Enter two integers: 3 12
12 is a multiple of 3
74 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.21 Write a program that inputs a series of integers and passes them one at a time to function even, which uses the modulus
operator to determine whether an integer is even. The function should take an integer argument and return true if the integer is
even and false otherwise.
3.22 Write a function that displays at the left margin of the screen a solid square of asterisks whose side is specified in integer
parameter side. For example, if side is 4, the function displays
1// Exercise 3.21 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8bool even( int );
9
10 int main()
11 {
12 int x;
13
14 for ( int i = 1; i <= 3; ++i ) {
15 cout << "Enter an integer: ";
16 cin >> x;
17
18 if ( even( x ) )
19 cout << x << " is an even integer\n\n";
20 else
21 cout << x << " is an odd integer\n\n";
22 }
23
24 cout << endl;
25
26 return 0;
27 }
28
29 bool even( int a )
30 {
31 return !( a % 2 );
32 }
Enter an integer: 8
8 is an even integer
Enter an integer: 3
3 is an odd integer
Enter an integer: 99
99 is an odd integer
****
****
****
****
Chapter 3 Functions Solutions 75
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1// Exercise 3.22 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8void square( int );
9
10 int main()
11 {
12 int side;
13
14 cout << "Enter side: ";
15 cin >> side;
16 cout << '\n';
17
18 square( side );
19
20 cout << endl;
21
22 return 0;
23 }
24
25 void square( int s )
26 {
27 for ( int row = 1; row <= s; ++row ) {
28
29 for ( int col = 1; col <= s; ++col )
30 cout << '*';
31
32 cout << '\n';
33 }
34 }
Enter side: 8
********
********
********
********
********
********
********
********
76 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.23 Modify the function created in Exercise 3.22 to form the square out of whatever character is contained in character param-
eter fillCharacter. Thus, if side is 5 and fillCharacter is “#,” then this function should print
3.24 Use techniques similar to those developed in Exercises 3.22 and 3.23 to produce a program that graphs a wide range of
shapes.
#####
#####
#####
#####
#####
1// Exercise 3.23 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8void square( int, char );
9
10 int main()
11 {
12 int s;
13 char c;
14
15 cout << "Enter a character and the side length: ";
16 cin >> c >> s;
17 cout << '\n';
18
19 square( s, c );
20
21 cout << endl;
22
23 return 0;
24 }
25
26 void square( int side, char fillCharacter )
27 {
28 for ( int row = 1; row <= side; ++row ) {
29
30 for ( int col = 1; col <= side; ++col )
31 cout << fillCharacter;
32
33 cout << '\n';
34 }
35 }
Enter a character and the side length: H 5
HHHHH
HHHHH
HHHHH
HHHHH
HHHHH
Chapter 3 Functions Solutions 77
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.25 Write program segments that accomplish each of the following:
a) Calculate the integer part of the quotient when integer a is divided by integer b.
b) Calculate the integer remainder when integer a is divided by integer b.
c) Use the program pieces developed in a) and b) to write a function that inputs an integer between 1 and 32767 and
prints it as a series of digits, each pair of which is separated by two spaces. For example, the integer 4562 should be
printed as
4 5 6 2
1// Exercise 3.25 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <iomanip>
9
10 using std::setw;
11
12 int quotient( int, int );
13 int remainder( int, int );
14
15 int main()
16 {
17 int number, divisor = 10000;
18
19 cout << "Enter an integer between 1 and 32767: ";
20 cin >> number;
21
22 cout << "The digits in the number are:\n";
23
24 while ( number >= 1 ) {
25
26 if ( number >= divisor ) {
27 cout << setw( 3 ) << quotient( number, divisor );
28 number = remainder( number, divisor );
29 divisor = quotient( divisor, 10 );
30 }
31 else
32 divisor = quotient( divisor, 10 );
33 }
34
35 cout << endl;
36
37 return 0;
38 }
39
40 // Part A: determine quotient using integer division
41 int quotient( int a, int b )
42 {
43 return a / b;
44 }
45
46 // Part B: determine remainder using the modulus operator
47 int remainder( int a, int b )
48 {
49 return a % b;
78 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.26 Write a function that takes the time as three integer arguments (for hours, minutes and seconds), and returns the number of
seconds since the last time the clock “struck 12.” Use this function to calculate the amount of time in seconds between two times,
both of which are within one 12-hour cycle of the clock.
3.27 Implement the following integer functions:
a) Function celsius returns the Celsius equivalent of a Fahrenheit temperature.
b) Function fahrenheit returns the Fahrenheit equivalent of a Celsius temperature.
50 }
Enter an integer between 1 and 32767: 6758
The digits in the number are:
6 7 5 8
1// Exercise 3.26 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8unsigned seconds( unsigned, unsigned, unsigned );
9
10 int main()
11 {
12 unsigned hours, minutes, secs, temp;
13
14 cout << "Enter the first time as three integers: ";
15 cin >> hours >> minutes >> secs;
16
17 temp = seconds( hours, minutes, secs );
18
19 cout << "Enter the second time as three integers: ";
20 cin >> hours >> minutes >> secs;
21
22 cout << "The difference between the times is "
23 << seconds( hours, minutes, secs ) - temp
24 << " seconds" << endl;
25
26 return 0;
27 }
28
29 unsigned seconds( unsigned h, unsigned m, unsigned s )
30 {
31 return 3600 * ( h >= 12 ? h - 12 : h ) + 60 * m + s;
32 }
Enter the first time as three integers: 5 33 45
Enter the second time as three integers: 9 22 8
The difference between the times is 13703 seconds
Chapter 3 Functions Solutions 79
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
c) Use these functions to write a program that prints charts showing the Fahrenheit equivalents of all Celsius temperatures
from 0 to 100 degrees, and the Celsius equivalents of all Fahrenheit temperatures from 32 to 212 degrees. Print the out-
puts in a neat tabular format that minimizes the number of lines of output while remaining readable.
1// Exercise 3.27 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int celcius( int );
8int fahrenheit( int );
9
10 int main()
11 {
12 cout << "Fahrenheit equivalents of Celcius temperatures:\n"
13 << "Celcius\t\tFahrenheit\n";
14
15 for ( int i = 0; i <= 100; ++i )
16 cout << i << "\t\t" << fahrenheit( i ) << '\n';
17
18 cout << "\nCelcius equivalents of Fahrenheit temperatures:"
19 << "\nFahrenheit\tCelcius\n";
20
21 for ( int j = 32; j <= 212; ++j )
22 cout << j << "\t\t" << celcius( j ) << '\n';
23
24 cout << endl;
25
26 return 0;
27 }
28
29 int celcius( int fTemp )
30 {
31 return static_cast< int > ( 5.0 / 9.0 * ( fTemp - 32 ) );
32 }
33
34 int fahrenheit( int cTemp )
35 {
36 return static_cast< int > ( 9.0 / 5.0 * cTemp + 32 );
37 }
Fahrenheit equivalents of Celcius temperatures:
Celcius Fahrenheit
0 32
1 33
2 35
...
Celcius equivalents of Fahrenheit temperatures:
Fahrenheit Celcius
32 0
33 0
34 1
...
80 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.28 Write a function that returns the smallest of three double-precision, floating-point numbers.
3.29 An integer number is said to be a perfect number if the sum of its factors, including 1 (but not the number itself), is equal
to the number. For example, 6 is a perfect number, because 6 = 1 + 2 + 3. Write a function perfect that determines whether pa-
rameter number is a perfect number. Use this function in a program that determines and prints all the perfect numbers between 1
and 1000. Print the factors of each perfect number to confirm that the number is indeed perfect. Challenge the power of your com-
puter by testing numbers much larger than 1000.
1// Exercise 3.28 Solution
2#include <iostream>
3using std::cout;
4using std::endl;
5using std::cin;
6
7double smallest3( double, double, double );
8
9int main()
10 {
11 double x, y, z;
12
13 cout << "Enter three numbers: ";
14 cin >> x >> y >> z;
15 cout << "The smallest value is " << smallest3( x, y, z ) << endl;
16
17 return 0;
18 }
19
20 double smallest3( double smallest, double b, double c )
21 {
22 if ( b < smallest && c > smallest )
23 return b;
24 else if ( c < smallest )
25 return c;
26 else
27 return smallest;
28 }
Enter three numbers: 4.3 6.77 9.76
The smallest value is 4.3
1// Exercise 3.29 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7bool perfect( int );
8
9int main()
10 {
11 cout << "For the integers from 1 to 1000:\n";
12
13 for ( int j = 2; j <= 1000; ++j )
14 if ( perfect( j ) )
15 cout << j << " is perfect\n";
16
17 cout << endl;
18
19 return 0;
Chapter 3 Functions Solutions 81
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.30 An integer is said to be prime if it is divisible by only 1 and itself. For example, 2, 3, 5 and 7 are prime, but 4, 6, 8 and 9
are not.
a) Write a function that determines whether a number is prime.
b) Use this function in a program that determines and prints all the prime numbers between 1 and 10,000. How many of
these 10,000 numbers do you really have to test before being sure that you have found all the primes?
c) Initially, you might think that n/2 is the upper limit for which you must test to see whether a number is prime, but you
need only go as high as the square root of n. Why? Rewrite the program, and run it both ways. Estimate the performance
improvement.
20 }
21
22 bool perfect( int value )
23 {
24 int factorSum = 1;
25
26 for ( int i = 2; i <= value / 2; ++i )
27 if ( value % i == 0 )
28 factorSum += i;
29
30 return factorSum == value ? true : false;
31 }
For the integers from 1 to 1000:
6 is perfect
28 is perfect
496 is perfect
1// Exercise 3.30 Part A Solution
2#include <iostream>
3using std::cout;
4
5#include <iomanip>
6
7using std::setw;
8
9bool prime( int );
10
11 int main()
12 {
13 int count = 0;
14
15 cout << "The prime numbers from 1 to 10000 are:\n";
16
17 for ( int loop = 2; loop <= 10000; ++loop )
18 if ( prime( loop ) ) {
19 ++count;
20 cout << setw( 6 ) << loop;
21
22 if ( count % 10 == 0 )
23 cout << '\n';
24 }
25
26 return 0;
27 }
28
29 bool prime( int n )
30 {
31 for ( int loop2 = 2; loop2 <= n / 2; loop2++ )
32 if ( n % loop2 == 0 )
82 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
33 return false;
34
35 return true;
36 }
The prime numbers from 1 to 10000 are:
2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113
127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199 211 223 227 229
233 239 241 251 257 263 269 271 277 281
283 293 307 311 313 317 331 337 347 349
353 359 367 373 379 383 389 397 401 409
419 421 431 433 439 443 449 457 461 463
...
9739 9743 9749 9767 9769 9781 9787 9791 9803 9811
9817 9829 9833 9839 9851 9857 9859 9871 9883 9887
9901 9907 9923 9929 9931 9941 9949 9967 9973
1// Exercise 3.30 Part C Solution
2#include <iostream>
3
4using std::cout;
5
6#include <iomanip>
7using std::setw;
8
9#include <cmath>
10
11 bool prime( int n );
12
13 int main()
14 {
15 int count = 0;
16
17 cout << "The prime numbers from 1 to 10000 are:\n";
18
19 for ( int j = 2; j <= 10000; ++j )
20 if ( prime( j ) ) {
21 ++count;
22 cout << setw( 5 ) << j;
23
24 if ( count % 10 == 0 )
25 cout << '\n';
26 }
27
28 return 0;
29 }
30
31 bool prime( int n )
32 {
33 for ( int i = 2; i <= static_cast< int > ( sqrt( n ) ); ++i )
34 if ( n % i == 0 )
35 return false;
36
37 return true;
38 }
Chapter 3 Functions Solutions 83
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.31 Write a function that takes an integer value and returns the number with its digits reversed. For example, given the number
7631, the function should return 1367.
The prime numbers from 1 to 10000 are:
2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113
127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199 211 223 227 229
233 239 241 251 257 263 269 271 277 281
283 293 307 311 313 317 331 337 347 349
353 359 367 373 379 383 389 397 401 409
419 421 431 433 439 443 449 457 461 463
...
9739 9743 9749 9767 9769 9781 9787 9791 9803 9811
9817 9829 9833 9839 9851 9857 9859 9871 9883 9887
9901 9907 9923 9929 9931 9941 9949 9967 9973
1// Exercise 3.31 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <iomanip>
9
10 using std::setw;
11 using std::setfill;
12
13 int reverseDigits( int );
14 int width( int );
15
16 int main()
17 {
18 int number;
19
20 cout << "Enter a number between 1 and 9999: ";
21 cin >> number;
22
23 cout << "The number with its digits reversed is: "
24 << setw( ( width( number ) ) ) << setfill( '0' )
25 << reverseDigits( number )
26 << endl;
27
28 return 0;
29 }
30
31 int reverseDigits( int n )
32 {
33 int reverse = 0, divisor = 1000, multiplier = 1;
34
35 while ( n > 10 ) {
36
37 if ( n >= divisor ) {
38 reverse += n / divisor * multiplier;
39 n %= divisor;
40 divisor /= 10;
41 multiplier *= 10;
42 }
84 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.32 The greatest common divisor (GCD) of two integers is the largest integer that evenly divides each of the numbers. Write a
function gcd that returns the greatest common divisor of two integers.
43 else
44 divisor /= 10;
45 }
46
47 reverse += n * multiplier;
48 return reverse;
49 }
50
51 int width( int n )
52 {
53 if ( n /= 1000 )
54 return 4;
55 else if ( n /= 100 )
56 return 3;
57 else if ( n /= 10 )
58 return 2;
59 else
60 return 1;
61 }
Enter a number between 1 and 9999: 8765
The number with its digits reversed is: 5678
1// Exercise 3.32 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6
7int gcd( int, int );
8
9int main()
10 {
11 int a, b;
12
13 for ( int j = 1; j <= 5; ++j ) {
14 cout << "Enter two integers: ";
15 cin >> a >> b;
16 cout << "The greatest common divisor of " << a << " and "
17 << b << " is " << gcd( a, b ) << "\n\n";
18 }
19
20 return 0;
21 }
22
23 int gcd( int x, int y )
24 {
25 int greatest = 1;
26
27 for ( int i = 2; i <= ( ( x < y ) ? x: y ); ++i )
28 if ( x % i == 0 && y % i == 0 )
29 greatest = i;
30
31 return greatest;
32 }
Chapter 3 Functions Solutions 85
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.33 Write a function qualityPoints that inputs a student’s average and returns 4 if a student's average is 90–100, 3 if the
average is 80–89, 2 if the average is 70–79, 1 if the average is 60–69 and 0 if the average is lower than 60.
Enter two integers: 6 8
The greatest common divisor of 6 and 8 is 2
Enter two integers: 789 4
The greatest common divisor of 789 and 4 is 1
Enter two integers: 9999 27
The greatest common divisor of 9999 and 27 is 9
Enter two integers: 73652 8
The greatest common divisor of 73652 and 8 is 4
Enter two integers: 99 11
The greatest common divisor of 99 and 11 is 11
1// Exercise 3.33 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int qualityPoints( int );
9
10 int main()
11 {
12 int average;
13
14 for ( int loop = 1; loop <= 5; ++loop ) {
15 cout << "\nEnter the student's average: ";
16 cin >> average;
17 cout << average << " on a 4 point scale is "
18 << qualityPoints( average ) << '\n';
19 }
20
21 cout << endl;
22 return 0;
23 }
24
25 int qualityPoints( int average )
26 {
27 if ( average >= 90 )
28 return 4;
29 else if ( average >= 80 )
30 return 3;
31 else if ( average >= 70 )
32 return 2;
33 else if ( average >= 60 )
34 return 1;
35 else
36 return 0;
37 }
86 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.34 Write a program that simulates coin tossing. For each toss of the coin, the program should print Heads or Tails. Let the
program toss the coin 100 times and count the number of times each side of the coin appears. Print the results. The program should
call a separate function flip that takes no arguments and returns 0 for tails and 1 for heads. Note: If the program realistically sim-
ulates the coin tossing, then each side of the coin should appear approximately half the time.
Enter the student's average: 99
99 on a 4 point scale is 4
Enter the student's average: 72
72 on a 4 point scale is 2
Enter the student's average: 88
88 on a 4 point scale is 3
Enter the student's average: 65
65 on a 4 point scale is 1
Enter the student's average: 33
33 on a 4 point scale is 0
1// Exercise 3.34 Solution
2
3#include <iostream>
4
5using std::cout;
6using std::endl;
7
8#include <cstdlib>
9#include <ctime>
10
11 int flip( void );
12
13 int main()
14 {
15 int headCount = 0, tailCount = 0;
16
17 srand( time( 0 ) );
18
19 for ( int loop = 1; loop <= 100; loop++ ) {
20
21 if ( flip() == 0 ) {
22 tailCount++;
23 cout << "Tails ";
24 }
25 else {
26 headCount++;
27 cout << "Heads ";
28 }
29
30 if ( loop % 10 == 0 )
31 cout << '\n';
32 }
33
34 cout << "\nThe total number of Heads was "
35 << headCount << "\nThe total number of Tails was "
36 << tailCount << endl;
37
38 return 0;
39 }
Chapter 3 Functions Solutions 87
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.35 Computers are playing an increasing role in education. Write a program that will help an elementary school student learn
multiplication. Use rand to produce two positive one-digit integers. It should then type a question such as:
How much is 6 times 7?
The student then types the answer. Your program checks the student's answer. If it is correct, print "Very good!", and then ask
another multiplication question. If the answer is wrong, print "No. Please try again." and then let the student try the same
question again repeatedly until the student finally gets it right.
40
41 int flip( void )
42 {
43 return rand() % 2;
44 }
Tails Heads Heads Heads Heads Tails Tails Tails Tails Tails
Tails Heads Heads Tails Tails Heads Tails Tails Heads Tails
Heads Tails Heads Heads Tails Tails Tails Heads Tails Heads
Heads Heads Heads Tails Heads Heads Heads Tails Heads Heads
Heads Heads Heads Heads Heads Heads Tails Heads Tails Heads
Heads Tails Tails Heads Heads Heads Heads Heads Tails Tails
Tails Heads Heads Heads Tails Tails Heads Heads Heads Heads
Heads Tails Tails Heads Tails Heads Tails Tails Heads Heads
Heads Tails Heads Tails Tails Tails Heads Tails Heads Heads
Heads Heads Heads Heads Heads Tails Tails Heads Heads Heads
The total number of Heads was 60
The total number of Tails was 40
1// Exercise 3.35 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstdlib>
9#include <ctime>
10
11 void multiplication( void );
12
13 int main()
14 {
15 srand( time( 0 ) );
16 multiplication();
17 return 0;
18 }
19
20 void multiplication( void )
21 {
22 int x, y, response = 0;
23
24 cout << "Enter -1 to End.\n";
25
26 while ( response != -1 ) {
27 x = rand() % 10;
28 y = rand() % 10;
29
30 cout << "How much is " << x << " times " << y << " (-1 to End)? ";
88 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.36 The use of computers in education is referred to as computer-assisted instruction (CAI). One problem that develops in CAI
environments is student fatigue. This can be eliminated by varying the computer's dialogue to hold the student's attention. Modify
the program of Exercise 3.35 so the various comments are printed for each correct answer and each incorrect answer as follows:
Responses to a correct answer
Very good!
Excellent!
Nice work!
Keep up the good work!
Responses to an incorrect answer
No. Please try again.
Wrong. Try once more.
Don't give up!
No. Keep trying.
Use the random number generator to choose a number from 1 to 4 to select an appropriate response to each answer. Use a switch
structure to issue the responses.
31 cin >> response;
32
33 while ( response != -1 && response != x * y ) {
34 cout << "No. Please try again.\n? ";
35 cin >> response;
36 }
37
38 if ( response != -1 )
39 cout << "Very good!\n\n";
40 }
41
42 cout << "That's all for now. Bye." << endl;
43 }
Enter -1 to End.
How much is 4 times 9 (-1 to End)? 36
Very good!
How much is 7 times 0 (-1 to End)? 0
Very good!
How much is 7 times 8 (-1 to End)? 55
No. Please try again.
? 56
Very good!
How much is 5 times 0 (-1 to End)? -1
That's all for now. Bye.
1// Exercise 3.36 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstdlib>
9#include <ctime>
10
Chapter 3 Functions Solutions 89
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
11 void correctMessage( void );
12 void incorrectMessage( void );
13 void multiplication( void );
14
15 int main()
16 {
17 srand( time( 0 ) );
18 multiplication();
19
20 return 0;
21 }
22
23 void correctMessage( void )
24 {
25 switch ( rand() % 4 ) {
26 case 0:
27 cout << "Very good!";
28 break;
29 case 1:
30 cout << "Excellent!";
31 break;
32 case 2:
33 cout << "Nice work!";
34 break;
35 case 3:
36 cout << "Keep up the good work!";
37 break;
38 }
39
40 cout << "\n\n";
41 }
42
43 void incorrectMessage( void )
44 {
45 switch ( rand() % 4 ) {
46 case 0:
47 cout << "No. Please try again.";
48 break;
49 case 1:
50 cout << "Wrong. Try once more.";
51 break;
52 case 2:
53 cout << "Don't give up!";
54 break;
55 case 3:
56 cout << "No. Keep trying.";
57 break;
58 }
59
60 cout << "\n? ";
61 }
62
63 void multiplication( void )
64 {
65 int x, y, response = 0;
66
67 while ( response != -1 ) {
68 x = rand() % 10;
69 y = rand() % 10;
70
71 cout << "How much is " << x << " times " << y
72 << " (-1 to End)? ";
90 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.37 More sophisticated computer-aided instruction systems monitor the student’s performance over a period of time. The de-
cision to begin a new topic is often based on the student’s success with previous topics. Modify the program of Exercise 3.36 to
count the number of correct and incorrect responses typed by the student. After the student types 10 answers, your program should
calculate the percentage of correct responses. If the percentage is lower than 75 percent, your program should print "Please ask
your instructor for extra help" and then terminate.
73 cin >> response;
74
75 while ( response != -1 && response != x * y ) {
76 incorrectMessage();
77 cin >> response;
78 }
79
80 if ( response != -1 ) {
81 correctMessage();
82 }
83 }
84
85 cout << "That's all for now. Bye." << endl;
86 }
Enter -1 to End.
How much is 4 times 9 (-1 to End)? 36
Very good!
How much is 7 times 0 (-1 to End)? 0
Nice Work!
How much is 7 times 8 (-1 to End)? 55
No. Please try again.
? 56
Excellent!
How much is 5 times 0 (-1 to End)? -1
That's all for now. Bye.
1// Exercise 3.37 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstdlib>
9#include <ctime>
10
11 void multiplication( void );
12 void correctMessage( void );
13 void incorrectMessage( void );
14
15 int main()
16 {
17 srand( time( 0 ) );
18 multiplication();
19
20 return 0;
21 }
22
Chapter 3 Functions Solutions 91
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
23 void multiplication( void )
24 {
25 int x, y, response, right = 0, wrong = 0;
26
27 for ( int i = 1; i <= 10; ++i ) {
28 x = rand() % 10;
29 y = rand() % 10;
30
31 cout << "How much is " << x << " times " << y << "? ";
32 cin >> response;
33
34 while ( response != x * y ) {
35 ++wrong;
36 incorrectMessage();
37 cin >> response;
38 }
39
40 ++right;
41 correctMessage();
42 }
43
44 if ( static_cast< double > ( right ) / ( right + wrong ) < .75 )
45 cout << "Please ask your instructor for extra help.\n";
46
47 cout << "That's all for now. Bye." << endl;
48 }
49
50 void correctMessage( void )
51 {
52 switch ( rand() % 4 ) {
53 case 0:
54 cout << "Very good!";
55 break;
56 case 1:
57 cout << "Excellent!";
58 break;
59 case 2:
60 cout << "Nice work!";
61 break;
62 case 3:
63 cout << "Keep up the good work!";
64 break;
65 }
66
67 cout << "\n\n";
68 }
69
70 void incorrectMessage( void )
71 {
72 switch ( rand() % 4 ) {
73 case 0:
74 cout << "No. Please try again.";
75 break;
76 case 1:
77 cout << "Wrong. Try once more.";
78 break;
79 case 2:
80 cout << "Don't give up!";
81 break;
82 case 3:
83 cout << "No. Keep trying.";
84 break;
92 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.38 Write a program that plays the game of “guess the number” as follows: Your program chooses the number to be guessed
by selecting an integer at random in the range 1 to 1000. The program then types:
The player then types a first guess. The program responds with one of the following:
If the player's guess is incorrect, your program should loop until the player finally gets the number right. Your program should keep
telling the player Too high or Too low to help the player “zero in” on the correct answer.
85 }
86
87 cout << "\n? ";
88 }
...
How much is 3 times 7? 21
Nice work!
How much is 5 times 9? 45
Very good!
That's all for now. Bye.
I have a number between 1 and 1000.
Can you guess my number?
Please type your first guess.
1. Excellent! You guessed the number!
Would you like to play again (y or n)?
2. Too low. Try again.
3. Too high. Try again.
1// Exercise 3.38 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6
7#include <cstdlib>
8#include <ctime>
9
10 void guessGame( void );
11 bool isCorrect( int, int );
12
13 int main()
14 {
15 srand( time( 0 ) );
16 guessGame();
17
18 return 0;
19 }
20
21 void guessGame( void )
Chapter 3 Functions Solutions 93
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
22 {
23 int answer, guess;
24 char response;
25
26 do {
27 answer = 1 + rand() % 1000;
28 cout << "\nI have a number between 1 and 1000.\n"
29 << "Can you guess my number?\nPlease type your"
30 << " first guess.\n? ";
31 cin >> guess;
32
33 while ( !isCorrect( guess, answer ) )
34 cin >> guess;
35
36 cout << "\nExcellent! You guessed the number!\n"
37 << "Would you like to play again?\nPlease type (y/n)? ";
38 cin >> response;
39
40 } while ( response == 'y' );
41 }
42
43 bool isCorrect( int g, int a )
44 {
45 if ( g == a )
46 return true;
47
48 if ( g < a )
49 cout << "Too low. Try again.\n? ";
50 else
51 cout << "Too high. Try again.\n? ";
52
53 return false;
54 }
94 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.39 Modify the program of Exercise 3.38 to count the number of guesses the player makes. If the number is 10 or fewer, print
Either you know the secret or you got lucky! If the player guesses the number in 10 tries, then print Ahah! You know
the secret! If the player makes more than 10 guesses, then print You should be able to do better! Why should it take
no more than 10 guesses? Well, with each “good guess” the player should be able to eliminate half of the numbers. Now show why
any number from 1 to 1000 can be guessed in 10 or fewer tries.
I have a number between 1 and 1000.
Can you guess my number?
Please type your first guess.
? 500
Too high. Try again.
? 250
Too low. Try again.
? 375
Too low. Try again.
? 438
Too high. Try again.
? 405
Too high. Try again.
? 380
Too low. Try again.
? 393
Too low. Try again.
? 399
Too high. Try again.
? 396
Too low. Try again.
? 398
Too high. Try again.
? 397
Excellent! You guessed the number!
Would you like to play again?
Please type (y/n)? n
1// Exercise 3.39 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6
7#include <cstdlib>
8#include <ctime>
9
10 void guessGame( void );
11 bool isCorrect( int, int );
12 void display( int );
13
14 int main()
15 {
16 srand( time( 0 ) );
17 guessGame();
18
19 return 0;
20 }
21
22 void guessGame( void )
23 {
24 int answer, guess, total = 1;
Chapter 3 Functions Solutions 95
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
25 char response;
26
27 do {
28 answer = 1 + rand() % 1000;
29 cout << "I have a number between 1 and 1000."
30 << "\nCan you guess my number?\nPlease type"
31 << " your first guess.\n? ";
32 cin >> guess;
33
34 while ( !isCorrect( guess, answer ) ) {
35 cin >> guess;
36 ++total;
37 }
38
39 cout << "\nExcellent! You guessed the number!\n";
40
41 display( total );
42
43 cout << "Would you like to play again?\nPlease type (y/n)? ";
44 cin >> response;
45
46 } while ( response == 'y' );
47 }
48
49 bool isCorrect( int g, int a )
50 {
51 if ( g == a )
52 return true;
53
54 if ( g < a )
55 cout << "Too low. Try again.\n? ";
56 else
57 cout << "Too high. Try again.\n? ";
58
59 return false;
60 }
61
62 void display( int t )
63 {
64 if ( t < 10 )
65 cout << "Either you know the secret or you got lucky!\n";
66 else if ( t == 10 )
67 cout << "Ahah! You know the secret!\n";
68 else
69 cout << "You should be able to do better!\n\n";
70 }
96 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.40 Write a recursive function power( base, exponent ) that, when invoked, returns
base exponent
For example, power( 3, 4 ) = 3 * 3 * 3 * 3. Assume that exponent is an integer greater than or equal to 1. Hint: The recursion
step would use the relationship
base exponent = base · base exponent - 1
and the terminating condition occurs when exponent is equal to 1 because
base1 = base
I have a number between 1 and 1000.
Can you guess my number?
Please type your first guess.
? 500
Too high. Try again.
? 250
Too low. Try again.
? 375
Too high. Try again.
? 313
Too low. Try again.
? 344
Too low. Try again.
? 360
Too high. Try again.
? 352
Too high. Try again.
? 348
Too low. Try again.
? 350
Too low. Try again.
? 351
Excellent! You guessed the number!
Ahah! You know the secret!
Would you like to play again?
Please type (y/n)? n
Press any key to continue
1// Exercise 3.40 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8long power( long, long );
9
10 int main()
11 {
12 long b, e;
13
14 cout << "Enter a base and an exponent: ";
15 cin >> b >> e;
16 cout << b << " raised to the " << e << " is "
Chapter 3 Functions Solutions 97
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.41 The Fibonacci series
0, 1, 1, 2, 3, 5, 8, 13, 21, …
begins with the terms 0 and 1 and has the property that each succeeding term is the sum of the two preceding terms. a) Write a
nonrecursive function fibonacci( n ) that calculates the nth Fibonacci number. b) Determine the largest Fibonacci number that
can be printed on your system. Modify the program of part a) to use double instead of int to calculate and return Fibonacci num-
bers, and use this modified program to repeat part b).
17 << power( b, e ) << endl;
18
19 return 0;
20 }
21
22 long power( long base, long exponent )
23 {
24 return exponent == 1 ? base : base * power( base, exponent - 1 );
25 }
Enter a base and an exponent: 3 4
3 raised to the 4 is 81
1// Exercise 3.41 Part A Solution
2// NOTE: This exercise was accidently placed in this
3// chapter. The solution utilizes ARRAYS which are
4// introduced in the next chapter.
5#include <iostream>
6
7using std::cout;
8using std::endl;
9
10 int MAX = 22; // the maximum number for which the
11 // fibonacci value can be calculated
12 // on 2-byte integer systems
13
14 int fibonacci( int );
15
16 int main()
17 {
18 for ( int loop = 0; loop <= MAX; ++loop )
19 cout << "fibonacci(" << loop << ") = " << fibonacci( loop )
20 << "\n";
21
22 cout << endl;
23 return 0;
24 }
25
26 int fibonacci( int n )
27 {
28 int fib[ 23 ];
29
30 fib[ 0 ] = 0;
31 fib[ 1 ] = 1;
32
33 for ( int j = 2; j <= n; ++j )
34 fib[ j ] = fib[ j - 1 ] + fib[ j - 2 ];
35
36 return fib[ n ];
98 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
37 }
fibonacci(0) = 0
fibonacci(1) = 1
fibonacci(2) = 1
fibonacci(3) = 2
fibonacci(4) = 3
fibonacci(5) = 5
fibonacci(6) = 8
fibonacci(7) = 13
fibonacci(8) = 21
fibonacci(9) = 34
fibonacci(10) = 55
fibonacci(11) = 89
fibonacci(12) = 144
fibonacci(13) = 233
fibonacci(14) = 377
fibonacci(15) = 610
fibonacci(16) = 987
fibonacci(17) = 1597
fibonacci(18) = 2584
fibonacci(19) = 4181
fibonacci(20) = 6765
fibonacci(21) = 10946
fibonacci(22) = 17711
fibonacci(23) = 28658
1// Exercise 3.41 Part B Solution
2// NOTE: This exercise was accidently placed in this
3// chapter. The solution utiliizes ARRAYS which are
4// introduced in the next chapter.
5#include <iostream>
6
7using std::cout;
8using std::endl;
9using std::ios;
10
11 #include <iomanip>
12
13 using std::setprecision;
14 using std::setiosflags;
15
16 double fibonacci( int );
17
18 int main()
19 {
20 cout << setiosflags( ios::fixed | ios::showpoint );
21
22 for ( int loop = 0; loop < 100; ++loop )
23 cout << setprecision( 1 ) << "fibonacci(" << loop << ") = "
24 << fibonacci( loop ) << endl;
25
26 return 0;
27 }
28
29 double fibonacci( int n )
30 {
31 double fib[ 100 ];
32
33 fib[ 0 ] = 0.0;
Chapter 3 Functions Solutions 99
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.42 (Towers of Hanoi) Every budding computer scientist must grapple with certain classic problems. The Towers of Hanoi (see
Fig.3.28) is one of the most famous of these. Legend has it that in a temple in the Far East, priests are attempting to move a stack
of disks from one peg to another. The initial stack had 64 disks threaded onto one peg and arranged from bottom to top by decreasing
size. The priests are attempting to move the stack from this peg to a second peg under the constraints that exactly one disk is moved
at a time, and at no time may a larger disk be placed above a smaller disk. A third peg is available for temporarily holding disks.
Supposedly, the world will end when the priests complete their task, so there is little incentive for us to facilitate their efforts.
Let us assume that the priests are attempting to move the disks from peg 1 to peg 3. We wish to develop an algorithm that will
print the precise sequence of peg-to-peg disk transfers.
If we were to approach this problem with conventional methods, we would rapidly find ourselves hopelessly knotted up in
managing the disks. Instead, if we attack the problem with recursion in mind, it immediately becomes tractable. Moving n disks
can be viewed in terms of moving only n - 1 disks (hence, the recursion), as follows:
Fig. 3.1 The Towers of Hanoi for the case with four disks.
a) Move n - 1 disks from peg 1 to peg 2, using peg 3 as a temporary holding area.
b) Move the last disk (the largest) from peg 1 to peg 3.
c) Move the n - 1 disks from peg 2 to peg 3, using peg 1 as a temporary holding area.
The process ends when the last task involves moving n = 1 disk, i.e., the base case. This is accomplished by trivially moving
the disk without the need for a temporary holding area.
Write a program to solve the Towers of Hanoi problem. Use a recursive function with four parameters:
34 fib[ 1 ] = 1.0;
35
36 for ( int j = 2; j <= n; j++ )
37 fib[ j ] = fib[ j - 1 ] + fib[ j - 2 ];
38
39 return fib[ n ];
40 }
fibonacci(0) = 0.0
fibonacci(1) = 1.0
fibonacci(2) = 1.0
fibonacci(3) = 2.0
fibonacci(4) = 3.0
fibonacci(5) = 5.0
fibonacci(6) = 8.0
fibonacci(7) = 13.0
...
fibonacci(96) = 51680708854858326000.0
fibonacci(97) = 83621143489848426000.0
fibonacci(98) = 135301852344706760000.0
fibonacci(99) = 218922995834555200000.0
100 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
a) The number of disks to be moved
b) The peg on which these disks are initially threaded
c) The peg to which this stack of disks is to be moved
d) The peg to be used as a temporary holding area
Your program should print the precise instructions it will take to move the disks from the starting peg to the destination peg.
For example, to move a stack of three disks from peg 1 to peg 3, your program should print the following series of moves:
1 3 (This means move one disk from peg 1 to peg 3.)
1 2
3 2
1 3
2 1
2 3
1 3
1// Exercise 3.42 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6
7void towers( int, int, int, int );
8
9int main()
10 {
11 int nDisks;
12
13 cout << "Enter the starting number of disks: ";
14 cin >> nDisks;
15 towers( nDisks, 1, 3, 2 );
16
17 return 0;
18 }
19
20 void towers( int disks, int start, int end, int temp )
21 {
22 if ( disks == 1 ) {
23 cout << start << " --> " << end << '\n';
24 return;
25 }
26
27 // move disks - 1 disks from start to temp
28 towers( disks - 1, start, temp, end );
29
30 // move last disk from start to end
31 cout << start << " --> " << end << '\n';
32
33 // move disks - 1 disks from temp to end
34 towers( disks - 1, temp, end, start );
35 }
Chapter 3 Functions Solutions 101
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.43 Any program that can be implemented recursively can be implemented iteratively, although sometimes with more difficulty
and less clarity. Try writing an iterative version of the Towers of Hanoi. If you succeed, compare your iterative version with the
recursive version you developed in Exercise 3.42. Investigate issues of performance, clarity and your ability to demonstrate the cor-
rectness of the programs.
3.44 (Visualizing Recursion) It is interesting to watch recursion “in action.” Modify the factorial function of Fig. 3.14 to print
its local variable and recursive call parameter. For each recursive call, display the outputs on a separate line and add a level of in-
dentation. Do your utmost to make the outputs clear, interesting and meaningful. Your goal here is to design and implement an out-
put format that helps a person understand recursion better. You may want to add such display capabilities to the many other
recursion examples and exercises throughout the text.
Enter the starting number of disks: 4
1 --> 2
1 --> 3
2 --> 3
1 --> 2
3 --> 1
3 --> 2
1 --> 2
1 --> 3
2 --> 3
2 --> 1
3 --> 1
2 --> 3
1 --> 2
1 --> 3
2 --> 3
1// Exercise 3.44 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <iomanip>
8
9using std::setw;
10
11 long factorial( long );
12 void printRecursion( int );
13
14 int main()
15 {
16 for ( int i = 0; i <= 10; ++i )
17 cout << setw( 3 ) << i << "! = " << factorial( i ) << endl;
18
19 return 0;
20 }
21
22 long factorial( long number )
23 {
24 if ( number <= 1 )
25 return 1;
26 else {
27 printRecursion( number );
28 return ( number * factorial( number - 1 ) );
29 }
30 }
31
102 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.45 The greatest common divisor of integers x and y is the largest integer that evenly divides both x and y. Write a recursive
function gcd that returns the greatest common divisor of x and y. The gcd of x and y is defined recursively as follows: If y is
equal to 0, then gcd( x, y ) is x; otherwise gcd( x, y ) is gcd( y, x % y ), where % is the modulus operator.
32 void printRecursion( int n )
33 {
34 cout << "number =" << setw( n ) << n << '\n';
35 }
0! = 1
1! = 1
number = 2
2! = 2
number = 3
number = 2
3! = 6
number = 4
number = 3
number = 2
4! = 24
number = 5
number = 4
number = 3
number = 2
5! = 120
number = 6
number = 5
number = 4
number = 3
number = 2
...
number = 10
number = 9
number = 8
number = 7
number = 6
number = 5
number = 4
number = 3
number = 2
10! = 3628800
1// Exercise 3.45 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8unsigned gcd( unsigned int, unsigned int );
9
10 int main()
11 {
12 unsigned x, y, gcDiv;
13
14 cout << "Enter two integers: ";
15 cin >> x >> y;
16
17 gcDiv = gcd( x, y );
Chapter 3 Functions Solutions 103
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.46 Can main be called recursively? Write a program containing a function main. Include static local variable count and
initialize it to 1. Postincrement and print the value of count each time main is called. Compile your program. What happens?
3.47 Exercises 3.35 through 3.37 developed a computer-assisted instruction program to teach an elementary school student mul-
tiplication. This exercise suggests enhancements to that program.
a) Modify the program to allow the user to enter a grade-level capability. A grade level of 1 means to use only single-digit
numbers in the problems, a grade level of two means to use numbers as large as two digits, etc.
18 cout << "Greatest common divisor of " << x << " and "
19 << y << " is " << gcDiv << endl;
20
21 return 0;
22 }
23
24 unsigned gcd( unsigned xMatch, unsigned yMatch )
25 {
26 return yMatch == 0 ? xMatch : gcd( yMatch, xMatch % yMatch );
27 }
Enter two integers: 32727 9
Greatest common divisor of 32727 and 9 is 3
1// Exercise 3.46 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 static int count = 1;
10
11 ++count;
12 cout << count << endl;
13 main();
14
15 return 0;
16 }
1
2
3
...
12298
12299
12300
12301
12302
12303
12304
...
104 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
b) Modify the program to allow the user to pick the type of arithmetic problems he or she wishes to study. An option of 1
means addition problems only, 2 means subtraction problems only, 3 means multiplication problems only, 4 means di-
vision problems only, and 5 means to randomly intermix problems of all these types.
1// Exercise 3.47 Part A Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstdlib>
9#include <ctime>
10
11 int randValue( int );
12 void multiplication( void );
13 void correctMessage( void );
14 void incorrectMessage( void );
15
16 int main()
17 {
18 srand( time( 0 ) );
19 multiplication();
20
21 return 0;
22 }
23
24 int randValue( int level )
25 {
26 switch ( level ) {
27 case 1:
28 return rand() % 10;
29 case 2:
30 return rand() % 100;
31 case 3:
32 return rand() % 1000;
33 default:
34 return rand() % 10;
35 }
36 }
37
38 void multiplication( void )
39 {
40 int x, y, gradeLevel, right = 0, wrong = 0;
41 unsigned int response;
42
43 cout << "Enter the grade-level (1 to 3): ";
44 cin >> gradeLevel;
45
46 for ( int i = 1; i <= 10; i++ ) {
47 x = randValue( gradeLevel );
48 y = randValue( gradeLevel );
49
50 cout << "How much is " << x << " times " << y << "? ";
51 cin >> response;
52
53 while ( response != x * y ) {
54 ++wrong;
55 incorrectMessage();
56 cin >> response;
57 }
Chapter 3 Functions Solutions 105
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
58
59 ++right;
60 correctMessage();
61 }
62
63 if ( static_cast< double > ( right ) / ( right + wrong ) < .75 )
64 cout << "Please ask your instructor for extra help.\n";
65
66 cout << "That's all for now. Bye." << endl;
67 }
68
69 void correctMessage( void )
70 {
71 switch ( rand() % 4 ) {
72 case 0:
73 cout << "Very good!";
74 break;
75 case 1:
76 cout << "Excellent!";
77 break;
78 case 2:
79 cout << "Nice work!";
80 break;
81 case 3:
82 cout << "Keep up the good work!";
83 break;
84 }
85
86 cout << "\n\n";
87 }
88
89 void incorrectMessage( void )
90 {
91 switch ( rand() % 4 ) {
92 case 0:
93 cout << "No. Please try again.";
94 break;
95 case 1:
96 cout << "Wrong. Try once more.";
97 break;
98 case 2:
99 cout << "Don't give up!";
100 break;
101 case 3:
102 cout << "No. Keep trying.";
103 break;
104 }
105
106 cout << "\n? ";
107 }
106 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Enter the grade-level (1 to 3): 3
How much is 643 times 462? 297066
Very good!
How much is 763 times 731? 537753
Don't give up!
? 557753
Keep up the good work!
How much is 382 times 120?
...
1// Exercise 3.47 Part B Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstdlib>
9#include <ctime>
10
11 int menu( void );
12 void arithmetic( void );
13 void correctMessage( void );
14 void incorrectMessage( void );
15
16 int main()
17 {
18 srand( time( 0 ) );
19 arithmetic();
20
21 return 0;
22 }
23
24 int menu( void )
25 {
26 int choice;
27
28 do {
29 cout << "Choose type of problem to study."
30 << "\nEnter: 1 for addition, 2 for subtraction"
31 << "\nEnter: 3 for multiplication, 4 for division"
32 << "\nEnter: 5 for a combination of 1 through 4\n? ";
33 cin >> choice;
34
35 } while ( choice < 1 || choice > 5 );
36
37 return choice;
38 }
39
40 void incorrectMessage( void )
41 {
42 switch ( rand() % 4 ) {
43 case 0:
44 cout << "No. Please try again.";
45 break;
46 case 1:
47 cout << "Wrong. Try once more.";
48 break;
Chapter 3 Functions Solutions 107
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
49 case 2:
50 cout << "Don't give up!";
51 break;
52 case 3:
53 cout << "No. Keep trying.";
54 break;
55 }
56
57 cout << "\n? ";
58 }
59
60 void correctMessage( void )
61 {
62 switch ( rand() % 4 ) {
63 case 0:
64 cout << "Very good!";
65 break;
66 case 1:
67 cout << "Excellent!";
68 break;
69 case 2:
70 cout << "Nice work!";
71 break;
72 case 3:
73 cout << "Keep up the good work!";
74 break;
75 }
76
77 cout << "\n\n";
78 }
79
80 void arithmetic( void )
81 {
82 int x, y, response, answer, selection, right = 0, wrong = 0;
83 int type, problemMix;
84 char op;
85
86 selection = menu();
87 type = selection;
88
89 for ( int i = 1; i <= 10; ++i ) {
90 x = rand() % 10;
91 y = rand() % 10;
92
93 if ( selection == 5 ) {
94 problemMix = 1 + rand() % 4;
95 type = problemMix;
96 }
97
98 switch ( type ) {
99 case 1:
100 op = '+';
101 answer = x + y;
102 break;
103 case 2: // note negative answers can exist
104 op = '-';
105 answer = x - y;
106 break;
107 case 3:
108 op = '*';
109 answer = x * y;
110 break;
108 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
111 case 4: // note this is integer division
112 op = '/';
113
114 if ( y == 0 ) {
115 y = 1; // eliminate divide by zero error
116 answer = x / y;
117 }
118 else {
119 x *= y; // create "nice" division
120 answer = x / y;
121 }
122
123 break;
124 }
125
126 cout << "How much is " << x << " " << op << " " << y << "? ";
127 cin >> response;
128
129 while ( response != answer ) {
130 ++wrong;
131 incorrectMessage();
132 cin >> response;
133 }
134
135 ++right;
136 correctMessage();
137 }
138
139 if ( static_cast< double > ( right ) / ( right + wrong ) < .75 )
140 cout << "Please ask your instructor for extra help.\n";
141
142 cout << "That's all for now. Bye." << endl;
143 }
Choose type of problem to study.
Enter: 1 for addition, 2 for subtraction
Enter: 3 for multiplication, 4 for division
Enter: 5 for a combination of 1 through 4
? 5
How much is 7 * 5? 35
Keep up the good work!
How much is 45 / 5? 9
Keep up the good work!
How much is 0 * 7? 0
Excellent!
How much is 1 * 1? 1
Nice work!
How much is 9 * 5? 45
Very good!
How much is 4 + 6?
...
Chapter 3 Functions Solutions 109
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.48 Write function distance that calculates the distance between two points (x1, y1) and (x2, y2). All numbers and return
values should be of type double.
3.49 What is wrong with the following program?
1// Exercise 3.48 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setprecision;
12 using std::setiosflags;
13
14 #include <cmath>
15
16 double distance( double, double, double, double );
17
18 int main()
19 {
20 double x1, y1, x2, y2, dist;
21
22 cout << "Enter the first point: ";
23 cin >> x1 >> y1;
24
25 cout << "Enter the second point: ";
26 cin >> x2 >> y2;
27
28 dist = distance( x1, y1, x2, y2 );
29
30 cout << setiosflags( ios::fixed | ios::showpoint )
31 << "Distance between (" << setprecision( 1 ) << x1 << ", "
32 << y1 << ") and (" << x2 << ", " << y2 << ") is "
33 << dist << endl;
34
35 return 0;
36 }
37
38 double distance( double xOne, double yOne, double xTwo, double yTwo )
39 {
40 return sqrt( pow( xOne - xTwo, 2 ) + pow( yOne - yTwo, 2 ) );
41 }
Enter the first point: 8 9
Enter the second point: 0 1
Distance between (8.0, 9.0) and (0.0, 1.0) is 11.3
1// ex03_49.cpp
2#include <iostream>
3
4using std::cin;
5using std::cout;
6
7int main()
8{
110 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
ANS: Standard C++ does not allow recursive calls of main, however, on nonstandard compilers, this program would
print the characters input in reverse order.
3.50 What does the following program do?
3.51 After you determine what the program of Exercise 3.50 does, modify the program to function properly after removing the
restriction that the second argument be nonnegative.
9 int c;
10
11 if ( ( c = cin.get() ) != EOF ) {
12 main();
13 cout << c;
14 }
15
16 return 0;
17 }
1// ex03_50.cpp
2#include <iostream>
3
4using std::cout;
5using std::cin;
6using std::endl;
7
8int mystery( int, int );
9
10 int main()
11 {
12 int x, y;
13
14 cout << "Enter two integers: ";
15 cin >> x >> y;
16 cout << "The result is " << mystery( x, y ) << endl;
17 return 0;
18 }
19
20 // Parameter b must be a positive
21 // integer to prevent infinite recursion
22 int mystery( int a, int b )
23 {
24 if ( b == 1 )
25 return a;
26 else
27 return a + mystery( a, b - 1 );
28 }
Enter two integers: 8 2
The result is 16
1// Exercise 3.51 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int mystery( int, int );
Chapter 3 Functions Solutions 111
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.52 Write a program that tests as many of the math library functions in Fig. 3.2 as you can. Exercise each of these functions by
having your program print out tables of return values for a diversity of argument values.
9
10 int main()
11 {
12 int x, y;
13
14 cout << "Enter two integers: ";
15 cin >> x >> y;
16 cout << "The result is " << mystery( x, y ) << endl;
17 return 0;
18 }
19
20 int mystery( int a, int b )
21 {
22 if ( ( a < 0 && b < 0 ) || b < 0 ) {
23 a *= -1;
24 b *= -1;
25 }
26
27 return b == 1 ? a : a + mystery( a, b - 1 );
28 }
Enter two integers: -8 8
The result is -64
1// Exercise 3.52 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::ios;
7
8#include <iomanip>
9
10 using std::setw;
11 using std::setprecision;
12 using std::setiosflags;
13
14 #include <cmath>
15
16 int main()
17 {
18 cout << "function"; // header
19
20 for ( int a = 1; a < 6; ++a )
21 cout << setw( 12 ) << a << ' ';
22
23 cout << setiosflags( ios::fixed | ios::showpoint ) << "\n\nsqrt() ";
24
25 for ( int b = 1; b < 6; ++b )
26 cout << setw( 12 ) << setprecision( 2 ) << sqrt( b ) << ' ';
27
28 cout << "\nexp() ";
29
30 for ( int c = 1; c < 6; ++c )
31 cout << setw( 12 ) << setprecision( 2 ) << exp( c ) << ' ';
32
112 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
33 cout << "\nlog() ";
34
35 for ( int d = 1; d < 6; ++d )
36 cout << setw( 12 ) << setprecision( 2 ) << log( d ) << ' ';
37
38 cout << "\nlog10() ";
39
40 for ( int e = 1; e < 6; ++e )
41 cout << setw( 12 ) << setprecision( 2 ) << log10( e ) << ' ';
42
43 cout << "\npow(2,x)";
44
45 for ( int f = 1; f < 6; ++f )
46 cout << setw( 12 ) << setprecision( 2 ) << pow( 2, f ) << ' ';
47
48 cout << "\n\n\nfunction"; // header
49
50 for ( double g = -1.5; g < 3.0; g += 1.1 )
51 cout << setw( 12 ) << setprecision( 2 ) << g << ' ';
52
53 cout << "\n\n\nfabs() ";
54
55 for ( double h = -1.5; h < 3.0; h += 1.1 )
56 cout << setw( 12 ) << setprecision( 2 ) << fabs( h ) << ' ';
57
58 cout << "\nceil() ";
59
60 for ( double i = -1.5; i < 3.0; i += 1.1 )
61 cout << setw( 12 ) << setprecision( 2 ) << ceil( i ) << ' ';
62
63 cout << "\nfloor() ";
64
65 for ( double j = -1.5; j < 3.0; j += 1.1 )
66 cout << setw( 12 ) << setprecision( 2 ) << floor( j ) << ' ';
67
68 cout << "\nsin() ";
69
70 for ( double k = -1.5; k < 3.0; k += 1.1 )
71 cout << setw( 12 ) << setprecision( 2 ) << sin( k ) << ' ';
72
73 cout << "\ncos() ";
74
75 for ( double l = -1.5; l < 3.0; l += 1.1 )
76 cout << setw( 12 ) << setprecision( 2 ) << cos( l ) << ' ';
77
78 cout << "\ntan() ";
79
80 for ( double m = -1.5; m < 3.0; m += 1.1 )
81 cout << setw( 12 ) << setprecision( 2 ) << tan( m ) << ' ';
82
83 cout << endl;
84 return 0;
85 }
Chapter 3 Functions Solutions 113
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.53 Find the error in each of the following program segments and explain how to correct it:
a) float cube( float ); // function prototype
double cube( float number ) // function definition
{
return number * number * number;
}
ANS: The function definition defaults to a return type of int. Specify a return type of float for the definition.
b) register auto int x = 7;
ANS: Only one storage class specifier can be used. Either register or auto must be removed.
c) int randomNumber = srand();
ANS: Function srand takes an unsigned argument and does not return a value. Use rand instead of srand.
d) float y = 123.45678;
int x;
x = y;
cout << static_cast< float >( x ) << endl;
ANS: The assignment of y to x truncates decimal places.
e) double square( double number )
{
double number;
return number * number;
}
ANS: Variable number is declared twice. Remove the declaration within the {}.
f) int sum( int n )
{
if ( n == 0 )
return 0;
else
return n + sum( n );
}
ANS: Infinite recursion. Change operator + to operator -.
3.54 Modify the craps program of Fig. 3.10 to allow wagering. Package as a function the portion of the program that runs one
game of craps. Initialize variable bankBalance to 1000 dollars. Prompt the player to enter a wager. Use a while loop to check
that wager is less than or equal to bankBalance and, if not, prompt the user to reenter wager until a valid wager is entered.
After a correct wager is entered, run one game of craps. If the player wins, increase bankBalance by wager and print the new
bankBalance. If the player loses, decrease bankBalance by wager, print the new bankBalance, check on whether bank-
function 1 2 3 4 5
sqrt() 1.00 1.41 1.73 2.00 2.24
exp() 2.72 7.39 20.09 54.60 148.41
log() 0.00 0.69 1.10 1.39 1.61
log10() 0.00 0.30 0.48 0.60 0.70
pow(2,x) 2.00 4.00 8.00 16.00 32.00
function -1.50 -0.40 0.70 1.80 2.90
fabs() 1.50 0.40 0.70 1.80 2.90
ceil() -1.00 0.00 1.00 2.00 3.00
floor() -2.00 -1.00 0.00 1.00 2.00
sin() -1.00 -0.39 0.64 0.97 0.24
cos() 0.07 0.92 0.76 -0.23 -0.97
tan() -14.10 -0.42 0.84 -4.29 -0.25
114 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Balance has become zero and, if so, print the message "Sorry. You busted!" As the game progresses, print various mes-
sages to create some “chatter” such as "Oh, you're going for broke, huh?" or "Aw cmon, take a chance!", or
"You're up big. Now's the time to cash in your chips!".
1// Exercise 3.54 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstdlib>
9#include <ctime>
10
11 enum Status { WON, LOST, CONTINUE };
12
13 int rollDice( void );
14 int craps( void );
15 void chatter( void );
16
17 int main()
18 {
19 int result, wager = 0, bankBalance = 1000;
20 char playAgain;
21
22 srand( time( 0 ) );
23
24 do {
25 cout << "You have $" << bankBalance
26 << " in the bank.\nPlace your wager: ";
27 cin >> wager;
28
29 while ( wager <= 0 || wager > bankBalance ) {
30 cout << "Please bet a valid amount.\n";
31 cin >> wager;
32 }
33
34 result = craps();
35
36 if ( result == LOST ) {
37 bankBalance -= wager;
38 cout << "Your new bank balance is $" << bankBalance << "\n";
39
40 if ( bankBalance == 0 ) {
41 cout << "Sorry. You Busted! Thank You For Playing.\n";
42 break;
43 }
44 }
45 else {
46 bankBalance += wager;
47 cout << "Your new bank balance is $" << bankBalance << "\n";
48 }
49
50 cout << "Would you like to try your luck again (y/n)? ";
51 cin >> playAgain;
52 } while ( playAgain == 'y' || playAgain == 'Y' );
53
54 cout << endl;
55
56 return 0;
57 }
58
Chapter 3 Functions Solutions 115
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
59 int rollDice( void )
60 {
61 int die1, die2, workSum;
62
63 die1 = 1 + rand() % 6;
64 die2 = 1 + rand() % 6;
65 workSum = die1 + die2;
66 cout << "Player rolled " << die1 << " + " << die2 << " = "
67 << workSum << '\n';
68
69 return workSum;
70 }
71
72 int craps( void )
73 {
74 int gameStatus, sum, myPoint;
75
76 sum = rollDice();
77
78 switch ( sum ) {
79 case 7: case 11:
80 gameStatus = WON;
81 chatter();
82 break;
83 case 2: case 3: case 12:
84 gameStatus = LOST;
85 chatter();
86 break;
87 default:
88 gameStatus = CONTINUE;
89 myPoint = sum;
90 cout << "Point is " << myPoint << '\n';
91 chatter();
92 break;
93 }
94
95 while ( gameStatus == CONTINUE ) {
96 chatter();
97 sum = rollDice();
98
99 if ( sum == myPoint )
100 gameStatus = WON;
101 else if ( sum == 7 )
102 gameStatus = LOST;
103 }
104
105 if ( gameStatus == WON ) {
106 cout << "Player wins\n";
107 return WON;
108 }
109 else {
110 cout << "Player loses\n";
111 return LOST;
112 }
113 }
114
115 void chatter( void )
116 {
117 switch ( 1 + rand() % 9 ) {
118 case 1:
119 cout << "Oh, you're going for broke, huh?";
120 break;
116 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.55 Write a C++ program that uses an inline function circleArea to prompt the user for the radius of a circle and to cal-
culate and print the area of that circle.
121 case 2:
122 cout << "Aw cmon, take a chance!";
123 break;
124 case 3:
125 cout << "Hey, I think this guy is going to break the bank!!";
126 break;
127 case 4:
128 cout << "You're up big. Now's the time to cash in your chips!";
129 break;
130 case 5:
131 cout << "Way too lucky! Those dice have to be loaded!";
132 break;
133 case 6:
134 cout << "Bet it all! Bet it all!";
135 break;
136 case 7:
137 cout << "Can I borrow a chip?";
138 break;
139 case 8:
140 cout << "Let's try our luck at another table.";
141 break;
142 case 9:
143 cout << "You're a cheat! It is just a matter of time"
144 << "\nbefore I catch you!!!";
145 break;
146 }
147
148 cout << endl;
149 }
You have $1000 in the bank.
Place your wager: 1000
Player rolled 5 + 4 = 9
Point is 9
Way too lucky! Those dice have to be loaded!
You're up big. Now's the time to cash in your chips!
Player rolled 5 + 4 = 9
Player wins
Your new bank balance is $2000
Would you like to try your luck again (y/n)? n
1// Exercise 3.55 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8double pi = 3.14159; // global variable
9
10 inline double circleArea( double r ) { return pi * r * r; }
11
12 int main()
13 {
14 double radius;
15
Chapter 3 Functions Solutions 117
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.56 Write a complete C++ program with the two alternate functions specified below, of which each simply triples the variable
count defined in main. Then compare and contrast the two approaches. These two functions are
a) Function tripleCallByValue that passes a copy of count call-by-value, triples the copy and returns the new val-
ue.
b) Function tripleByReference that passes count with true call-by-reference via a reference parameter and triples
the original copy of count through its alias (i.e., the reference parameter).
16 cout << "Enter the radius of the circle: ";
17 cin >> radius;
18 cout << "The area of the circle is " << circleArea( radius ) << endl;
19
20 return 0;
21 }
Enter the radius of the circle: 10
The area of the circle is 314.159
1// Exercise 3.56 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int tripleCallByValue( int );
9void tripleByReference( int & );
10
11 int main()
12 {
13 int value, &valueRef = value;
14
15 cout << "Enter an integer: ";
16 cin >> value;
17
18 cout << "\nValue before call to tripleCallByValue() is: "
19 << value << "\nValue returned from tripleCallByValue() is: "
20 << tripleCallByValue( value )
21 << "\nValue (in main) after tripleCallByValue() is: " << value
22 << "\n\nValue before call to tripleByReference() is: "
23 << value << '\n';
24
25 tripleByReference( valueRef );
26
27 cout << "Value (in main) after call to tripleByReference() is: "
28 << value << endl;
29
30 return 0;
31 }
32
33 int tripleCallByValue( int valueCopy )
34 {
35 return valueCopy *= 3;
36 }
37
38 void tripleByReference( int &aliasRef )
39 {
40 aliasRef *= 3;
41 }
118 Functions Solutions Chapter 3
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.57 What is the purpose of the unary scope resolution operator?
ANS: The unary scope resolution operator is used to access a global variable. In particular, the unary scope resolution oper-
ator is useful when a global variable needs to be accessed and a local varible has the same name.
3.58 Write a program that uses a function template called min to determine the smaller of two arguments. Test the program using
integer, character and floating-point number pairs.
3.59 Write a program that uses a function template called max to determine the largest of three arguments. Test the program
using integer, character and floating-point number pairs.
Enter an integer: 8
Value before call to tripleCallByValue() is: 8
Value returned from tripleCallByValue() is: 24
Value (in main) after tripleCallByValue() is: 8
Value before call to tripleByReference() is: 8
Value (in main) after call to tripleByReference() is: 24
1// Exercise 3.58 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7template < class T >
8void min( T value1, T value2 ) // find the smallest value
9{
10 if ( value1 > value2 )
11 cout << value2 << " is smaller than " << value1;
12 else
13 cout << value1 << " is smaller than " << value2;
14
15 cout << endl;
16 }
17
18 int main()
19 {
20 min( 7, 54 ); // integers
21 min( 4.35, 8.46 ); // doubles
22 min( 'g', 'T' ); // characters
23
24 return 0;
25 }
7 is smaller than 54
4.35 is smaller than 8.46
T is smaller than g
1// Exercise 3.59 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7template < class T >
8void max( T value1, T value2, T value3 ) // find the largest value
Chapter 3 Functions Solutions 119
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3.60 Determine whether the following program segments contain errors. For each error, explain how it can be corrected. Note:
For a particular program segment, it is possible that no errors are present in the segment.
a) template < class A >
int sum( int num1, int num2, int num3 )
{
return num1 + num2 + num3;
}
ANS: The function return type and parameter types should be A.
b) void printResults( int x, int y )
{
cout << "The sum is " << x + y << '\n';
return x + y;
}
ANS: The function specifies a void return type and attempts to return a value. Two possible solutions: (1) change void
to int. or (2) remove the line return x + y;.
c) template < A >
A product( A num1, A num2, A num3 )
{
return num1 * num2 * num3;
}
ANS: Keyword class is needed in the template declaration template <class A>.
d) double cube( int );
int cube( int );
ANS: The signatures are not different. Overloaded functions must have different signatures meaning that the name and
parameter list must be different. If only the returns types differ, the compiler generates an error message.
9{
10 if ( value1 > value2 && value1 > value3 )
11 cout << value1 << " is greater than " << value2
12 << " and " << value3;
13 else if ( value2 > value1 && value2 > value3 )
14 cout << value2 << " is greater than " << value1
15 << " and " << value3;
16 else
17 cout << value3 << " is greater than " << value1
18 << " and " << value2;
19
20 cout << endl;
21 }
22
23
24 int main()
25 {
26 max( 7, 5, 2 ); // integers
27 max( 9.35, 8.461, 94.3 ); // doubles
28 max( '!', 'T', '$' ); // characters
29
30 return 0;
31 }
7 is greater than 5 and 2
94.3 is greater than 9.35 and 8.461
T is greater than ! and $
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4
Arrays
Solutions
Solutions
4.6 Fill in the blanks in each of the following:
a) C++ stores lists of values in .
ANS: arrays.
b) The elements of an array are related by the fact that they .
ANS: have the same name and type.
c) When referring to an array element, the position number contained within square brackets is called a .
ANS: subscript.
d) The names of the four elements of array p are , , and .
ANS: p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ]
e) Naming an array, stating its type and specifying the number of elements in the array is called the array.
ANS: declaring.
f) The process of placing the elements of an array into either ascending or descending order is called .
ANS: sorting.
g) In a double-subscripted array, the first subscript (by convention) identifies the
of an element, and the second subscript (by convention) identifies the
of an element.
ANS: row, column.
h) An m-by-n array contains rows, columns and elements.
ANS: m, n, m x n.
i) The name of the element in row 3 and column 5 of array d is .
ANS: d[ 2 ][ 4 ].
4.7 State which of the following are true and which are false; for those that are false, explain why they are false.
a) To refer to a particular location or element within an array, we specify the name of the array and the value of the par-
ticular element.
ANS: False. The name of the array and the subscript of the array are specified.
b) An array declaration reserves space for the array.
ANS: True.
c) To indicate that 100 locations should be reserved for integer array p, the programmer writes the declaration
p[ 100 ];
ANS: False. A data type must be specified. An example of a correct definition would be: unsigned p[ 100 ];.
Chapter 4 Arrays Solutions 121
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
d) A C++ program that initializes the elements of a 15-element array to zero must contain at least one for statement.
ANS: False. The array can be initialized in a declaration with a member initializer list.
e) A C++ program that totals the elements of a double-subscripted array must contain nested for statements.
ANS: False. The sum of the elements can be obtained without for loops, with one for loop, three for loops, etc.
4.8 Write C++ statements to accomplish each of the following:
a) Display the value of the seventh element of character array f.
ANS: cout << f[ 6 ] << ’\n’;
b) Input a value into element 4 of single-subscripted floating-point array b.
ANS: cin >> b[ 4 ];
c) Initialize each of the 5 elements of single-subscripted integer array g to 8.
ANS:
int g[ 5 ] = { 8, 8, 8, 8, 8 };
or
for ( int j = 0; j < 5; ++j )
g[ j ] = 8;
d) Total and print the elements of floating-point array c of 100 elements.
ANS:
for ( int k = 0; k < 5; ++k ) {
total += c[ k ]; // assume total declared and initalized
cout << c[ k ] << ’\n’
}
e) Copy array a into the first portion of array b. Assume double a[ 11 ], b[ 34 ];
ANS:
for ( int i = 0; i < 11; ++i )
b[ i ] = a[ i ];
f) Determine and print the smallest and largest values contained in 99-element floating-point array w.
ANS:
// assume all variables declared and initialized
for ( int j = 0; j < 99; ++j )
if ( w[ j ] < smallest )
smallest = w[ j ];
else if ( w[ j ] > largest )
largest = w[ j ];
4.9 Consider a 2-by-3 integer array t.
a) Write a declaration for t.
ANS: int t[ 2 ][ 3 ];
b) How many rows does t have?
ANS: 2
c) How many columns does t have?
ANS: 3
d) How many elements does t have?
ANS: 6
e) Write the names of all the elements in the second row of t.
ANS: t[ 1 ][ 0 ], t[ 1 ][ 1 ], t[ 1 ][ 2 ]
f) Write the names of all the elements in the third column of t.
ANS: t[ 0 ][ 2 ], t[ 1 ][ 2 ]
g) Write a single statement that sets the element of t in row 1 and column 2 to zero.
ANS: t[ 0 ][ 1 ] = 0;
h) Write a series of statements that initialize each element of t to zero. Do not use a repetition structure.
ANS:
t[ 0 ][ 0 ] = 0;
t[ 0 ][ 1 ] = 0;
t[ 0 ][ 2 ] = 0;
t[ 1 ][ 0 ] = 0;
t[ 1 ][ 1 ] = 0;
t[ 1 ][ 2 ] = 0;
122 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
i) Write a nested for structure that initializes each element of t to zero.
ANS:
for ( int i = 0; i < 2; ++i )
for ( int j = 0; j < 3; ++j )
t[ i ][ j ] = 0;
j) Write a statement that inputs the values for the elements of t from the terminal.
ANS:
for ( int r = 0; r < 2; ++r )
for ( int c = 0; c < 3; ++c )
t[ r ][ c ] = 0;
k) Write a series of statements that determine and print the smallest value in array t.
ANS:
int smallest = t[ 0 ][ 0 ];
for ( int r = 1; r < 2; ++r )
for ( int c = 1; c < 3; ++c )
if ( t[ r ][ c ] < smallest )
smallest = t[ r ][ c ];
cout << smallest;
l) Write a statement that displays the elements of the first row of t
ANS: cout << t[ 0 ][ 0 ] << ’ ’ << t[ 0 ][ 1 ] << ’ ’ << t[ 0 ][ 2 ] << ’\n’;
m) Write a statement that totals the elements of the fourth column of t.
ANS: t does not contain a fourth column.
n) Write a series of statements that prints the array t in neat, tabular format. List the column subscripts as headings across
the top and list the row subscripts at the left of each row.
ANS:
cout << " 0 1 2\n";
for ( int r = 0; r < 2; ++r ) {
cout << r << ’ ’;
for ( int c = 0; c < 3; ++c )
cout << t[ r ][ c ] << " ";
cout << ’\n’;
}
4.10 Use a single-subscripted array to solve the following problem. A company pays its salespeople on a commission basis. The
salespeople receive $200 per week plus 9 percent of their gross sales for that week. For example, a salesperson who grosses $5000
in sales in a week receives $200 plus 9 percent of $5000, or a total of $650. Write a program (using an array of counters) that de-
termines how many of the salespeople earned salaries in each of the following ranges (assume that each salesperson’s salary is t run-
cated to an integer amount):
a) $200–$299
b) $300–$399
c) $400–$499
d) $500–$599
e) $600–$699
f) $700–$799
g) $800–$899
h) $900–$999
i) $1000 and over
1// Exercise 4.10 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
Chapter 4 Arrays Solutions 123
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
9#include <iomanip>
10
11 using std::setprecision;
12 using std::setiosflags;
13
14 void wages( int [] );
15 void display( const int [] );
16
17 int main()
18 {
19 int salaries[ 11 ] = { 0 };
20
21 cout << setiosflags( ios::fixed | ios::showpoint );
22 wages( salaries );
23 display( salaries );
24
25 return 0;
26 }
27
28 void wages( int money[] )
29 {
30 double sales, i = 0.09;
31
32 cout << "Enter employee gross sales (-1 to end): ";
33 cin >> sales;
34
35 while ( sales != -1 ) {
36 double salary = 200.0 + sales * i;
37 cout << setprecision( 2 ) << "Employee Commission is $"
38 << salary << '\n';
39
40 int x = static_cast< int > ( salary ) / 100;
41 ++money[ ( x < 10 ? x : 10 ) ];
42
43 cout << "\nEnter employee gross sales (-1 to end): ";
44 cin >> sales;
45 }
46 }
47
48 void display( const int dollars[] )
49 {
50 cout << "Employees in the range:";
51 for ( int i = 2; i < 10; ++i )
52 cout << "\n$" << i << "00-$" << i << "99 : " << dollars[ i ];
53
54 cout << "\nOver $1000: " << dollars[ 10 ] << endl;
55 }
124 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.11 The bubble sort presented in Fig. 4.16 is inefficient for large arrays. Make the following simple modifications to improve
the performance of the bubble sort:
a) After the first pass, the largest number is guaranteed to be in the highest-numbered element of the array; after the second
pass, the two highest numbers are “in place,” and so on. Instead of making nine comparisons on every pass, modify the
bubble sort to make eight comparisons on the second pass, seven on the third pass, and so on.
b) The data in the array may already be in the proper order or near-proper order, so why make nine passes if fewer will
suffice? Modify the sort to check at the end of each pass if any swaps have been made. If none have been made, then
the data must already be in the proper order, so the program should terminate. If swaps have been made, then at least
one more pass is needed.
Enter employee gross sales (-1 to end): 10000
Employee Commission is $1100.00
Enter employee gross sales (-1 to end): 4235
Employee Commission is $581.15
Enter employee gross sales (-1 to end): 600
Employee Commission is $254.00
Enter employee gross sales (-1 to end): 12500
Employee Commission is $1325.00
Enter employee gross sales (-1 to end): -1
Employees in the range:
$200-$299 : 1
$300-$399 : 0
$400-$499 : 0
$500-$599 : 1
$600-$699 : 0
$700-$799 : 0
$800-$899 : 0
$900-$999 : 0
Over $1000: 2
1// Exercise 4.11 Part A Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <iomanip>
8
9using std::setw;
10
11 int main()
12 {
13 const int SIZE = 10;
14 int a[ SIZE ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 };
15 int hold, numberOfComp = 0, comp;
16
17 cout << "Data items in original order\n";
18 for ( int i = 0; i < SIZE; ++i )
19 cout << setw( 4 ) << a[ i ];
20
21 cout << "\n\n";
22
23 for ( int pass = 1; pass < SIZE; ++pass ) {
24 cout << "After pass " << pass - 1 << ": ";
25
Chapter 4 Arrays Solutions 125
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
26 for ( comp = 0; comp < SIZE - pass; ++comp ) {
27 ++numberOfComp;
28
29 if ( a[ comp ] > a[ comp + 1 ] ) {
30 hold = a[ comp ];
31 a[ comp ] = a[ comp + 1 ];
32 a[ comp + 1 ] = hold;
33 }
34
35 cout << setw( 3 ) << a[ comp ];
36 }
37
38 cout << setw( 3 ) << a[ comp ] << '\n'; // print last array value
39 }
40
41 cout << "\nData items in ascending order\n";
42
43 for ( int j = 0; j < SIZE; ++j )
44 cout << setw( 4 ) << a[ j ];
45
46 cout << "\nNumber of comparisons = " << numberOfComp << endl;
47
48 return 0;
49 }
Data items in original order
2 6 4 8 10 12 89 68 45 37
After pass 0: 2 4 6 8 10 12 68 45 37 89
After pass 1: 2 4 6 8 10 12 45 37 68
After pass 2: 2 4 6 8 10 12 37 45
After pass 3: 2 4 6 8 10 12 37
After pass 4: 2 4 6 8 10 12
After pass 5: 2 4 6 8 10
After pass 6: 2 4 6 8
After pass 7: 2 4 6
After pass 8: 2 4
Data items in ascending order
2 4 6 8 10 12 37 45 68 89
Number of comparisons = 45
1// Exercise 4.11 Part B Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <iomanip>
8
9using std::setw;
10
11 int main()
12 {
13 const int SIZE = 10;
14 int a[ SIZE ] = { 6, 4, 2, 8, 10, 12, 37, 45, 68, 89 };
15 int hold, numberOfComp = 0, comp;
16 bool swapCheck = true;
17
18 cout << "Data items in original order\n";
126 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.12 Write single statements that perform the following single-subscripted array operations:
a) Initialize the 10 elements of integer array counts to zero.
ANS: int counts[ 10 ] = { 0 };
b) Add 1 to each of the 15 elements of integer array bonus.
ANS:
for ( int i = 0; i < 15; ++i )
++bonus[ i ];
c) Read 12 values for double array monthlyTemperatures from the keyboard.
ANS:
for ( int p = 0; p < 12; ++p )
cin >> monthlyTemperatures[ p ];
d) Print the 5 values of integer array bestScores in column format.
19 for ( int i = 0; i < SIZE; ++i )
20 cout << setw( 4 ) << a[ i ];
21
22 cout << "\n\n";
23
24 for ( int pass = 1; pass < SIZE - 1 && swapCheck == true; ++pass ) {
25 cout << "After pass " << pass - 1 << ": ";
26 swapCheck = false; // assume no swaps will be made
27
28 for ( comp = 0; comp < SIZE - pass; ++comp ) {
29 ++numberOfComp;
30
31 if ( a[ comp ] > a[ comp + 1 ] ) {
32 hold = a[ comp ];
33 a[ comp ] = a[ comp + 1 ];
34 a[ comp + 1 ] = hold;
35 swapCheck = true; // a swap has been made
36 }
37
38 cout << setw( 3 ) << a[ comp ];
39 }
40
41 cout << setw( 3 ) << a[ comp ] << '\n'; // print last array value
42 }
43
44 cout << "\nData items in ascending order\n";
45
46 for ( int q = 0; q < SIZE; ++q )
47 cout << setw( 4 ) << a[ q ];
48
49 cout << "\nNumber of comparisons = " << numberOfComp << endl;
50
51 return 0;
52 }
Data items in original order
6 4 2 8 10 12 37 45 68 89
After pass 0: 4 2 6 8 10 12 37 45 68 89
After pass 1: 2 4 6 8 10 12 37 45 68
After pass 2: 2 4 6 8 10 12 37 45
Data items in ascending order
2 4 6 8 10 12 37 45 68 89
Number of comparisons = 24
Chapter 4 Arrays Solutions 127
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
ANS:
for ( int u = 0; u < 5; ++u )
cout << bestScores[ u ] << ’\t’;
4.13 Find the error(s) in each of the following statements:
a) Assume that: char str[ 5 ];
cin >> str; // User types hello
ANS: Inadequate length. The string input exceeds the valid subscript range.
b) Assume that: int a[ 3 ];
cout << a[ 1 ] << " " << a[ 2 ] << " " << a[ 3 ] << endl;
ANS: a[ 3 ] is not a valid location in the array. a[ 2 ] is the last valid location.
c) double f[ 3 ] = { 1.1, 10.01, 100.001, 1000.0001 };
ANS: Too many initializers in the initializer list. Only 1, 2, or 3 values may be provided in the initializer list.
d) Assume that: double d[ 2 ][ 10 ];
d[ 1, 9 ] = 2.345;
ANS: Incorrect syntax array element access. d[ 1 ][ 9 ] is the correct syntax.
4.14 Modify the program of Fig. 4.17 so function mode is capable of handling a tie for the mode value. Also modify function
median so the two middle elements are averaged in an array with an even number of elements.
1// Exercise 4.14 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::ios;
7
8#include <iomanip>
9
10 using std::setw;
11 using std::setprecision;
12 using std::setiosflags;
13
14 void mean( int [], int );
15 void median( int [], int );
16 void mode( int [], int [], int, int );
17
18 int main()
19 {
20 const int SIZE = 100, MAXFREQUENCY = 10;
21 int response[ SIZE ] = { 6, 7, 8, 9, 8, 7, 8, 9, 8, 9,
22 7, 8, 9, 5, 9, 8, 7, 8, 7, 1,
23 6, 7, 8, 9, 3, 9, 8, 7, 1, 7,
24 7, 8, 9, 8, 9, 8, 9, 7, 1, 9,
25 6, 7, 8, 7, 8, 7, 9, 8, 9, 2,
26 7, 8, 9, 8, 9, 8, 9, 7, 5, 3,
27 5, 6, 7, 2, 5, 3, 9, 4, 6, 4,
28 7, 8, 9, 6, 8, 7, 8, 9, 7, 1,
29 7, 4, 4, 2, 5, 3, 8, 7, 5, 6,
30 4, 5, 6, 1, 6, 5, 7, 8, 7, 9 };
31 int frequency[ MAXFREQUENCY ] = { 0 };
32
33 mean( response, SIZE );
34 median( response, SIZE );
35 mode( frequency, response, SIZE, MAXFREQUENCY );
36
37 return 0;
38 }
39
40 void mean( int answer[], int size ) // mean
41 {
128 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
42 int total = 0;
43
44 cout << "******\nMean\n******\n";
45
46 for ( int j = 0; j < size; ++j )
47 total += answer[ j ];
48
49 cout << setiosflags( ios::fixed | ios::showpoint )
50 << "The mean is the average value of the data items.\n"
51 << "The mean is equal to the total of all the data\n"
52 << "items divided by the number of data items (" << size << ")."
53 << "\nThe mean value for this run is: " << total
54 << " / " << size << " = " << setprecision( 2 )
55 << static_cast< double > ( total ) / size << "\n\n";
56 }
57
58 void median( int answer[], int size ) // median
59 {
60 int hold;
61 bool firstRow = true;
62
63 cout << "\n******\nMedian\n******\n"
64 << "The unsorted array of responses is\n";
65
66 for ( int loop = 0; loop < size; loop++ ) {
67 if ( loop % 20 == 0 && !firstRow )
68 cout << '\n';
69
70 cout << setw( 2 ) << answer[ loop ];
71 firstRow = false;
72 }
73
74 cout << "\n\n";
75
76 for ( int pass = 0; pass <= size - 2; ++pass )
77 for ( int k = 0; k <= size - 2; ++k )
78 if ( answer[ k ] > answer[ k + 1 ] ) {
79 hold = answer[ k ];
80 answer[ k ] = answer[ k + 1 ];
81 answer[ k + 1 ] = hold;
82 }
83
84 cout << "The sorted array is\n";
85
86 firstRow = true;
87 for ( int j = 0; j < size; ++j ) {
88 if ( j % 20 == 0 && !firstRow )
89 cout << '\n';
90
91 cout << setw( 2 ) << answer[ j ];
92 firstRow = false;
93 }
94
95 cout << "\n\n";
96
97 if ( size % 2 == 0 ) // even number of elements
98 cout << "The median is the average of elements " << ( size + 1 ) / 2
99 << " and " << 1 + ( size + 1 ) / 2 << " of the sorted "
100 << size << " element array.\nFor this run the median is "
101 << setprecision( 1 )
102 << static_cast< double >( answer[ ( size + 1 ) / 2 ] +
103 answer[ ( size + 1 ) / 2 + 1 ] ) / 2
Chapter 4 Arrays Solutions 129
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
104 << "\n\n";
105 else // odd number of elements
106 cout << "The median is element " << ( size + 1 ) / 2 << " of "
107 << "the sorted " << size << " element array.\n"
108 << "For this run the median is " << answer[ ( size + 1 ) / 2 - 1 ]
109 << "\n\n";
110 }
111
112 void mode( int freq[], int answer[], int aSize, int fSize )
113 {
114 const int SIZE2 = 10;
115 int largest = 0, array[ SIZE2 ] = { 0 }, count = 0;
116
117 cout << "\n******\nMode\n******\n";
118
119 for ( int rating = 1; rating < fSize; ++rating )
120 freq[ rating ] = 0;
121
122 for ( int loop = 0; loop < aSize; ++loop )
123 ++freq[ answer[ loop ] ];
124
125 cout << setw( 13 ) << "Response" << setw( 11 ) << "Frequency" << setw( 19 )
126 << "Histogram\n\n" << setw( 55 ) << "1 1 2 2\n"
127 << setw( 56 ) << "5 0 5 0 5\n\n";
128
129 for ( int r = 1; r < fSize; ++r ) {
130 cout << setw( 8 ) << rating << setw( 11 ) << freq[ r ] << " ";
131
132 if ( freq[ r ] > largest ) {
133 largest = freq[ r ];
134
135 for ( int v = 0; v < SIZE2; ++v )
136 array[ v ] = 0;
137
138 array[ r ] = largest;
139 ++count;
140 }
141 else if ( freq[ r ] == largest ) {
142 array[ r ] = largest;
143 ++count;
144 }
145
146 for ( int b = 1; b <= freq[ r ]; b++ )
147 cout << '*';
148
149 cout << '\n';
150 }
151
152 cout << ( count > 1 ? "\nThe modes are: " : "\nThe mode is: " );
153
154 for ( int m = 1; m < SIZE2; ++m )
155 if ( array[ m ] != 0 )
156 cout << m << " with a frequency of " << array[ m ] << "\n\t\t";
157
158 cout << endl;
159 }
130 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.15 Use a single-subscripted array to solve the following problem. Read in 20 numbers, each of which is between 10 and 100,
inclusive. As each number is read, print it only if it is not a duplicate of a number already read. Provide for the “worst case” in which
all 20 numbers are different. Use the smallest possible array to solve this problem.
******
Mean
******
The mean is the average value of the data items.
The mean is equal to the total of all the data
items divided by the number of data items (100).
The mean value for this run is: 662 / 100 = 6.62
******
Median
******
The unsorted array of responses is
6 7 8 9 8 7 8 9 8 9 7 8 9 5 9 8 7 8 7 1
6 7 8 9 3 9 8 7 1 7 7 8 9 8 9 8 9 7 1 9
6 7 8 7 8 7 9 8 9 2 7 8 9 8 9 8 9 7 5 3
5 6 7 2 5 3 9 4 6 4 7 8 9 6 8 7 8 9 7 1
7 4 4 2 5 3 8 7 5 6 4 5 6 1 6 5 7 8 7 9
The sorted array is
1 1 1 1 1 2 2 2 3 3 3 3 4 4 4 4 4 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 8 8
8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
The median is the average of elements 50 and 51 of the sorted 100 element array.
For this run the median is 7.0
******
Mode
******
Response Frequency Histogram
1 1 2 2
5 0 5 0 5
10 5 *****
10 3 ***
10 4 ****
10 5 *****
10 8 ********
10 9 *********
10 23 ***********************
10 23 ***********************
10 20 ********************
The modes are: 7 with a frequency of 23
8 with a frequency of 23
Chapter 4 Arrays Solutions 131
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.16 Label the elements of 3-by-5 double-subscripted array sales to indicate the order in which they are set to zero by the
following program segment:
for ( row = 0; row < 3; row++ )
for ( column = 0; column < 5; column++ )
sales[ row ][ column ] = 0;
1// Exercise 4.15 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <iomanip>
9
10 using std::setw;
11
12 int main()
13 {
14 const int SIZE = 20;
15 int a[ SIZE ] = { 0 }, subscript = 0, duplicate, value;
16
17 cout << "Enter 20 integers between 10 and 100:\n";
18
19 for ( int i = 0; i < SIZE; ++i ) {
20 duplicate = 0;
21 cin >> value;
22
23 for ( int j = 0; j < subscript; ++j )
24 if ( value == a[ j ] ) {
25 duplicate = 1;
26 break;
27 }
28
29 if ( !duplicate )
30 a[ subscript++ ] = value;
31 }
32
33 cout << "\nThe nonduplicate values are:\n";
34
35 for ( i = 0; a[ i ] != 0; ++i )
36 cout << setw( 4 ) << a[ i ];
37
38 cout << endl;
39
40 return 0;
41 }
Enter 20 integers between 10 and 100:
22 56 78 94 22 94 38 10 11 12 22 12 13 14 15 16 17 88 88 77
The nonduplicate values are:
22 56 78 94 38 10 11 12 13 14 15 16 17 88 77
132 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
ANS:
sales[ 0 ][ 0 ], sales[ 0 ][ 1 ], sales[ 0 ][ 2 ], sales[ 0 ][ 3 ],
sales[ 0 ][ 4 ], sales[ 1 ][ 0 ], sales[ 1 ][ 1 ], sales[ 1 ][ 2 ],
sales[ 1 ][ 3 ], sales[ 1 ][ 4 ], sales[ 2 ][ 0 ], sales[ 2 ][ 1 ],
sales[ 2 ][ 2 ], sales[ 2 ][ 3 ], sales[ 2 ][ 4 ]
4.17 Write a program that simulates the rolling of two dice. The program should use rand to roll the first die and should use
rand again to roll the second die. The sum of the two values should then be calculated. Note: Since each die can show an integer
value from 1 to 6, then the sum of the two values will vary from 2 to 12, with 7 being the most frequent sum and 2 and 12 being the
least frequent sums. Figure 4.24 shows the 36 possible combinations of the two dice. Your program should roll the two dice 36,000
times. Use a single-subscripted array to tally the numbers of times each possible sum appears. Print the results in a tabular format.
Also, determine if the totals are reasonable (i.e., there are six ways to roll a 7, so approximately one sixth of all the rolls should be 7).
Fig. 4.24 The 36 possible outcomes of rolling two dice.
1// Exercise 4.17 Solution
2#include <iostream>
3
4using std::cout;
5using std::ios;
6
7#include <iomanip>
8
9using std::setw;
10 using std::setprecision;
11 using std::setiosflags;
12
13 #include <cstdlib>
14 #include <ctime>
15
16 int main()
17 {
18 const long ROLLS = 36000;
19 const int SIZE = 13;
20 // array exepected contains counts for the expected
21 // number of times each sum occurs in 36 rolls of the dice
22 int expected[ SIZE ] = { 0, 0, 1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1 };
23 int x, y, sum[ SIZE ] = { 0 };
24
25 srand( time( 0 ) );
26
27 for ( long i = 1; i <= ROLLS; ++i ) {
28 x = 1 + rand() % 6;
29 y = 1 + rand() % 6;
30 ++sum[ x + y ];
31 }
32
33 cout << setw( 10 ) << "Sum" << setw( 10 ) << "Total" << setw( 10 )
123456
1
2
3
4
5
6
876543
765432
1098765
987654
987
678
10
910 11
11 12
Chapter 4 Arrays Solutions 133
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.18 What does the following program do?
4.19 Write a program that runs 1000 games of craps and answers the following questions:
a) How many games are won on the 1st roll, 2nd roll, …, 20th roll, and after the 20th roll?
34 << "Expected" << setw( 10 ) << "Actual\n"
35 << setiosflags( ios::fixed | ios::showpoint );
36
37 for ( int j = 2; j < SIZE; ++j )
38 cout << setw( 10 ) << j << setw( 10 ) << sum[ j ] << setprecision( 3 )
39 << setw( 9 ) << 100.0 * expected[ j ] / 36 << "%" << setprecision(3)
40 << setw( 9 ) << 100.0 * sum[ j ] / 36000 << "%\n";
41
42 return 0;
43 }
Sum Total Expected Actual
2 996 2.778% 2.767%
3 2015 5.556% 5.597%
4 3005 8.333% 8.347%
5 3965 11.111% 11.014%
6 5003 13.889% 13.897%
7 5985 16.667% 16.625%
8 5000 13.889% 13.889%
9 4035 11.111% 11.208%
10 3042 8.333% 8.450%
11 1947 5.556% 5.408%
12 1007 2.778% 2.797%
1// ex04_18.cpp
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int whatIsThis( int [], int );
8
9int main()
10 {
11 const int arraySize = 10;
12 int a[ arraySize ] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
13
14 int result = whatIsThis( a, arraySize );
15
16 cout << "Result is " << result << endl;
17 return 0;
18 }
19
20 int whatIsThis( int b[], int size )
21 {
22 if ( size == 1 )
23 return b[ 0 ];
24 else
25 return b[ size - 1 ] + whatIsThis( b, size - 1 );
26 }
Result is 55
134 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
b) How many games are lost on the 1st roll, 2nd roll, …, 20th roll, and after the 20th roll?
c) What are the chances of winning at craps? (Note: You should discover that craps is one of the fairest casino games.
What do you suppose this means?)
d) What is the average length of a game of craps?
e) Do the chances of winning improve with the length of the game?
1// Exercise 4.19 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::ios;
7
8#include <iomanip>
9
10 using std::setw;
11 using std::setprecision;
12 using std::setiosflags;
13
14 #include <cstdlib>
15 #include <ctime>
16
17 int rollDice( void );
18
19 int main()
20 {
21 enum Outcome { CONTINUE, WIN, LOSE };
22 const int SIZE = 22, ROLLS = 1000;
23 int gameStatus, sum, myPoint, roll, length = 0, wins[ SIZE ] = { 0 },
24 losses[ SIZE ] = { 0 }, winSum = 0, loseSum = 0;
25
26 srand( time( 0 ) );
27
28 for ( int i = 1; i <= ROLLS; ++i ) {
29 sum = rollDice();
30 roll = 1;
31
32 switch ( sum ) {
33 case 7: case 11:
34 gameStatus = WIN;
35 break;
36 case 2: case 3: case 12:
37 gameStatus = LOSE;
38 break;
39 default:
40 gameStatus = CONTINUE;
41 myPoint = sum;
42 break;
43 }
44
45 while ( gameStatus == CONTINUE ) {
46 sum = rollDice();
47 ++roll;
48
49 if ( sum == myPoint )
50 gameStatus = WIN;
51 else if ( sum == 7 )
52 gameStatus = LOSE;
53 }
54
55 if ( roll > 21 )
Chapter 4 Arrays Solutions 135
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
56 roll = 21;
57
58 if ( gameStatus == WIN ) {
59 ++wins[ roll ];
60 ++winSum;
61 }
62 else {
63 ++losses[ roll ];
64 ++loseSum;
65 }
66 }
67
68 cout << "Games won or lost after the 20th roll"
69 << "\nare displayed as the 21st roll.\n\n";
70
71 for ( int z = 1; z <= 21; ++z )
72 cout << setw( 3 ) << wins[ z ] << " games won and " << setw( 3 )
73 << losses[ z ] << " games lost on roll " << z << '\n';
74
75 // calculate chances of winning
76 cout << setiosflags( ios::fixed | ios::showpoint )
77 << "\nThe chances of winning are " << winSum << " / "
78 << winSum + loseSum << " = " << setprecision( 2 )
79 << 100.0 * winSum / ( winSum + loseSum ) << "%\n";
80
81 // calculate average length of game
82 for ( int k = 1; k <= 21; ++k )
83 length += wins[ k ] * k + losses[ k ] * k;
84
85 cout << "The average game length is " << setprecision( 2 )
86 << length / 1000.0 << " rolls." << endl;
87
88 return 0;
89 }
90
91 int rollDice( void )
92 {
93 int die1, die2, workSum;
94
95 die1 = 1 + rand() % 6;
96 die2 = 1 + rand() % 6;
97 workSum = die1 + die2;
98
99 return workSum;
100 }
136 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.20 (Airline Reservations System) A small airline has just purchased a computer for its new automated reservations system. You
have been asked to program the new system. You are to write a program to assign seats on each flight of the airline’s only plane
(capacity: 10 seats).
Your program should display the following menu of alternatives— Please type 1 for "First Class" and Please
type 2 for "Economy". If the person types 1, your program should assign a seat in the first class section (seats 1-5). If the per-
son types 2, your program should assign a seat in the economy section (seats 6-10). Your program should print a boarding pass
indicating the person’s seat number and whether it is in the first class or economy section of the plane.
Use a single-subscripted array to represent the seating chart of the plane. Initialize all the elements of the array to 0 to indicate
that all seats are empty. As each seat is assigned, set the corresponding elements of the array to 1 to indicate that the seat is no
longer available.
Your program should, of course, never assign a seat that has already been assigned. When the first class section is full, your
program should ask the person if it is acceptable to be placed in the nonsmoking section (and vice versa). If yes, then make the
appropriate seat assignment. If no, then print the message "Next flight leaves in 3 hours."
Games won or lost after the 20th roll
are displayed as the 21st roll.
225 games won and 102 games lost on roll 1
72 games won and 106 games lost on roll 2
63 games won and 86 games lost on roll 3
40 games won and 64 games lost on roll 4
28 games won and 32 games lost on roll 5
21 games won and 37 games lost on roll 6
12 games won and 26 games lost on roll 7
13 games won and 11 games lost on roll 8
9 games won and 8 games lost on roll 9
2 games won and 10 games lost on roll 10
3 games won and 9 games lost on roll 11
2 games won and 6 games lost on roll 12
1 games won and 0 games lost on roll 13
1 games won and 3 games lost on roll 14
2 games won and 0 games lost on roll 15
1 games won and 1 games lost on roll 16
0 games won and 1 games lost on roll 17
1 games won and 0 games lost on roll 18
0 games won and 0 games lost on roll 19
0 games won and 1 games lost on roll 20
1 games won and 0 games lost on roll 21
The chances of winning are 497 / 1000 = 49.70%
The average game length is 3.36 rolls.
1// Exercise 4.20 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cctype>
9
10 int main()
11 {
12 const int SEATS = 11;
13 int plane[ SEATS ] = { 0 }, people = 0, economy = 1, firstClass = 6,
14 choice;
15 char response;
16
Chapter 4 Arrays Solutions 137
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
17 while ( people < 10 ) {
18 cout << "\nPlease type 1 for \"firstClass\"\n"
19 << "Please type 2 for \"economy\"\n";
20 cin >> choice;
21
22 if ( choice == 1 ) {
23 if ( !plane[ firstClass ] && firstClass <= 10 ) {
24 cout << "Your seat assignment is " << firstClass << ' ';
25 plane[ firstClass++ ] = 1;
26 ++people;
27 }
28 else if ( firstClass > 10 && economy <= 5 ) {
29 cout << "The firstClass section is full.\n"
30 << "Would you like to sit in the economy"
31 << " section (Y or N)? ";
32 cin >> response;
33
34 if ( toupper( response ) == 'Y' ) {
35 cout << "Your seat assignment is " << economy << ' ';
36 plane[ economy++ ] = 1;
37 ++people;
38 }
39 else
40 cout << "Next flight leaves in 3 hours.\n";
41 }
42 else
43 cout << "Next flight leaves in 3 hours.\n";
44 }
45 else {
46 if ( !plane[ economy ] && economy <= 5 ) {
47 cout << "Your seat assignment is " << economy << '\n';
48 plane[ economy++ ] = 1;
49 ++people;
50 }
51 else if ( economy > 5 && firstClass <= 10 ) {
52 cout << "The economy section is full.\n"
53 << "Would you like to sit in the firstClass"
54 << " section (Y or N)? ";
55 cin >> response;
56
57 if ( toupper( response ) == 'Y' ) {
58 cout << "Your seat assignment is " << firstClass << '\n';
59 plane[ firstClass++ ] = 1;
60 ++people;
61 }
62 else
63 cout << "Next flight leaves in 3 hours.\n";
64 }
65 else
66 cout << "Next flight leaves in 3 hours.\n";
67 }
68 }
69
70 cout << "All seats for this flight are sold." << endl;
71
72 return 0;
73 }
138 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.21 What does the following program do?
4.22 Use a double-subscripted array to solve the following problem. A company has four salespeople (1 to 4) who sell five dif-
ferent products (1 to 5). Once a day, each salesperson passes in a slip for each different type of product sold. Each slip contains the
following:
a) The salesperson number
Please type 1 for "firstClass"
Please type 2 for "economy"
1
...
Please type 1 for "firstClass"
Please type 2 for "economy"
1
Your seat assignment is 9
Please type 1 for "firstClass"
Please type 2 for "economy"
1
Your seat assignment is 10
Please type 1 for "firstClass"
Please type 2 for "economy"
2
Your seat assignment is 5
All seats for this flight are sold.
1// ex04_21.cpp
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7void someFunction( int [], int );
8
9int main()
10 {
11 const int arraySize = 10;
12 int a[ arraySize ] =
13 32, 27, 64, 18, 95, 14, 90, 70, 60, 37 };
14
15 cout << "The values in the array are:" << endl;
16 someFunction( a, arraySize );
17 cout << endl;
18
19 return 0;
20 }
21
22 void someFunction( int b[], int size )
23 {
24 if ( size > 0 ) {
25 someFunction( &b[ 1 ], size - 1 );
26 cout << b[ 0 ] << " ";
27 }
28 }
The values in the array are:
37 60 70 90 14 95 18 64 27 32
Chapter 4 Arrays Solutions 139
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
b) The product number
c) The total dollar value of that product sold that day
Thus, each salesperson passes in between 0 and 5 sales slips per day. Assume that the information from all of the slips for last month
is available. Write a program that will read all this information for last month’s sales and summarize the total sales by salesperson
by product. All totals should be stored in the double-subscripted array sales. After processing all the information for last month,
print the results in tabular format with each of the columns representing a particular salesperson and each of the rows representing
a particular product. Cross total each row to get the total sales of each product for last month; cross total each column to get the total
sales by salesperson for last month. Your tabular printout should include these cross totals to the right of the totaled rows and to the
bottom of the totaled columns.
1// Exercise 4.22 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setw;
12 using std::setprecision;
13 using std::setiosflags;
14
15 int main()
16 {
17 const int PEOPLE = 5, PRODUCTS = 6;
18 double sales[ PEOPLE ][ PRODUCTS ] = { 0.0 }, value, totalSales,
19 productSales[ PRODUCTS ] = { 0.0 };
20 int salesPerson, product;
21
22 cout << "Enter the salesperson (1 - 4), product number (1 - 5), "
23 << "and total sales.\nEnter -1 for the salesperson"
24 << " to end input.\n";
25 cin >> salesPerson;
26
27 while ( salesPerson != -1 ) {
28 cin >> product >> value;
29 sales[ salesPerson ][ product ] += value;
30 cin >> salesPerson;
31 }
32
33 cout << "\nThe total sales for each salesperson are displayed"
34 << " at the end of each row,\n" << "and the total sales for"
35 << " each product are displayed at the bottom of each\n"
36 << "column.\n " << setw( 12 ) << 1 << setw( 12 ) << 2
37 << setw( 12 ) << 3 << setw( 12 ) << 4 << setw( 12 ) << 5 << setw( 13 )
38 << "Total\n" << setiosflags( ios::fixed | ios::showpoint );
39
40 for ( int i = 1; i < PEOPLE; ++i ) {
41 totalSales = 0.0;
42 cout << i;
43
44 for ( int j = 1; j < PRODUCTS; ++j ) {
45 totalSales += sales[ i ][ j ];
46 cout << setw( 12 ) << setprecision( 2 ) << sales[ i ][ j ];
47 productSales[ j ] += sales[ i ][ j ];
48 }
49
50 cout << setw( 12 ) << setprecision( 2 ) << totalSales << '\n';
51 }
140 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.23 (Turtle Graphics) The Logo language, which is particularly popular among personal computer users, made the concept of
turtle graphics famous. Imagine a mechanical turtle that walks around the room under the control of a C++ program. The turtle
holds a pen in one of two positions, up or down. While the pen is down, the turtle traces out shapes as it moves; while the pen is up,
the turtle moves about freely without writing anything. In this problem, you will simulate the operation of the turtle and create a
computerized sketchpad as well.
Use a 20-by-20 array floor that is initialized to zeros. Read commands from an array that contains them. Keep track of the
current position of the turtle at all times and whether the pen is currently up or down. Assume that the turtle always starts at posi-
tion 0,0 of the floor with its pen up. The set of turtle commands your program must process are as follows:
Suppose that the turtle is somewhere near the center of the floor. The following “program” would draw and print a 12-by-12
square and end with the pen in the up position:
2
5,12
3
5,12
52
53 cout << "\nTotal" << setw( 8 ) << setprecision( 2 ) << productSales[ 1 ];
54
55 for ( int j = 2; j < PRODUCTS; ++j )
56 cout << setw( 12 ) << setprecision( 2 ) << productSales[ j ];
57
58 cout << endl;
59
60 return 0;
61 }
Enter the salesperson (1 - 4), product number (1 - 5), and total sales.
Enter -1 for the salesperson to end input.
1 1 9.99
3 3 5.99
2 2 4.99
-1
The total sales for each salesperson are displayed at the end of each row,
and the total sales for each product are displayed at the bottom of each
column.
1 2 3 4 5 Total
1 9.99 0.00 0.00 0.00 0.00 9.99
2 0.00 4.99 0.00 0.00 0.00 4.99
3 0.00 0.00 5.99 0.00 0.00 5.99
4 0.00 0.00 0.00 0.00 0.00 0.00
Total 9.99 4.99 5.99 0.00 0.00
Command Meaning
1Pen up
2Pen down
3Turn right
4Turn left
5,10 Move forward 10 spaces (or a number other than 10)
6Print the 20-by-20 array
9End of data (sentinel)
Chapter 4 Arrays Solutions 141
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3
5,12
3
5,12
1
6
9
As the turtle moves with the pen down, set the appropriate elements of array floor to 1s. When the 6 command (print) is given,
wherever there is a 1 in the array, display an asterisk or some other character you choose. Wherever there is a zero, display a blank.
Write a program to implement the turtle graphics capabilities discussed here. Write several turtle graphics programs to draw
interesting shapes. Add other commands to increase the power of your turtle graphics language.
1// Exercise 4.23 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8const int MAXCOMMANDS = 100, SIZE = 20;
9
10 int turnRight( int );
11 int turnLeft( int );
12 void getCommands( int [][ 2 ] );
13 void movePen( int, int [][ SIZE ], int, int );
14 void printArray( const int [][ SIZE ] );
15
16 int main()
17 {
18 int floor[ SIZE ][ SIZE ] = { 0 }, command, direction = 0,
19 commandArray[ MAXCOMMANDS ][ 2 ] = { 0 }, distance, count = 0;
20 bool penDown = false;
21
22 getCommands( commandArray );
23 command = commandArray[ count ][ 0 ];
24
25 while ( command != 9 ) {
26 switch ( command ) {
27 case 1:
28 penDown = false;
29 break;
30 case 2:
31 penDown = true;
32 break;
33 case 3:
34 direction = turnRight( direction );
35 break;
36 case 4:
37 direction = turnLeft( direction );
38 break;
39 case 5:
40 distance = commandArray[ count ][ 1 ];
41 movePen( penDown, floor, direction, distance );
42 break;
43 case 6:
44 cout << "\nThe drawing is:\n\n";
45 printArray( floor );
46 break;
47 }
48
49 command = commandArray[ ++count ][ 0 ];
142 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
50 }
51
52 return 0;
53 }
54
55 void getCommands( int commands[][ 2 ] )
56 {
57 int tempCommand;
58
59 cout << "Enter command (9 to end input): ";
60 cin >> tempCommand;
61
62 for ( int i = 0; tempCommand != 9 && i < MAXCOMMANDS; ++i ) {
63 commands[ i ][ 0 ] = tempCommand;
64
65 if ( tempCommand == 5 ) {
66 cin.ignore(); // skip comma
67 cin >> commands[ i ][ 1 ];
68 }
69
70 cout << "Enter command (9 to end input): ";
71 cin >> tempCommand;
72 }
73
74 commands[ i ][ 0 ] = 9; // last command
75 }
76
77 int turnRight( int d )
78 {
79 return ++d > 3 ? 0 : d;
80 }
81
82 int turnLeft( int d )
83 {
84 return --d < 0 ? 3 : d;
85 }
86
87 void movePen( int down, int a[][ SIZE ], int dir, int dist )
88 {
89 static int xPos = 0, yPos = 0;
90 int j; // looping variable
91
92 switch ( dir ) {
93 case 0: // move to the right
94 for ( j = 1; j <= dist && yPos + j < SIZE; ++j )
95 if ( down )
96 a[ xPos ][ yPos + j ] = 1;
97
98 yPos += j - 1;
99 break;
100 case 1: // move down
101 for ( j = 1; j <= dist && xPos + j < SIZE; ++j )
102 if ( down )
103 a[ xPos + j ][ yPos ] = 1;
104
105 xPos += j - 1;
106 break;
107 case 2: // move to the left
108 for ( j = 1; j <= dist && yPos - j >= 0; ++j )
109 if ( down )
110 a[ xPos ][ yPos - j ] = 1;
111
Chapter 4 Arrays Solutions 143
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.24 (Knight’s Tour) One of the more interesting puzzlers for chess buffs is the Knight’s Tour problem, originally proposed by
the mathematician Euler. The question is this: Can the chess piece called the knight move around an empty chessboard and touch
each of the 64 squares once and only once? We study this intriguing problem in depth here.
The knight makes L-shaped moves (over two in one direction and then over one in a perpendicular direction). Thus, from a
square in the middle of an empty chessboard, the knight can make eight different moves (numbered 0 through 7) as shown in Fig.
4.25.
112 yPos -= j - 1;
113 break;
114 case 3: // move up
115 for ( j = 1; j <= dist && xPos - j >= 0; ++j )
116 if ( down )
117 a[ xPos - j ][ yPos ] = 1;
118
119 xPos -= j - 1;
120 break;
121 }
122 }
123
124 void printArray( const int a[][ SIZE ] )
125 {
126 for ( int i = 0; i < SIZE; ++i ) {
127 for ( int j = 0; j < SIZE; ++j )
128 cout << ( a[ i ][ j ] ? '*' : ' ' );
129
130 cout << endl;
131 }
132 }
Enter command (9 to end input): 2
Enter command (9 to end input): 5,6
Enter command (9 to end input): 3
Enter command (9 to end input): 5,12
Enter command (9 to end input): 3
Enter command (9 to end input): 5,12
Enter command (9 to end input): 3
Enter command (9 to end input): 5,12
Enter command (9 to end input): 1
Enter command (9 to end input): 6
Enter command (9 to end input): 9
The drawing is:
*******
* *
* *
* *
* *
* *
* *
* *
* *
* *
* *
* *
*******
144 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Fig. 4.25 The eight possible moves of the knight.
a) Draw an 8-by-8 chessboard on a sheet of paper and attempt a Knight’s Tour by hand. Put a 1 in the first square you
move to, a 2 in the second square, a 3 in the third, etc. Before starting the tour, estimate how far you think you will get,
remembering that a full tour consists of 64 moves. How far did you get? Was this close to your estimate?
b) Now let us develop a program that will move the knight around a chessboard. The board is represented by an 8-by-8
double-subscripted array board. Each of the squares is initialized to zero. We describe each of the eight possible
moves in terms of both their horizontal and vertical components. For example, a move of type 0, as shown in Fig. 4.25,
consists of moving two squares horizontally to the right and one square vertically upward. Move 2 consists of moving
one square horizontally to the left and two squares vertically upward. Horizontal moves to the left and vertical moves
upward are indicated with negative numbers. The eight moves may be described by two single-subscripted arrays,
horizontal and vertical, as follows:
horizontal[ 0 ] = 2
horizontal[ 1 ] = 1
horizontal[ 2 ] = -1
horizontal[ 3 ] = -2
horizontal[ 4 ] = -2
horizontal[ 5 ] = -1
horizontal[ 6 ] = 1
horizontal[ 7 ] = 2
vertical[ 0 ] = -1
vertical[ 1 ] = -2
vertical[ 2 ] = -2
vertical[ 3 ] = -1
vertical[ 4 ] = 1
vertical[ 5 ] = 2
vertical[ 6 ] = 2
vertical[ 7 ] = 1
Let the variables currentRow and currentColumn indicate the row and column of the knight’s current position.
To make a move of type moveNumber, where moveNumber is between 0 and 7, your program uses the statements
currentRow += vertical[ moveNumber ];
currentColumn += horizontal[ moveNumber ];
Keep a counter that varies from 1 to 64. Record the latest count in each square the knight moves to. Remember to test
each potential move to see if the knight has already visited that square, and, of course, test every potential move to
01234567
0
1
2
3
4
5
6
7
2 1
0
7
65
4
3
K
Chapter 4 Arrays Solutions 145
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
make sure that the knight does not land off the chessboard. Now write a program to move the knight around the chess-
board. Run the program. How many moves did the knight make?
c) After attempting to write and run a Knight’s Tour program, you have probably developed some valuable insights. We
will use these to develop a heuristic (or strategy) for moving the knight. Heuristics do not guarantee success, but a care-
fully developed heuristic greatly improves the chance of success. You may have observed that the outer squares are
more troublesome than the squares nearer the center of the board. In fact, the most troublesome, or inaccessible, squares
are the four corners.
Intuition may suggest that you should attempt to move the knight to the most troublesome squares first and leave
open those that are easiest to get to, so when the board gets congested near the end of the tour, there will be a greater
chance of success.
We may develop an “accessibility heuristic” by classifying each of the squares according to how accessible they
are and then always moving the knight to the square (within the knight’s L-shaped moves, of course) that is most inac-
cessible. We label a double-subscripted array accessibility with numbers indicating from how many squares
each particular square is accessible. On a blank chessboard, each center square is rated as 8, each corner square is
rated as 2 and the other squares have accessibility numbers of 3, 4 or 6 as follows:
2 3 4 4 4 4 3 2
3 4 6 6 6 6 4 3
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
3 4 6 6 6 6 4 3
2 3 4 4 4 4 3 2
Now write a version of the Knight’s Tour program using the accessibility heuristic. At any time, the knight should
move to the square with the lowest accessibility number. In case of a tie, the knight may move to any of the tied
squares. Therefore, the tour may begin in any of the four corners. (Note: As the knight moves around the chessboard,
your program should reduce the accessibility numbers as more and more squares become occupied. In this way, at any
given time during the tour, each available square’s accessibility number will remain equal to precisely the number of
squares from which that square may be reached.) Run this version of your program. Did you get a full tour? Now mod-
ify the program to run 64 tours, one starting from each square of the chessboard. How many full tours did you get?
d) Write a version of the Knight’s Tour program which, when encountering a tie between two or more squares, decides
what square to choose by looking ahead to those squares reachable from the “tied” squares. Your program should move
to the square for which the next move would arrive at a square with the lowest accessibility number.
1// Exercise 4.24 Part C Solution
2// Knight's Tour - access version
3// runs one tour
4#include <iostream>
5
6using std::cout;
7using std::endl;
8
9#include <iomanip>
10
11 using std::setw;
12
13 #include <cstdlib>
14 #include <ctime>
15
16 const int SIZE = 8;
17
18 void clearBoard( int [][ SIZE ] );
19 void printBoard( const int [][ SIZE ] );
20 bool validMove( int, int, const int [][ SIZE ] );
21
22 int main()
23 {
24 int board[ SIZE ][ SIZE ], currentRow, currentColumn, moveNumber = 0,
146 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
25 access[ SIZE ][ SIZE ] = { 2, 3, 4, 4, 4, 4, 3, 2,
26 3, 4, 6, 6, 6, 6, 4, 3,
27 4, 6, 8, 8, 8, 8, 6, 4,
28 4, 6, 8, 8, 8, 8, 6, 4,
29 4, 6, 8, 8, 8, 8, 6, 4,
30 4, 6, 8, 8, 8, 8, 6, 4,
31 3, 4, 6, 6, 6, 6, 4, 3,
32 2, 3, 4, 4, 4, 4, 3, 2 },
33
34 testRow, testColumn, minRow, minColumn,
35 minAccess = 9, accessNumber,
36 horizontal[ SIZE ] = { 2, 1, -1, -2, -2, -1, 1, 2 },
37 vertical[ SIZE ] = { -1, -2, -2, -1, 1, 2, 2, 1 };
38 bool done;
39
40 srand( time( 0 ) );
41
42 clearBoard( board ); // initialize array board
43 currentRow = rand() % 8;
44 currentColumn = rand() % 8;
45 board[ currentRow ][ currentColumn ] = ++moveNumber;
46 done = false;
47
48 while ( !done ) {
49 accessNumber = minAccess;
50
51 for ( int moveType = 0; moveType < SIZE; ++moveType ) {
52 testRow = currentRow + vertical[ moveType ];
53 testColumn = currentColumn + horizontal[ moveType ];
54
55 if ( validMove( testRow, testColumn, board ) ) {
56
57 if ( access[ testRow ][ testColumn ] < accessNumber ) {
58 accessNumber = access[ testRow ][ testColumn ];
59 minRow = testRow;
60 minColumn = testColumn;
61 }
62
63 --access[ testRow ][ testColumn ];
64 }
65 }
66
67 if ( accessNumber == minAccess )
68 done = true;
69 else {
70 currentRow = minRow;
71 currentColumn = minColumn;
72 board[ currentRow ][ currentColumn ] = ++moveNumber;
73 }
74 }
75
76 cout << "The tour ended with " << moveNumber << " moves.\n";
77
78 if ( moveNumber == 64 )
79 cout << "This was a full tour!\n\n";
80 else
81 cout << "This was not a full tour.\n\n";
82
83 cout << "The board for this test is:\n\n";
84 printBoard( board );
85
86 return 0;
Chapter 4 Arrays Solutions 147
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.25 (Knight’s Tour: Brute-Force Approaches) In Exercise 4.24, we developed a solution to the Knight’s Tour problem. The
approach used, called the “accessibility heuristic,” generates many solutions and executes efficiently.
As computers continue increasing in power, we will be able to solve more problems with sheer computer power and relatively
unsophisticated algorithms. Let us call this approach “brute force” problem solving.
a) Use random-number generation to enable the knight to walk around the chessboard (in its legitimate L-shaped moves,
of course) at random. Your program should run one tour and print the final chessboard. How far did the knight get?
b) Most likely, the preceding program produced a relatively short tour. Now modify your program to attempt 1000 tours.
Use a single-subscripted array to keep track of the number of tours of each length. When your program finishes attempt-
ing the 1000 tours, it should print this information in neat tabular format. What was the best result?
87 }
88
89 void clearBoard( int workBoard[][ SIZE ] )
90 {
91 for ( int row = 0; row < SIZE; ++row )
92 for ( int col = 0; col < SIZE; ++col )
93 workBoard[ row ][ col ] = 0;
94 }
95
96 void printBoard( const int workBoard[][ SIZE ] )
97 {
98 cout << " 0 1 2 3 4 5 6 7\n";
99
100 for ( int row = 0; row < SIZE; ++row ) {
101 cout << row;
102
103 for ( int col = 0; col < SIZE; ++col )
104 cout << setw( 3 ) << workBoard[ row ][ col ];
105
106 cout << '\n';
107 }
108
109 cout << endl;
110 }
111
112 bool validMove( int row, int column, const int workBoard[][ SIZE ] )
113 {
114 // NOTE: This test stops as soon as it becomes false
115 return ( row >= 0 && row < SIZE && column >= 0 && column < SIZE
116 && workBoard[ row ][ column ] == 0 );
117 }
The tour ended with 64 moves.
This was a full tour!
The board for this test is:
0 1 2 3 4 5 6 7
0 7 36 5 44 9 34 29 56
1 4 45 8 35 30 55 10 33
2 37 6 43 50 47 32 57 28
3 42 3 46 31 58 49 54 11
4 21 38 51 48 53 60 27 62
5 2 41 20 59 24 63 12 15
6 19 22 39 52 17 14 61 26
7 40 1 18 23 64 25 16 13
148 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
c) Most likely, the preceding program gave you some “respectable” tours, but no full tours. Now “pull all the stops out”
and simply let your program run until it produces a full tour. (Caution: This version of the program could run for hours
on a powerful computer.) Once again, keep a table of the number of tours of each length, and print this table when the
first full tour is found. How many tours did your program attempt before producing a full tour? How much time did it
take?
d) Compare the brute-force version of the Knight’s Tour with the accessibility-heuristic version. Which required a more
careful study of the problem? Which algorithm was more difficult to develop? Which required more computer power?
Could we be certain (in advance) of obtaining a full tour with the accessibility heuristic approach? Could we be certain
(in advance) of obtaining a full tour with the brute-force approach? Argue the pros and cons of brute-force problem
solving in general.
1// Exercise 4.25 Part A Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <iomanip>
8
9using std::setw;
10
11 #include <cstdlib>
12 #include <ctime>
13
14 const int SIZE = 8;
15
16 bool validMove( int, int, const int [][ SIZE ] );
17 void printBoard( const int [][ SIZE ] );
18
19 int main()
20 {
21 int currentRow, currentColumn, moveType, moveNumber = 0,
22 testRow, testColumn, board[ SIZE ][ SIZE ] = { 0 },
23 horizontal[ SIZE ] = { 2, 1, -1, -2, -2, -1, 1, 2 },
24 vertical[ SIZE ] = { -1, -2, -2, -1, 1, 2, 2, 1 };
25 bool done, goodMove;
26
27 srand( time( 0 ) );
28
29 currentRow = rand() % SIZE;
30 currentColumn = rand() % SIZE;
31 board[ currentRow ][ currentColumn ] = ++moveNumber;
32 done = false;
33
34 while ( !done ) {
35 moveType = rand() % SIZE;
36 testRow = currentRow + vertical[ moveType ];
37 testColumn = currentColumn + horizontal[ moveType ];
38 goodMove = validMove( testRow, testColumn, board );
39
40 if ( goodMove ) {
41 currentRow = testRow;
42 currentColumn = testColumn;
43 board[ currentRow ][ currentColumn ] = ++moveNumber;
44 }
45 else {
46
47 for ( int count = 0; count < SIZE - 1 && !goodMove; ++count ) {
48 moveType = ++moveType % SIZE;
49 testRow = currentRow + vertical[ moveType ];
50 testColumn = currentColumn + horizontal[ moveType ];
Chapter 4 Arrays Solutions 149
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
51 goodMove = validMove( testRow, testColumn, board );
52
53 if ( goodMove ) {
54 currentRow = testRow;
55 currentColumn = testColumn;
56 board[ currentRow ][ currentColumn ] = ++moveNumber;
57 }
58 }
59
60 if ( !goodMove )
61 done = true;
62 }
63
64 if ( moveNumber == 64 )
65 done = true;
66 }
67
68 cout << "The tour has ended with " << moveNumber << " moves.\n";
69
70 if ( moveNumber == 64 )
71 cout << "This was a full tour!\n";
72 else
73 cout << "This was not a full tour.\n";
74
75 cout << "The board for this random test was:\n\n";
76 printBoard( board );
77 return 0;
78 }
79
80 bool validMove( int row, int column, const int workBoard[][ SIZE ] )
81 {
82 // NOTE: This test stops as soon as it becomes false
83 return ( row >= 0 && row < SIZE && column >= 0 && column < SIZE
84 && workBoard[ row ][ column ] == 0 );
85 }
86
87 void printBoard( const int board[][ SIZE ] )
88 {
89 cout << " 0 1 2 3 4 5 6 7\n";
90
91 for ( int row = 0; row < SIZE; ++row ) {
92 cout << row;
93
94 for ( int col = 0; col < SIZE; ++col )
95 cout << setw( 3 ) << board[ row ][ col ];
96
97 cout << '\n';
98 }
99
100 cout << endl;
101 }
150 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
The tour has ended with 30 moves.
This was not a full tour.
The board for this random test was:
0 1 2 3 4 5 6 7
0 30 27 0 17 0 0 14 0
1 0 18 25 28 15 0 0 0
2 26 29 16 21 0 0 0 13
3 0 24 19 0 11 22 0 0
4 0 1 0 23 20 9 12 7
5 0 0 0 10 0 6 0 0
6 2 0 0 0 4 0 8 0
7 0 0 3 0 0 0 5 0
1// Exercise 4.25 Part B Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6#include <iomanip>
7
8using std::setw;
9
10 #include <cstdlib>
11 #include <ctime>
12
13 const int SIZE = 8, TOURS = 1000, MAXMOVES = 65;
14
15 bool validMove( int, int, int, const int [][ SIZE ] );
16
17 int main()
18 {
19 int currentRow, currentColumn, moveType, moveNumber, testRow, testColumn,
20 moveTotal[ MAXMOVES ] = { 0 }, goodMove, board[ SIZE ][ SIZE ],
21 horizontal[ SIZE ] = { 2, 1, -1, -2, -2, -1, 1, 2 },
22 vertical[ SIZE ] = { -1, -2, -2, -1, 1, 2, 2, 1 };
23 bool done;
24
25 srand( time( 0 ) );
26
27 for ( int i = 0; i < TOURS; ++i ) {
28 for ( int row = 0; row < SIZE; ++row )
29 for ( int col = 0; col < SIZE; ++col )
30 board[ row ][ col ] = 0;
31
32 moveNumber = 0;
33
34 currentRow = rand() % SIZE;
35 currentColumn = rand() % SIZE;
36 board[ currentRow ][ currentColumn ] = ++moveNumber;
37 done = false;
38
39 while ( !done ) {
40 moveType = rand() % SIZE;
41 testRow = currentRow + vertical[ moveType ];
42 testColumn = currentColumn + horizontal[ moveType ];
43 goodMove = validMove( testRow, testColumn, moveType, board );
44
Chapter 4 Arrays Solutions 151
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
45 if ( goodMove ) {
46 currentRow = testRow;
47 currentColumn = testColumn;
48 board[ currentRow ][ currentColumn ] = ++moveNumber;
49 }
50 else {
51
52 for ( int count = 0; count < SIZE - 1 && !goodMove; ++count ) {
53 moveType = ++moveType % SIZE;
54 testRow = currentRow + vertical[ moveType ];
55 testColumn = currentColumn + horizontal[ moveType ];
56 goodMove = validMove( testRow, testColumn, moveType, board );
57
58 if ( goodMove ) {
59 currentRow = testRow;
60 currentColumn = testColumn;
61 board[ currentRow ][ currentColumn ] = ++moveNumber;
62 }
63
64 }
65
66 if ( !goodMove )
67 done = true;
68 }
69
70 if ( moveNumber == 64 )
71 done = true;
72 }
73
74 ++moveTotal[ moveNumber ];
75 }
76
77 for ( int j = 1; j < MAXMOVES; ++j )
78 if ( moveTotal[ j ] )
79 cout << "There were " << moveTotal[ j ] << " tours of " << j
80 << " moves." << endl;
81
82 return 0;
83 }
84
85 bool validMove( int testRow, int testColumn, int moveType,
86 const int board[][ SIZE ] )
87 {
88 if ( testRow >= 0 && testRow < SIZE && testColumn >= 0 &&
89 testColumn < SIZE )
90 return board[ testRow ][ testColumn ] != 0 ? false : true;
91 else
92 return false;
93 }
152 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.26 (Eight Queens) Another puzzler for chess buffs is the Eight Queens problem. Simply stated: Is it possible to place eight
queens on an empty chessboard so that no queen is “attacking” any other, i.e., no two queens are in the same row, the same column,
or along the same diagonal? Use the thinking developed in Exercise 4.24 to formulate a heuristic for solving the Eight Queens prob-
lem. Run your program. (Hint: It is possible to assign a value to each square of the chessboard indicating how many squares of an
empty chessboard are “eliminated” if a queen is placed in that square. Each of the corners would be assigned the value 22, as in Fig.
There were 1 tours of 5 moves.
There were 3 tours of 6 moves.
There were 3 tours of 8 moves.
There were 2 tours of 10 moves.
There were 6 tours of 11 moves.
There were 4 tours of 12 moves.
There were 6 tours of 13 moves.
There were 5 tours of 14 moves.
There were 11 tours of 15 moves.
There were 7 tours of 16 moves.
There were 5 tours of 17 moves.
There were 15 tours of 18 moves.
There were 6 tours of 19 moves.
There were 11 tours of 20 moves.
There were 6 tours of 21 moves.
There were 10 tours of 22 moves.
There were 19 tours of 23 moves.
There were 20 tours of 24 moves.
There were 12 tours of 25 moves.
There were 25 tours of 26 moves.
There were 21 tours of 27 moves.
There were 29 tours of 28 moves.
There were 24 tours of 29 moves.
There were 23 tours of 30 moves.
There were 23 tours of 31 moves.
There were 25 tours of 32 moves.
There were 26 tours of 33 moves.
There were 34 tours of 34 moves.
There were 32 tours of 35 moves.
There were 30 tours of 36 moves.
There were 24 tours of 37 moves.
There were 42 tours of 38 moves.
There were 21 tours of 39 moves.
There were 42 tours of 40 moves.
There were 31 tours of 41 moves.
There were 49 tours of 42 moves.
There were 46 tours of 43 moves.
There were 42 tours of 44 moves.
There were 28 tours of 45 moves.
There were 33 tours of 46 moves.
There were 31 tours of 47 moves.
There were 28 tours of 48 moves.
There were 22 tours of 49 moves.
There were 24 tours of 50 moves.
There were 17 tours of 51 moves.
There were 22 tours of 52 moves.
There were 12 tours of 53 moves.
There were 13 tours of 54 moves.
There were 13 tours of 55 moves.
There were 6 tours of 56 moves.
There were 4 tours of 57 moves.
There were 4 tours of 58 moves.
There were 2 tours of 59 moves.
Chapter 4 Arrays Solutions 153
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.26.) Once these “elimination numbers” are placed in all 64 squares, an appropriate heuristic might be: Place the next queen in the
square with the smallest elimination number. Why is this strategy intuitively appealing?
4.27 (Eight Queens: Brute-Force Approaches) In this exercise, you will develop several brute-force approaches to solving the
Eight Queens problem introduced in Exercise 4.26.
a) Solve the Eight Queens exercise, using the random brute-force technique developed in Exercise 4.25.
b) Use an exhaustive technique, i.e., try all possible combinations of eight queens on the chessboard.
c) Why do you suppose the exhaustive brute-force approach may not be appropriate for solving the Knight’s Tour prob-
lem?
d) Compare and contrast the random brute-force and exhaustive brute-force approaches in general.
* * * * * * * *
* *
* *
* *
* *
* *
* *
* *
Fig. 4.26 The 22 squares eliminated by placing a queen in the upper-left corner.
1// Exercise 4.27 Part A Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <iomanip>
8
9using std::setw;
10
11 #include <ctime>
12 #include <cstdlib>
13
14 bool queenCheck( const char [][ 8 ], int, int );
15 void placeQueens( char [][ 8 ] );
16 void printBoard( const char [][ 8 ] );
17 void xConflictSquares( char [][ 8 ], int, int );
18 void xDiagonals( char [][ 8 ], int, int );
19 bool availableSquare( const char [][ 8 ] );
20 inline int validMove( const char board[][ 8 ], int row, int col )
21 { return ( row >= 0 && row < 8 && col >= 0 && col < 8 ); }
22
23 int main()
24 {
25 char board [ 8 ][ 8 ] = { '\0' };
26
27 srand( time( 0 ) );
28
29 placeQueens( board );
30 printBoard( board );
31
32 return 0;
33 }
34
35 bool availableSquare( const char board[][ 8 ] )
36 {
37 for ( int row = 0; row < 8; ++row )
154 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
38 for ( int col = 0; col < 8; ++col )
39 if ( board[ row ][ col ] == '\0' )
40 return false; // at least one open square is available
41
42 return true; // no available squares
43 }
44
45 void placeQueens( char board[][ 8 ] )
46 {
47 const char QUEEN = 'Q';
48 int rowMove, colMove, queens = 0;
49 bool done = false;
50
51 while ( queens < 8 && !done ) {
52 rowMove = rand() % 8;
53 colMove = rand() % 8;
54
55 if ( queenCheck( board, rowMove, colMove ) ) {
56 board[ rowMove ][ colMove ] = QUEEN;
57 xConflictSquares( board, rowMove, colMove );
58 ++queens;
59 }
60
61 done = availableSquare( board );
62 }
63 }
64
65 void xConflictSquares( char board[][ 8 ], int row, int col )
66 {
67 for ( int loop = 0; loop < 8; ++loop ) {
68 // place an '*' in the row occupied by the queen
69 if ( board[ row ][ loop ] == '\0' )
70 board[ row ][ loop ] = '*';
71
72 // place an '*' in the col occupied by the queen
73 if ( board[ loop ][ col ] == '\0' )
74 board[ loop ][ col ] = '*';
75 }
76
77 // place an '*' in the diagonals occupied by the queen
78 xDiagonals( board, row, col );
79 }
80
81 bool queenCheck( const char board[][ 8 ], int row, int col )
82 {
83 int r = row, c = col;
84
85 // check row and column for a queen
86 for ( int d = 0; d < 8; ++d )
87 if ( board[ row ][ d ] == 'Q' || board[ d ][ col ] == 'Q' )
88 return false;
89
90 // check upper left diagonal for a queen
91 for ( int e = 0; e < 8 && validMove( board, --r, --c ); ++e )
92 if ( board[ r ][ c ] == 'Q' )
93 return false;
94
95 r = row;
96 c = col;
97 // check upper right diagonal for a queen
98 for ( int f = 0; f < 8 && validMove( board, --r, ++c ); ++f )
99 if ( board[ r ][ c ] == 'Q' )
Chapter 4 Arrays Solutions 155
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
100 return false;
101
102 r = row;
103 c = col;
104 // check lower left diagonal for a queen
105 for ( int g = 0; g < 8 && validMove( board, ++r, --c ); ++g )
106 if (board[ r ][ c ] == 'Q' )
107 return false;
108
109 r = row;
110 c = col;
111 // check lower right diagonal for a queen
112 for ( int h = 0; h < 8 && validMove( board, ++r, ++c ); ++h )
113 if ( board[ r ][ c ] == 'Q' )
114 return false;
115
116 return true; // no queen in conflict
117 }
118
119 void xDiagonals( char board[][ 8 ], int row, int col )
120 {
121 int r = row, c = col;
122
123 // upper left diagonal
124 for ( int a = 0; a < 8 && validMove( board, --r, --c ); ++a )
125 board[ r ][ c ] = '*';
126
127 r = row;
128 c = col;
129 // upper right diagonal
130 for ( int b = 0; b < 8 && validMove( board, --r, ++c ); ++b )
131 board[ r ][ c ] = '*';
132
133 r = row;
134 c = col;
135 // lower left diagonal
136 for ( int d = 0; d < 8 && validMove( board, ++r, --c ); ++d )
137 board[ r ][ c ] = '*';
138
139 r = row;
140 c = col;
141 // lower right diagonal
142 for ( int e = 0; e < 8 && validMove( board, ++r, ++c ); ++e )
143 board[ r ][ c ] = '*';
144 }
145
146 void printBoard( const char board[][ 8 ] )
147 {
148 int queens = 0;
149
150 // header for columns
151 cout << " 0 1 2 3 4 5 6 7\n";
152
153 for ( int r = 0; r < 8; ++r ) {
154 cout << setw( 2 ) << r << ' ';
155
156 for ( int c = 0; c < 8; ++c ) {
157 cout << board[ r ][ c ] << ' ';
158
159 if ( board[ r ][ c ] == 'Q' )
160 ++queens;
161 }
156 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.28 (Knight’s Tour: Closed-Tour Test) In the Knight’s Tour, a full tour occurs when the knight makes 64 moves touching each
square of the chess board once and only once. A closed tour occurs when the 64th move is one move away from the location in
which the knight started the tour. Modify the Knight’s Tour program you wrote in Exercise 4.24 to test for a closed tour if a full
tour has occurred.
162
163 cout << '\n';
164 }
165
166 if ( queens == 8 )
167 cout << "\nEight Queens were placed on the board!" << endl;
168 else
169 cout << '\n' << queens << " Queens were placed on the board." << endl;
170 }
0 1 2 3 4 5 6 7
0 * * * * Q * * *
1 * Q * * * * * *
2 * * * * * Q * *
3 * * Q * * * * *
4 * * * * * * * *
5 * * * * * * * Q
6 Q * * * * * * *
7 * * * Q * * * *
7 Queens were placed on the board.
1// Exercise 4.28 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <iomanip>
8
9using std::setw;
10
11 #include <cstdlib>
12 #include <ctime>
13
14 const int SIZE = 8;
15
16 void clearBoard( int [][ SIZE ] );
17 void printBoard( const int [][ SIZE ] );
18 bool validMove( int, int, const int [][ SIZE ] );
19
20 int main()
21 {
22 int board[ SIZE ][ SIZE ], firstMoveRow, firstMoveCol,
23 access[ SIZE ][ SIZE ] = { 2, 3, 4, 4, 4, 4, 3, 2,
24 3, 4, 6, 6, 6, 6, 4, 3,
25 4, 6, 8, 8, 8, 8, 6, 4,
26 4, 6, 8, 8, 8, 8, 6, 4,
27 4, 6, 8, 8, 8, 8, 6, 4,
28 4, 6, 8, 8, 8, 8, 6, 4,
29 3, 4, 6, 6, 6, 6, 4, 3,
30 2, 3, 4, 4, 4, 4, 3, 2 },
31 currentRow, currentColumn, moveNumber = 0, testRow, testColumn,
32 minRow, minColumn, minAccess = 9, accessNumber,
Chapter 4 Arrays Solutions 157
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
33 horizontal[ SIZE ] = { 2, 1, -1, -2, -2, -1, 1, 2 },
34 vertical[ SIZE ] = { -1, -2, -2, -1, 1, 2, 2, 1 };
35 bool done, closedTour = false;
36
37 srand( time( 0 ) );
38
39 clearBoard( board ); // initialize array board
40 currentRow = rand() % SIZE;
41 currentColumn = rand() % SIZE;
42 firstMoveRow = currentRow; // store first moves row
43 firstMoveCol = currentColumn; // store first moves col
44
45 board[ currentRow ][ currentColumn ] = ++moveNumber;
46 done = false;
47
48 while ( !done ) {
49 accessNumber = minAccess;
50
51 for ( int moveType = 0; moveType < SIZE; ++moveType ) {
52 testRow = currentRow + vertical[ moveType ];
53 testColumn = currentColumn + horizontal[ moveType ];
54
55 if ( validMove( testRow, testColumn, board ) ) {
56 if ( access[ testRow ][ testColumn ] < accessNumber ) {
57 accessNumber = access[ testRow ][ testColumn ];
58 minRow = testRow;
59 minColumn = testColumn;
60 }
61
62 --access[ testRow ][ testColumn ];
63 }
64 }
65
66 if ( accessNumber == minAccess )
67 done = true;
68 else {
69 currentRow = minRow;
70 currentColumn = minColumn;
71 board[ currentRow ][ currentColumn ] = ++moveNumber;
72
73 // check for closed tour
74 if ( moveNumber == 64 )
75 for ( int m = 0; m < SIZE; ++m ) {
76 testRow = currentRow + vertical[ m ];
77 testColumn = currentColumn + horizontal[ m ];
78
79 if ( testRow == firstMoveRow && testColumn == firstMoveCol )
80 closedTour = true;
81 }
82 }
83 }
84
85 cout << "The tour ended with " << moveNumber << " moves.\n";
86
87 if ( moveNumber == 64 && closedTour == true )
88 cout << "This was a CLOSED tour!\n\n";
89 else if ( moveNumber == 64 )
90 cout << "This was a full tour!\n\n";
91 else
92 cout << "This was not a full tour.\n\n";
93
94 cout << "The board for this test is:\n\n";
158 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.29 (The Sieve of Eratosthenes) A prime integer is any integer that is evenly divisible only by itself and 1. The Sieve of Era-
tosthenes is a method of finding prime numbers. It operates as follows:
a) Create an array with all elements initialized to 1 (true). Array elements with prime subscripts will remain 1. All other
array elements will eventually be set to zero.
b) Starting with array subscript 2 (subscript 1 must be prime), every time an array element is found whose value is 1, loop
through the remainder of the array and set to zero every element whose subscript is a multiple of the subscript for the
element with value 1. For array subscript 2, all elements beyond 2 in the array that are multiples of 2 will be set to zero
(subscripts 4, 6, 8, 10, etc.); for array subscript 3, all elements beyond 3 in the array that are multiples of 3 will be set
to zero (subscripts 6, 9, 12, 15, etc.); and so on.
95 printBoard( board );
96
97 return 0;
98 }
99
100 void clearBoard( int workBoard[][ SIZE ] )
101 {
102 for ( int row = 0; row < SIZE; ++row )
103 for ( int col = 0; col < SIZE; ++col )
104 workBoard[ row ][ col ] = 0;
105 }
106
107 void printBoard( const int workBoard[][ SIZE ] )
108 {
109 cout << " 0 1 2 3 4 5 6 7\n";
110
111 for ( int row = 0; row < SIZE; ++row ) {
112 cout << row;
113
114 for ( int col = 0; col < SIZE; ++col )
115 cout << setw( 3 ) << workBoard[ row ][ col ];
116
117 cout << '\n';
118 }
119
120 cout << endl;
121 }
122
123 bool validMove( int row, int column, const int workBoard[][ SIZE ] )
124 {
125 // NOTE: This test stops as soon as it becomes false
126 return ( row >= 0 && row < SIZE && column >= 0 && column < SIZE
127 && workBoard[ row ][ column ] == 0 );
128 }
The tour ended with 64 moves.
This was a full tour!
The board for this test is:
0 1 2 3 4 5 6 7
0 42 25 50 7 40 23 52 5
1 49 8 41 24 51 6 39 22
2 26 43 48 55 46 59 4 53
3 9 56 45 60 63 54 21 38
4 44 27 64 47 58 37 62 3
5 13 10 57 36 61 18 31 20
6 28 35 12 15 30 33 2 17
7 11 14 29 34 1 16 19 32
Chapter 4 Arrays Solutions 159
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
When this process is complete, the array elements that are still set to one indicate that the subscript is a prime number. These sub-
scripts can then be printed. Write a program that uses an array of 1000 elements to determine and print the prime numbers between
1 and 999. Ignore element 0 of the array.
4.30 (Bucket Sort) A bucket sort begins with a single-subscripted array of positive integers to be sorted and a double-subscripted
array of integers with rows subscripted from 0 to 9 and columns subscripted from 0 to n - 1, where n is the number of values in the
array to be sorted. Each row of the double-subscripted array is referred to as a bucket. Write a function bucketSort that takes an
integer array and the array size as arguments and performs as follows:
a) Place each value of the single-subscripted array into a row of the bucket array based on the value’s ones digit. For ex-
ample, 97 is placed in row 7, 3 is placed in row 3 and 100 is placed in row 0. This is called a “distribution pass.”
b) Loop through the bucket array row by row, and copy the values back to the original array. This is called a “gathering
pass.” The new order of the preceding values in the single-subscripted array is 100, 3 and 97.
c) Repeat this process for each subsequent digit position (tens, hundreds, thousands, etc.).
1// Exercise 4.29 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <iomanip>
8
9using std::setw;
10
11 int main()
12 {
13 const int SIZE = 1000;
14 int array[ SIZE ], count = 0;
15
16 for ( int k = 0; k < SIZE; ++k )
17 array[ k ] = 1;
18
19 for ( int i = 1; i < SIZE; ++i )
20 if ( array[ i ] == 1 && i != 1 )
21 for ( int j = i; j <= SIZE; ++j )
22 if ( j % i == 0 && j != i )
23 array[ j ] = 0;
24
25 // range 2 - 197
26 for ( int q = 2; q < SIZE; ++q )
27 if ( array[ q ] == 1 ) {
28 cout << setw( 3 ) << q << " is a prime number.\n";
29 ++count;
30 }
31
32 cout << "A total of " << count << " prime numbers were found." << endl;
33
34 return 0;
35 }
3 is a prime number.
5 is a prime number.
7 is a prime number.
11 is a prime number.
...
983 is a prime number.
991 is a prime number.
997 is a prime number.
A total of 168 prime numbers were found.
160 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
On the second pass, 100 is placed in row 0, 3 is placed in row 0 (because 3 has no tens digit) and 97 is placed in row 9. After the
gathering pass, the order of the values in the single-subscripted array is 100, 3 and 97. On the third pass, 100 is placed in row 1, 3
is placed in row zero and 97 is placed in row zero (after the 3). After the last gathering pass, the original array is now in sorted
order.
Note that the double-subscripted array of buckets is 10 times the size of the integer array being sorted. This sorting technique
provides better performance than a bubble sort, but requires much more memory. The bubble sort requires space for only one addi-
tional element of data. This is an example of the space–time trade-off: The bucket sort uses more memory than the bubble sort, b ut
performs better. This version of the bucket sort requires copying all the data back to the original array on each pass. Another possi-
bility is to create a second double-subscripted bucket array and repeatedly swap the data between the two bucket arrays.
1// Exercise 4.30 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <iomanip>
8
9using std::setw;
10
11 // constant size must be defined as the array size for bucketSort to work
12 const int SIZE = 12;
13
14 void bucketSort( int [] );
15 void distributeElements( int [], int [][ SIZE ], int );
16 void collectElements( int [], int [][ SIZE ] );
17 int numberOfDigits( int [], int );
18 void zeroBucket( int [][ SIZE ] );
19
20 int main()
21 {
22 int array[ SIZE ] = { 19, 13, 5, 27, 1, 26, 31, 16, 2, 9, 11, 21 };
23
24 cout << "Array elements in original order:\n";
25
26 for ( int i = 0; i < SIZE; ++i )
27 cout << setw( 3 ) << array[ i ];
28
29 cout << '\n';
30 bucketSort( array );
31
32 cout << "\nArray elements in sorted order:\n";
33
34 for ( int j = 0; j < SIZE; ++j )
35 cout << setw( 3 ) << array[ j ];
36
37 cout << endl;
38
39 return 0;
40 }
41
42 // Perform the bucket sort algorithm
43 void bucketSort( int a[] )
44 {
45 int totalDigits, bucket[ 10 ][ SIZE ] = { 0 };
46
47 totalDigits = numberOfDigits( a, SIZE );
48
49 for ( int i = 1; i <= totalDigits; ++i ) {
50 distributeElements( a, bucket, i );
51 collectElements( a, bucket );
Chapter 4 Arrays Solutions 161
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
52
53 if ( i != totalDigits )
54 zeroBucket( bucket ); // set all bucket contents to zero
55 }
56 }
57
58 // Determine the number of digits in the largest number
59 int numberOfDigits( int b[], int arraySize )
60 {
61 int largest = b[ 0 ], digits = 0;
62
63 for ( int i = 1; i < arraySize; ++i )
64 if ( b[ i ] > largest )
65 largest = b[ i ];
66
67 while ( largest != 0 ) {
68 ++digits;
69 largest /= 10;
70 }
71
72 return digits;
73 }
74
75 // Distribute elements into buckets based on specified digit
76 void distributeElements( int a[], int buckets[][ SIZE ], int digit )
77 {
78 int divisor = 10, bucketNumber, elementNumber;
79
80 for ( int i = 1; i < digit; ++i ) // determine the divisor
81 divisor *= 10; // used to get specific digit
82
83 for ( int k = 0; k < SIZE; ++k ) {
84 // bucketNumber example for hundreds digit:
85 // (1234 % 1000 - 1234 % 100) / 100 --> 2
86 bucketNumber = ( a[ k ] % divisor - a[ k ] %
87 ( divisor / 10 ) ) / ( divisor / 10 );
88
89 // retrieve value in buckets[bucketNumber][0] to determine
90 // which element of the row to store a[i] in.
91 elementNumber = ++buckets[ bucketNumber ][ 0 ];
92 buckets[ bucketNumber ][ elementNumber ] = a[ k ];
93 }
94 }
95
96 // Return elements to original array
97 void collectElements( int a[], int buckets[][ SIZE ])
98 {
99 int subscript = 0;
100
101 for ( int i = 0; i < 10; ++i )
102 for ( int j = 1; j <= buckets[ i ][ 0 ]; ++j )
103 a[ subscript++ ] = buckets[ i ][ j ];
104 }
105
106 // Set all buckets to zero
107 void zeroBucket( int buckets[][ SIZE ] )
108 {
109 for ( int i = 0; i < 10; ++i )
110 for ( int j = 0; j < SIZE; ++j )
111 buckets[ i ][ j ] = 0;
112 }
162 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
RECURSION EXERCISES
4.31 (Selection Sort) A selection sort searches an array looking for the smallest element in the array. Then, the smallest element
is swapped with the first element of the array. The process is repeated for the subarray beginning with the second element of the
array. Each pass of the array results in one element being placed in its proper location. This sort performs comparably to the bubble
sort—for an array of n elements, n - 1 passes must be made, and for each subarray, n - 1 comparisons must be made to find the
smallest value. When the subarray being processed contains one element, the array is sorted. Write recursive function selec-
tionSort to perform this algorithm.
Array elements in original order:
19 13 5 27 1 26 31 16 2 9 11 21
Array elements in sorted order:
1 2 5 9 11 13 16 19 21 26 27 31
1// Exercise 4.31 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <cstdlib>
8#include <ctime>
9
10 void selectionSort( int [], int );
11
12 int main()
13 {
14 const int SIZE = 10, MAXRANGE = 1000;
15 int sortThisArray[ SIZE ] = { 0 };
16
17 srand( time( 0 ) );
18
19 for ( int i = 0; i < SIZE; ++i )
20 sortThisArray[ i ] = 1 + rand() % MAXRANGE;
21
22 cout << "\nUnsorted array is:\n";
23 for ( int j = 0; j < SIZE; ++j )
24 cout << ' ' << sortThisArray[ j ] << ' ';
25
26 selectionSort( sortThisArray, SIZE );
27
28 cout << "\n\nSorted array is:\n";
29 for ( int k = 0; k < SIZE; ++k )
30 cout << ' ' << sortThisArray[ k ] << ' ';
31
32 cout << '\n' << endl;
33
34 return 0;
35 }
36
37 void selectionSort( int array[], int size )
38 {
39 int temp;
40
41 if ( size >= 1 ) {
42
43 for ( int loop = 0; loop < size; ++loop )
44 if ( array[ loop ] < array[ 0 ] ) {
Chapter 4 Arrays Solutions 163
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.32 (Palindromes) A palindrome is a string that is spelled the same way forwards and backwards. Some examples of palin-
dromes are “radar,” “able was i ere i saw elba” and (if blanks are ignored) “a man a plan a canal panama.” Write a recursive function
testPalindrome that returns true if the string stored in the array is a palindrome, and false otherwise. The function should
ignore spaces and punctuation in the string.
45 temp = array[ loop ];
46 array[ loop ] = array[ 0 ];
47 array[ 0 ] = temp;
48 }
49
50 selectionSort( &array[ 1 ], size - 1 );
51 }
52 }
Unsorted array is:
957 848 727 597 384 617 228 424 878 10
Sorted array is:
10 228 384 424 597 617 727 848 878 957
1// Exercise 4.32 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8bool testPalindrome( const char [], int, int );
9
10 int main()
11 {
12 const int SIZE = 80;
13 char c, string[ SIZE ], copy[ SIZE ];
14 int count = 0, copyCount, i;
15
16 cout << "Enter a sentence:\n";
17
18 while ( ( c = cin.get() ) != '\n' && count < SIZE )
19 string[ count++ ] = c;
20
21 string[ count ] = '\0'; // terminate cstring
22
23 // make a copy of cstring without spaces
24 for ( copyCount = 0, i = 0; string[ i ] != '\0'; ++i )
25 if ( string[ i ] != ' ' )
26 copy[ copyCount++ ] = string[ i ];
27
28 if ( testPalindrome( copy, 0, copyCount - 1 ) )
29 cout << '\"' << string << "\" is a palindrome" << endl;
30 else
31 cout << '\"' << string << "\" is not a palindrome" << endl;
32
33 return 0;
34 }
35
36 bool testPalindrome( const char array[], int left, int right )
37 {
38 if ( left == right || left > right )
39 return true;
164 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.33 (Linear Search) Modify the program in Fig. 4.19 to use recursive function linearSearch to perform a linear search of
the array. The function should receive an integer array and the size of the array as arguments. If the search key is found, return the
array subscript; otherwise, return –1.
40 else if ( array[ left ] != array[ right ] )
41 return false;
42 else
43 return testPalindrome( array, left + 1, right - 1 );
44 }
Enter a sentence:
alucard e dracula
"alucard e dracula" is a palindrome
1// Exercise 4.33 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int linearSearch( const int [], int, int, int );
9
10 int main()
11 {
12 const int SIZE = 100;
13 int array[ SIZE ], searchKey, element;
14
15 for ( int loop = 0; loop < SIZE; ++loop )
16 array[ loop ] = 2 * loop;
17
18 cout << "Enter the integer search key: ";
19 cin >> searchKey;
20
21 element = linearSearch( array, searchKey, 0, SIZE - 1 );
22
23 if ( element != -1 )
24 cout << "Found value in element " << element << endl;
25 else
26 cout << "Value not found" << endl;
27
28 return 0;
29 }
30
31 int linearSearch( const int array[], int key, int low, int high )
32 {
33 if ( array[low] == key )
34 return low;
35 else if ( low == high )
36 return -1;
37 else
38 return linearSearch( array, key, low + 1, high );
39 }
Enter the integer search key: 22
Found value in element 11
Chapter 4 Arrays Solutions 165
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.34 (Binary Search) Modify the program of Fig. 4.20 to use a recursive function binarySearch to perform the binary search
of the array. The function should receive an integer array and the starting subscript and ending subscript as arguments. If the search
key is found, return the array subscript; otherwise, return –1.
1// Exercise 4.34 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <iomanip>
9
10 using std::setw;
11
12 const int SIZE = 15;
13
14 int binarySearch( const int [], int, int, int );
15 void printRow( const int [], int, int, int );
16 void printHeader( void );
17
18 int main()
19 {
20 int a[ SIZE ], key, result;
21
22 for ( int i = 0; i < SIZE; ++i )
23 a[ i ] = 2 * i;
24
25 cout << "Enter a number between 0 and 28: ";
26 cin >> key;
27
28 printHeader();
29 result = binarySearch( a, key, 0, SIZE - 1 );
30
31 if ( result != -1 )
32 cout << '\n' << key << " found in array element " << result << endl;
33 else
34 cout << '\n' << key << " not found" << endl;
35
36 return 0;
37 }
38
39 int binarySearch( const int b[], int searchKey, int low, int high )
40 {
41 int middle;
42
43 if ( low <= high ) {
44 middle = ( low + high ) / 2;
45 printRow( b, low, middle, high );
46
47 if ( searchKey == b[ middle ] )
48 return middle;
49 else if ( searchKey < b[ middle ] )
50 return binarySearch( b, searchKey, low, middle - 1 );
51 else
52 return binarySearch( b, searchKey, middle + 1, high );
53 }
54
55 return -1; // searchKey not found
56 }
57
58 // Print a header for the output
166 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.35 (Eight Queens) Modify the Eight Queens program you created in Exercise 4.26 to solve the problem recursively.
4.36 (Print an array) Write a recursive function printArray that takes an array and the size of the array as arguments and
returns nothing. The function should stop processing and return when it receives an array of size zero.
59 void printHeader( void )
60 {
61 cout << "Subscripts:\n";
62
63 for ( int i = 0; i < SIZE; ++i )
64 cout << setw( 3 ) << i << ' ';
65
66 cout << '\n';
67
68 for ( int k = 1; k <= 4 * SIZE; ++k )
69 cout << '-';
70
71 cout << '\n';
72 }
73
74 // print one row of output showing the current
75 // part of the array being processed.
76 void printRow( const int b[], int low, int mid, int high )
77 {
78 for ( int i = 0; i < SIZE; ++i )
79 if ( i < low || i > high )
80 cout << " ";
81 else if ( i == mid )
82 cout << setw( 3 ) << b[ i ] << '*'; // mark middle value
83 else
84 cout << setw( 3 ) << b[ i ] << ' ';
85
86 cout << '\n';
87 }
Enter a number between 0 and 28: 17
Subscripts:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
------------------------------------------------------------
0 2 4 6 8 10 12 14* 16 18 20 22 24 26 28
16 18 20 22* 24 26 28
16 18* 20
16*
17 not found
1// Exercise 4.36 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <iomanip>
8
9using std::setw;
10
11 #include <cstdlib>
12 #include <ctime>
13
14 void printArray( const int [], int, int );
Chapter 4 Arrays Solutions 167
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.37 (Print a string backwards) Write a recursive function stringReverse that takes a character array containing a string as
an argument, prints the string backwards and returns nothing. The function should stop processing and return when the terminating
null character is encountered.
15
16 int main()
17 {
18 const int SIZE = 10, MAXNUMBER = 500;
19 int array[ SIZE ];
20
21 srand( time( 0 ) );
22
23 for ( int loop = 0; loop < SIZE; ++loop )
24 array[ loop ] = 1 + rand() % MAXNUMBER;
25
26 cout << "Array values printed in main:\n";
27
28 for ( int j = 0; j < SIZE; ++j )
29 cout << setw( 5 ) << array[ j ];
30
31 cout << "\n\nArray values printed in printArray:\n";
32 printArray( array, 0, SIZE - 1 );
33 cout << endl;
34
35 return 0;
36 }
37
38 void printArray( const int array[], int low, int high )
39 {
40 cout << setw( 5 ) << array[ low ];
41
42 if ( low == high )
43 return;
44 else
45 printArray( array, low + 1, high );
46 }
Array values printed in main:
432 14 59 484 45 388 355 384 425 448
Array values printed in printArray:
432 14 59 484 45 388 355 384 425 448
1// Exercise 4.37 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7void stringReverse( const char [] );
8
9int main()
10 {
11 const int SIZE = 30;
12 char strArray[ SIZE ] = "Print this string backwards.";
13
14 for ( int loop = 0; loop < SIZE; ++loop )
15 cout << strArray[ loop ];
16
168 Arrays Solutions Chapter 4
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
4.38 (Find the minimum value in an array) Write a recursive function recursiveMinimum that takes an integer array and
the array size as arguments and returns the smallest element of the array. The function should stop processing and return when it
receives an array of 1 element.
17 cout << '\n';
18 stringReverse( strArray );
19 cout << endl;
20
21 return 0;
22 }
23
24 void stringReverse( const char strArray[] )
25 {
26 if ( strArray[ 0 ] == '\0' )
27 return;
28
29 stringReverse( &strArray[ 1 ] );
30 cout << strArray[ 0 ];
31 }
Print this string backwards.
.sdrawkcab gnirts siht tnirP
1// Exercise 4.38 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <iomanip>
8
9using std::setw;
10
11 #include <cstdlib>
12 #include <ctime>
13
14 const int MAXRANGE = 1000;
15 int recursiveMinimum( const int [], int, int );
16
17 int main()
18 {
19 const int SIZE = 10;
20 int array[ SIZE ], smallest;
21
22 srand( time( 0 ) );
23
24 for ( int loop = 0; loop < SIZE; ++loop )
25 array[ loop ] = 1 + rand() % MAXRANGE;
26
27 cout << "Array members are:\n";
28 for ( int k = 0; k < SIZE; ++k )
29 cout << setw( 5 ) << array[ k ];
30
31 cout << '\n';
32 smallest = recursiveMinimum( array, 0, SIZE - 1 );
33 cout << "\nSmallest element is: " << smallest << endl;
34
35 return 0;
36 }
Chapter 4 Arrays Solutions 169
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
37
38 int recursiveMinimum( const int array[], int low, int high )
39 {
40 static int smallest = MAXRANGE;
41
42 if ( array[ low ] < smallest )
43 smallest = array[ low ];
44
45 return low == high ? smallest : recursiveMinimum( array, low + 1, high );
46 }
Array members are:
7 84 951 884 404 167 905 93 744 115
Smallest element is: 7
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5
Pointers
and Strings
Solutions
Solutions
5.8 State whether the following are true or false. If false, explain why.
a) Two pointers that point to different arrays cannot be compared meaningfully.
ANS: True.
b) Because the name of an array is a pointer to the first element of the array, array names may be manipulated in precisely
the same manner as pointers.
ANS: False. An array name cannot be used to refer to another location in memory.
5.9 Answer each of the following. Assume that unsigned integers are stored in 2 bytes and that the starting address of the array
is at location 1002500 in memory.
a) Declare an array of type unsigned int called values with 5 elements, and initialize the elements to the even in-
tegers from 2 to 10. Assume that the symbolic constant SIZE has been defined as 5.
ANS: unsigned values[ SIZE ] = { 2, 4, 6, 8, 10 };
b) Declare a pointer vPtr that points to an object of type unsigned int.
ANS: unsigned *vPtr;
c) Print the elements of array values using array subscript notation. Use a for structure and assume integer control
variable i has been declared.
ANS:
for ( i = 0; i < SIZE; ++i )
cout << setw( 4 ) << values[ i ];
d) Give two separate statements that assign the starting address of array values to pointer variable vPtr.
ANS: vPtr = values; and vPtr = &values[ 0 ];
e) Print the elements of array values using pointer/offset notation.
ANS:
for ( i = 0; i < SIZE; ++i )
cout << setw( 4 ) << *( vPtr + i );
f) Print the elements of array values using pointer/offset notation with the array name as the pointer.
ANS:
for ( i = 0; i < SIZE; ++i )
cout << setw( 4 ) << *( values + i );
g) Print the elements of array values by subscripting the pointer to the array.
ANS:
for ( i = 0; i < SIZE; ++i )
cout << setw( 4 ) << vPtr[ i ];
Chapter 5 Pointers and Strings Solutions 171
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
h) Refer to the fifth element of values using array subscript notation pointer/offset notation with the array name as the
pointer, pointer subscript notation, and pointer/offset notation.
ANS: values[ 4 ], *( values + 4 ), vPtr[ 4 ], *( vPtr + 4 )
i) What address is referenced by vPtr + 3? What value is stored at that location?
ANS: The address of the location pertaining to values[ 3 ] (i.e., 1002506). 8.
j) Assuming vPtr points to values[ 4 ], what address is referenced by vPtr -= 4? What value is stored at that lo-
cation?
ANS: The address of where values begins in memory (i.e., 1002500). 2.
5.10 For each of the following, write a single statement that performs the indicated task. Assume that long integer variables
value1 and value2 have been declared and that value1 has been initialized to 200000.
a) Declare the variable lPtr to be a pointer to an object of type long.
ANS: long *lPtr;
b) Assign the address of variable value1 to pointer variable lPtr.
ANS: lPtr = &value1;
c) Print the value of the object pointed to by lPtr.
ANS: cout << *lPtr << ’\n’;
d) Assign the value of the object pointed to by lPtr to variable value2.
ANS: value2 = *lPtr;
e) Print the value of value2.
ANS: cout << value2 << ’\n’;
f) Print the address of value1.
ANS: cout << &value1 << ’\n’;
g) Print the address stored in lPtr. Is the value printed the same as the address of value1?
ANS: cout << lPtr << ’\n’; yes.
5.11 Do each of the following.
a) Write the function header for function zero that takes a long integer array parameter bigIntegers and does not
return a value.
ANS: void zero( long bigIntegers[] ) or
void zero( long *bigIntegers )
b) Write the function prototype for the function in part (a).
ANS: void zero( long [] ); or void zero( long * );
c) Write the function header for function add1AndSum that takes an integer array parameter oneTooSmall and returns
an integer.
ANS: int add1Andsum( int oneTooSmall[] ) or
int add1Andsum( int *oneTooSmall )
d) Write the function prototype for the function described in part (c).
ANS: int add1Andsum( int [] ); or int add1Andsum( int * );
Note: Exercises 5.12 through 5.15 are reasonably challenging. Once you have done these prob-
lems, you ought to be able to implement most popular card games easily.
5.12 Modify the program in Fig. 5.24 so that the card dealing function deals a five-card poker hand. Then write functions to
accomplish each of the following:
a) Determine if the hand contains a pair.
b) Determine if the hand contains two pairs.
c) Determine if the hand contains three of a kind (e.g., three jacks).
d) Determine if the hand contains four of a kind (e.g., four aces).
e) Determine if the hand contains a flush (i.e., all five cards of the same suit).
f) Determine if the hand contains a straight (i.e., five cards of consecutive face values).
1// Exercise 5.12 Solution
2#include <iostream>
3
4using std::cout;
5using std::ios;
6
7#include <iomanip>
8
172 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
9using std::setw;
10 using std::setprecision;
11 using std::setiosflags;
12 using std::resetiosflags;
13
14 #include <cstdlib>
15 #include <ctime>
16
17 void shuffle( int [][ 13 ] );
18 void deal( const int [][ 13 ], const char *[], const char *[], int [][ 2 ] );
19 void pair( const int [][ 13 ], const int [][ 2 ], const char *[] );
20 void threeOfKind( const int [][ 13 ], const int [][ 2 ], const char *[] );
21 void fourOfKind( const int [][ 13 ], const int [][ 2 ], const char *[] );
22 void flushHand( const int [][ 13 ], const int [][ 2 ], const char *[] );
23 void straightHand( const int [][ 13 ], const int [][ 2 ], const char *[],
24 const char *[] );
25
26 int main()
27 {
28 const char *suit[] = { "Hearts", "Diamonds", "Clubs", "Spades" },
29 *face[] = { "Ace", "Deuce", "Three", "Four", "Five", "Six",
30 "Seven", "Eight", "Nine", "Ten", "Jack", "Queen",
31 "King" };
32 int deck[ 4 ][ 13 ] = { 0 }, hand[ 5 ][ 2 ] = { 0 };
33
34 srand( time( 0 ) );
35
36 shuffle( deck );
37 deal( deck, face, suit, hand );
38 pair( deck, hand, face );
39 threeOfKind( deck, hand, face );
40 fourOfKind( deck, hand, face );
41 flushHand( deck, hand, suit );
42 straightHand( deck, hand, suit, face );
43
44 return 0;
45 }
46
47 void shuffle( int wDeck[][ 13 ] )
48 {
49 int row, column;
50
51 for ( int card = 1; card <= 52; ++card ) {
52 do {
53 row = rand() % 4;
54 column = rand() % 13;
55 } while ( wDeck[ row ][ column ] != 0 );
56
57 wDeck[ row ][ column ] = card;
58 }
59 }
60
61 // deal a five card poker hand
62 void deal( const int wDeck[][ 13 ], const char *wFace[],
63 const char *wSuit[], int wHand[][ 2 ] )
64 {
65 int r = 0;
66
67 cout << "The hand is:\n";
68
69 for ( int card = 1; card < 6; ++card )
70 for ( int row = 0; row <= 3; ++row )
71 for ( int column = 0; column <= 12; ++column )
Chapter 5 Pointers and Strings Solutions 173
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
72 if ( wDeck[ row ][ column ] == card ) {
73 wHand[ r ][ 0 ] = row;
74 wHand[ r ][ 1 ] = column;
75 cout << setw( 5 ) << wFace[ column ]
76 << " of " << setw( 8 ) << setiosflags( ios::left )
77 << wSuit[ row ] << ( card % 2 == 0 ? '\n' : '\t' )
78 << resetiosflags( ios::left );
79 ++r;
80 }
81
82 cout << '\n';
83 }
84
85 // pair determines if the hand contains one or two pair
86 void pair( const int wDeck[][ 13 ], const int wHand[][ 2 ],
87 const char *wFace[] )
88 {
89 int counter[ 13 ] = { 0 };
90
91 for ( int r = 0; r < 5; ++r )
92 ++counter[ wHand[ r ][ 1 ] ];
93
94 cout << '\n';
95
96 for ( int p = 0; p < 13; ++p )
97 if ( counter[ p ] == 2 )
98 cout << "The hand contains a pair of " << wFace[ p ] << "'s.\n";
99 }
100
101 void threeOfKind( const int wDeck[][ 13 ], const int wHand[][ 2 ],
102 const char *wFace[] )
103 {
104 int counter[ 13 ] = { 0 };
105
106 for ( int r = 0; r < 5; ++r )
107 ++counter[ wHand[ r ][ 1 ] ];
108
109 for ( int t = 0; t < 13; t++ )
110 if ( counter[ t ] == 3 )
111 cout << "The hand contains three " << wFace[ t ] << "'s.\n";
112 }
113
114 void fourOfKind( const int wDeck[][ 13 ], const int wHand[][ 2 ],
115 const char *wFace[] )
116 {
117 int counter[ 13 ] = { 0 };
118
119 for ( int r = 0; r < 5; ++r )
120 ++counter[ wHand[ r ][ 1 ] ];
121
122 for ( int k = 0; k < 13; ++k )
123 if ( counter[ k ] == 4 )
124 cout << "The hand contains four " << wFace[ k ] << "'s.\n";
125 }
126
127 void flushHand( const int wDeck[][ 13 ], const int wHand[][ 2 ],
128 const char *wSuit[] )
129 {
130 int count[ 4 ] = { 0 };
131
132 for ( int r = 0; r < 5; ++r )
133 ++count[ wHand[ r ][ 0 ] ];
174 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.13 Use the functions developed in Exercise 5.12 to write a program that deals two five-card poker hands, evaluates each hand,
and determines which is the better hand.
5.14 Modify the program developed in Exercise 5.13 so that it can simulate the dealer. The dealer’s five-card hand is dealt “face
down” so the player cannot see it. The program should then evaluate the dealer’s hand, and, based on the quality of the hand, the
dealer should draw one, two or three more cards to replace the corresponding number of unneeded cards in the original hand. The
program should then reevaluate the dealer’s hand. (Caution: This is a difficult problem!)
5.15 Modify the program developed in Exercise 5.14 so that it can handle the dealer’s hand automatically, but the player is al-
lowed to decide which cards of the player’s hand to replace. The program should then evaluate both hands and determine who wins.
Now use this new program to play 20 games against the computer. Who wins more games: you or the computer? Have one of your
friends play 20 games against the computer. Who wins more games? Based on the results of these games, make appropriate modi-
fications to refine your poker-playing program. (This, too, is a difficult problem.) Play 20 more games. Does your modified program
play a better game?
5.16 In the card-shuffling and dealing program of Fig. 5.24, we intentionally used an inefficient shuffling algorithm that intro-
duced the possibility of indefinite postponement. In this problem, you will create a high-performance shuffling algorithm that a voids
indefinite postponement.
Modify Fig. 5.24 as follows. Initialize the deck array as shown in Fig. 5.35. Modify the shuffle function to loop row by
row and column by column through the array touching every element once. Each element should be swapped with a randomly
134
135 for ( int f = 0; f < 4; ++f )
136 if ( count[ f ] == 5 )
137 cout << "The hand contains a flush of " << wSuit[ f ] << "'s.\n";
138 }
139
140 void straightHand( const int wDeck[][ 13 ], const int wHand[][ 2 ],
141 const char *wSuit[], const char *wFace[] )
142 {
143 int s[ 5 ] = { 0 }, temp;
144
145 // copy column locations to sort
146 for ( int r = 0; r < 5; ++r )
147 s[ r ] = wHand[ r ][ 1 ];
148
149 // bubble sort column locations
150 for ( int pass = 1; pass < 5; ++pass )
151 for ( int comp = 0; comp < 4; ++comp )
152 if ( s[ comp ] > s[ comp + 1 ] ) {
153 temp = s[ comp ];
154 s[ comp ] = s[ comp + 1 ];
155 s[ comp + 1 ] = temp;
156 }
157
158 // check if sorted columns are a straight
159 if ( s[ 4 ] - 1 == s[ 3 ] && s[ 3 ] - 1 == s[ 2 ]
160 && s[ 2 ] - 1 == s[ 1 ] && s[ 1 ] - 1 == s[ 0 ] ) {
161 cout << "The hand contains a straight consisting of\n";
162
163 for ( int j = 0; j < 5; ++j )
164 cout << wFace[ wHand[ j ][ 1 ] ] << " of " << wSuit[ wHand[ j ][ 0 ] ]
165 << '\n';
166 }
167 }
The hand is:
Ace of Diamonds Jack of Clubs
Ten of Clubs Queen of Clubs
Deuce of Hearts
Chapter 5 Pointers and Strings Solutions 175
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
selected element of the array. Print the resulting array to determine if the deck is satisfactorily shuffled (as in Fig. 5.36, for example).
You may want your program to call the shuffle function several times to ensure a satisfactory shuffle.
Note that although the approach in this problem improves the shuffling algorithm, the dealing algorithm still requires search-
ing the deck array for card 1, then card 2, then card 3, and so on. Worse yet, even after the dealing algorithm locates and deals the
card, the algorithm continues searching through the remainder of the deck. Modify the program of Fig. 5.24 so that once a card is
dealt, no further attempts are made to match that card number, and the program immediately proceeds with dealing the next card.
Unshuffled deck array
0 1 2 3 4 5 6 7 8 9 10 11 12
01 2 3 4 5 6 7 8 9 10 11 12 13
114 15 16 17 18 19 20 21 22 23 24 25 26
227 28 29 30 31 32 33 34 35 36 37 38 39
340 41 42 43 44 45 46 47 48 49 50 51 52
Fig. 5.35 Unshuffled deck array.
Sample shuffled deck array
0 1 2 3 4 5 6 7 8 9 10 11 12
019 40 27 25 36 46 10 34 35 41 18 2 44
113 28 14 16 21 30 8 11 31 17 24 7 1
212 33 15 42 43 23 45 3 29 32 4 47 26
350 38 52 39 48 51 9 5 37 49 22 6 20
Fig. 5.36 Sample shuffled deck array.
1// Exercise 5.16 Solution
2#include <iostream>
3
4using std::cout;
5using std::ios;
6
7
8#include <iomanip>
9using std::setw;
10 using std::setprecision;
11 using std::setiosflags;
12 using std::resetiosflags;
13
14 #include <cstdlib>
15 #include <ctime>
16
17 void shuffle( int [][ 13 ] );
18 void deal( const int [][ 13 ], const char *[], const char *[] );
19
20 int main()
21 {
22 int card = 1, deck[ 4 ][ 13 ] = { 0 };
23 const char *suit[ 4 ] = { "Hearts", "Diamonds", "Clubs", "Spades" };
24 const char *face[ 13 ] = { "Ace", "Deuce", "Three", "Four", "Five", "Six",
176 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
25 "Seven", "Eight", "Nine", "Ten", "Jack", "Queen",
26 "King" };
27
28 srand( time( 0 ) );
29
30 // initialize deck
31 for ( int row = 0; row <= 3; ++row )
32 for ( int column = 0; column <= 12; ++column )
33 deck[ row ][ column ] = card++;
34
35 shuffle( deck );
36 deal( deck, face, suit );
37
38 return 0;
39 }
40
41 void shuffle( int workDeck[][ 13 ] )
42 {
43 int temp, randRow, randColumn;
44
45 for ( int row = 0; row <= 3; ++row )
46 for ( int column = 0; column <= 12; ++column ) {
47 randRow = rand() % 4;
48 randColumn = rand() % 13;
49 temp = workDeck[ row ][ column ];
50 workDeck[ row][ column ] = workDeck[ randRow ][ randColumn ];
51 workDeck[ randRow ][ randColumn ] = temp;
52 }
53 }
54
55 void deal( const int workDeck2[][ 13 ], const char *workFace[],
56 const char *workSuit[] )
57 {
58 for ( int card = 1; card <= 52; ++card )
59 for ( int row = 0; row <= 3; ++row )
60 for ( int column = 0; column <= 12; ++column )
61 if ( workDeck2[ row ][ column ] == card ) {
62 cout << setw( 8 ) << workFace[ column ] << " of "
63 << setiosflags( ios::left ) << setw( 8 )
64 << workSuit[ row ]
65 << ( card % 2 == 0 ? '\n' : '\t' )
66 << resetiosflags( ios::left );
67 break;
68 }
69 }
Chapter 5 Pointers and Strings Solutions 177
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.17 (Simulation: The Tortoise and the Hare) In this problem you will re-create the classic race of the tortoise and the hare. You
will use random-number generation to develop a simulation of this memorable event.
Our contenders begin the race at “square 1” of 70 squares. Each square represents a possible position along the race course.
The finish line is at square 70. The first contender to reach or pass square 70 is rewarded with a pail of fresh carrots and lettuce.
The course weaves its way up the side of a slippery mountain, so occasionally the contenders lose ground.
There is a clock that ticks once per second. With each tick of the clock, your program should adjust the position of the animals
according to the following rules:
Use variables to keep track of the positions of the animals (i.e., position numbers are 1–70). Start each animal at position 1
(i.e., the “starting gate”). If an animal slips left before square 1, move the animal back to square 1.
Generate the percentages in the preceding table by producing a random integer i in the range 1 i 10. For the tortoise, per-
form a “fast plod” when 1 i 5, a “slip” when 6 i 7 or a “slow plod” when 8 i 10. Use a similar technique to move the
hare.
King of Hearts King of Diamonds
Eight of Spades Four of Clubs
Five of Clubs Queen of Hearts
Eight of Hearts Nine of Diamonds
Ace of Clubs Deuce of Clubs
Six of Diamonds Five of Hearts
Seven of Hearts Nine of Hearts
Six of Spades Jack of Diamonds
Five of Spades Queen of Diamonds
King of Clubs King of Spades
Five of Diamonds Seven of Diamonds
Eight of Diamonds Four of Hearts
Four of Spades Ten of Hearts
Three of Spades Three of Diamonds
Ten of Spades Four of Diamonds
Ten of Diamonds Deuce of Hearts
Ace of Diamonds Six of Hearts
Nine of Clubs Nine of Spades
Deuce of Spades Eight of Clubs
Queen of Spades Six of Clubs
Seven of Clubs Jack of Clubs
Ace of Hearts Three of Clubs
Deuce of Diamonds Queen of Clubs
Seven of Spades Ace of Spades
Jack of Hearts Jack of Spades
Ten of Clubs Three of Hearts
Animal Move type
Percentage of the
time Actual move
Tortoise Fast plod 50% 3 squares to the right
Slip 20% 6 squares to the left
Slow plod 30% 1 square to the right
Hare Sleep 20% No move at all
Big hop 20% 9 squares to the right
Big slip 10% 12 squares to the left
Small hop 30% 1 square to the right
Small slip 20% 2 squares to the left
178 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Begin the race by printing
BANG !!!!!
AND THEY'RE OFF !!!!!
For each tick of the clock (i.e., each repetition of a loop), print a 70-position line showing the letter T in the tortoise’s position
and the letter H in the hare’s position. Occasionally, the contenders land on the same square. In this case, the tortoise bites the hare,
and your program should print OUCH!!! beginning at that position. All print positions other than the T, the H or the OUCH!!! (in
case of a tie) should be blank.
After printing each line, test if either animal has reached or passed square 70. If so, print the winner and terminate the simula-
tion. If the tortoise wins, print TORTOISE WINS!!! YAY!!! If the hare wins, print Hare wins. Yuch. If both animals win
on the same clock tick, you may want to favor the turtle (the “underdog”), or you may want to print It's a tie. If neither animal
wins, perform the loop again to simulate the next tick of the clock. When you are ready to run your program, assemble a group of
fans to watch the race. You’ll be amazed how involved the audience gets!
1// Exercise 5.17 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <cstdlib>
8#include <ctime>
9
10 #include <iomanip>
11
12 using std::setw;
13
14 const int RACE_END = 70;
15
16 void moveTortoise( int * const );
17 void moveHare( int * const );
18 void printCurrentPositions( const int * const, const int * const );
19
20 int main()
21 {
22 int tortoise = 1, hare = 1, timer = 0;
23
24 srand( time( 0 ) );
25
26 cout << "ON YOUR MARK, GET SET\nBANG !!!!"
27 << "\nAND THEY'RE OFF !!!!\n";
28
29 while ( tortoise != RACE_END && hare != RACE_END ) {
30 moveTortoise( &tortoise );
31 moveHare( &hare );
32 printCurrentPositions( &tortoise, &hare );
33 ++timer;
34 }
35
36 if ( tortoise >= hare )
37 cout << "\nTORTOISE WINS!!! YAY!!!\n";
38 else
39 cout << "Hare wins. Yuch.\n";
40
41 cout << "TIME ELAPSED = " << timer << " seconds" << endl;
42
43 return 0;
44 }
45
46 void moveTortoise( int * const turtlePtr )
Chapter 5 Pointers and Strings Solutions 179
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
47 {
48 int x = 1 + rand() % 10;
49
50 if ( x >= 1 && x <= 5 ) // fast plod
51 *turtlePtr += 3;
52 else if ( x == 6 || x == 7 ) // slip
53 *turtlePtr -= 6;
54 else // slow plod
55 ++( *turtlePtr );
56
57 if ( *turtlePtr < 1 )
58 *turtlePtr = 1;
59 else if ( *turtlePtr > RACE_END )
60 *turtlePtr = RACE_END;
61 }
62
63 void moveHare( int * const rabbitPtr )
64 {
65 int y = 1 + rand() % 10;
66
67 if ( y == 3 || y == 4 ) // big hop
68 *rabbitPtr += 9;
69 else if ( y == 5 ) // big slip
70 *rabbitPtr -= 12;
71 else if ( y >= 6 && y <= 8 ) // small hop
72 ++( *rabbitPtr );
73 else if ( y > 8 ) // small slip
74 *rabbitPtr -= 2;
75
76 if ( *rabbitPtr < 1 )
77 *rabbitPtr = 1;
78 else if ( *rabbitPtr > RACE_END )
79 *rabbitPtr = RACE_END;
80 }
81
82 void printCurrentPositions( const int * const snapperPtr,
83 const int * const bunnyPtr )
84 {
85 if ( *bunnyPtr == *snapperPtr )
86 cout << setw( *bunnyPtr ) << "OUCH!!!";
87 else if ( *bunnyPtr < *snapperPtr )
88 cout << setw( *bunnyPtr ) << 'H'
89 << setw( *snapperPtr - *bunnyPtr ) << 'T';
90 else
91 cout << setw( *snapperPtr ) << 'T'
92 << setw( *bunnyPtr - *snapperPtr ) << 'H';
93
94 cout << '\n';
95 }
180 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
ON YOUR MARK, GET SET
BANG !!!!
AND THEY'RE OFF !!!!
H T
T H
T H
T H
T H
T H
T H
T H
T H
T H
T H
T H
T H
T H
T H
T H
T H
T H
T H
T H
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
H T
TORTOISE WINS!!! YAY!!!
TIME ELAPSED = 59 seconds
Chapter 5 Pointers and Strings Solutions 181
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
SPECIAL SECTION: BUILDING YOUR OWN COMPUTER
In the next several problems, we take a temporary diversion away from the world of high-level-language programming. We “peel
open” a computer and look at its internal structure. We introduce machine-language programming and write several machine-lan-
guage programs. To make this an especially valuable experience, we then build a computer (through the technique of software-
based simulation) on which you can execute your machine-language programs!
5.18 (Machine-Language Programming) Let us create a computer we will call the Simpletron. As its name implies, it is a simple
machine, but, as we will soon see, a powerful one as well. The Simpletron runs programs written in the only language it directly
understands; that is, Simpletron Machine Language, or SML for short.
The Simpletron contains an accumulator—a “special register” in which information is put before the Simpletron uses that
information in calculations or examines it in various ways. All information in the Simpletron is handled in terms of words. A word
is a signed four-digit decimal number, such as +3364, -1293, +0007, -0001, etc. The Simpletron is equipped with a 100-word
memory, and these words are referenced by their location numbers 00, 01, , 99.
Before running an SML program, we must load, or place, the program into memory. The first instruction (or statement) of
every SML program is always placed in location 00. The simulator will start executing at this location.
Each instruction written in SML occupies one word of the Simpletron’s memory. (Thus, instructions are signed four-digit dec-
imal numbers.) We shall assume that the sign of an SML instruction is always plus, but the sign of a data word may be either plus
or minus. Each location in the Simpletron’s memory may contain an instruction, a data value used by a program or an unused (and
hence undefined) area of memory. The first two digits of each SML instruction are the operation code that specifies the operation
to be performed. SML operation codes are shown in Fig. 5.37.
Operation code Meaning
Input/output operations:
const int READ = 10 Read a word from the keyboard into a specific
location in memory.
const int WRITE = 11; Write a word from a specific location in memory
to the screen.
Load and store operations:
const int LOAD = 20; Load a word from a specific location in memory
into the accumulator.
const int STORE = 21; Store a word from the accumulator into a spe-
cific location in memory.
Arithmetic operations:
const int ADD = 30; Add a word from a specific location in memory
to the word in the accumulator (leave result in
accumulator).
const int SUBTRACT = 31; Subtract a word from a specific location in mem-
ory from the word in the accumulator (leave
result in accumulator).
const int DIVIDE = 32; Divide a word from a specific location in mem-
ory into the word in the accumulator (leave result
in accumulator).
const int MULTIPLY = 33; Multiply a word from a specific location in
memory by the word in the accumulator (leave
result in accumulator).
Transfer of control operations:
const int BRANCH = 40; Branch to a specific location in memory.
Fig. 5.37 Simpletron Machine Language (SML) operation codes (part 1 of 2).
182 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
The last two digits of an SML instruction are the operand—the address of the memory location containing the word to which
the operation applies.
Now let us consider several simple SML programs. The first SML program (Example 1) reads two numbers from the key-
board and computes and prints their sum. The instruction +1007 reads the first number from the keyboard and places it into loca-
tion 07 (which has been initialized to zero). Then instruction +1008 reads the next number into location 08. The load instruction,
+2007, puts (copies) the first number into the accumulator, and the add instruction, +3008, adds the second number to the num-
ber in the accumulator. All SML arithmetic instructions leave their results in the accumulator. The store instruction, +2109, places
(copies) the result back into memory location 09 from which the write instruction, +1109, takes the number and prints it (as a
signed four-digit decimal number). The halt instruction, +4300, terminates execution.
The SML program in Example 2 reads two numbers from the keyboard and determines and prints the larger value. Note the
use of the instruction +4107 as a conditional transfer of control, much the same as C++’s if statement.
const int BRANCHNEG = 41; Branch to a specific location in memory if the
accumulator is negative.
const int BRANCHZERO = 42; Branch to a specific location in memory if the
accumulator is zero.
const int HALT = 43; Halt—the program has completed its task.
Example 1
Location Number Instruction
00 +1007 (Read A)
01 +1008 (Read B)
02 +2007 (Load A)
03 +3008 (Add B)
04 +2109 (Store C)
05 +1109 (Write C)
06 +4300 (Halt)
07 +0000 (Variable A)
08 +0000 (Variable B)
09 +0000 (Result C)
Example 2
Location Number Instruction
00 +1009 (Read A)
01 +1010 (Read B)
02 +2009 (Load A)
03 +3110 (Subtract B)
04 +4107 (Branch negative to 07)
05 +1109 (Write A)
06 +4300 (Halt)
07 +1110 (Write B)
Operation code Meaning
Fig. 5.37 Simpletron Machine Language (SML) operation codes (part 2 of 2).
Chapter 5 Pointers and Strings Solutions 183
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Now write SML programs to accomplish each of the following tasks.
a) Use a sentinel-controlled loop to read positive numbers and compute and print their sum. Terminate input when a neg-
ative number is entered.
b) Use a counter-controlled loop to read seven numbers, some positive and some negative, and compute and print their
average.
c) Read a series of numbers and determine and print the largest number. The first number read indicates how many num-
bers should be processed.
5.19 (A Computer Simulator) It may at first seem outrageous, but in this problem, you are going to build your own computer.
No, you will not be soldering components together. Rather, you will use the powerful technique of software-based simulation to
create a software model of the Simpletron. You will not be disappointed. Your Simpletron simulator will turn the computer you are
using into a Simpletron, and you will actually be able to run, test and debug the SML programs you wrote in Exercise 5.18.
When you run your Simpletron simulator, it should begin by printing
*** Welcome to Simpletron! ***
*** Please enter your program one instruction ***
*** (or data word) at a time. I will type the ***
*** location number and a question mark (?). ***
*** You then type the word for that location. ***
*** Type the sentinel -99999 to stop entering ***
*** your program. ***
Simulate the memory of the Simpletron with a single-subscripted array memory that has 100 elements. Now assume that the
simulator is running, and let us examine the dialog as we enter the program of Example 2 of Exercise 5.18:
00 ? +1009
01 ? +1010
02 ? +2009
03 ? +3110
04 ? +4107
05 ? +1109
06 ? +4300
07 ? +1110
08 ? +4300
09 ? +0000
10 ? +0000
11 ? -99999
*** Program loading completed ***
*** Program execution begins ***
The SML program has now been placed (or loaded) in array memory. Now the Simpletron executes your SML program. Exe-
cution begins with the instruction in location 00 and, like C++, continues sequentially, unless directed to some other part of the
program by a transfer of control.
Use the variable accumulator to represent the accumulator register. Use the variable counter to keep track of the loca-
tion in memory that contains the instruction being performed. Use variable operationCode to indicate the operation currently
being performed (i.e., the left two digits of the instruction word). Use variable operand to indicate the memory location on which
the current instruction operates. Thus, operand is the rightmost two digits of the instruction currently being performed. Do not
execute instructions directly from memory. Rather, transfer the next instruction to be performed from memory to a variable called
instructionRegister. Then “pick off” the left two digits and place them in operationCode, and “pick off” the right two
digits and place them in operand. When Simpletron begins execution, the special registers are all initialized to zero.
08 +4300 (Halt)
09 +0000 (Variable A)
10 +0000 (Variable B)
Example 2
Location Number Instruction
184 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Now let us “walk through” the execution of the first SML instruction, +1009 in memory location 00. This is called an
instruction execution cycle.
The counter tells us the location of the next instruction to be performed. We fetch the contents of that location from mem-
ory by using the C++ statement
instructionRegister = memory[ counter ];
The operation code and operand are extracted from the instruction register by the statements
operationCode = instructionRegister / 100;
operand = instructionRegister % 100;
Now the Simpletron must determine that the operation code is actually a read (versus a write, a load, etc.). A switch differ-
entiates among the twelve operations of SML.
In the switch structure, the behavior of various SML instructions is simulated as follows (we leave the others to the reader):
read: cin >> memory[ operand ];
load: accumulator = memory[ operand ];
add: accumulator += memory[ operand ];
branch: We will discuss the branch instructions shortly.
halt: This instruction prints the message
*** Simpletron execution terminated ***
It then prints the name and contents of each register, as well as the complete contents of memory. Such a printout is often called a
computer dump (and, no, a computer dump is not a place where old computers go). To help you program your dump function, a
sample dump format is shown in Fig. 5.38. Note that a dump after executing a Simpletron program would show the actual values of
instructions and data values at the moment execution terminated.
Let us proceed with the execution of our program’s first instruction—+1009 in location 00. As we have indicated, the
switch statement simulates this by performing the C++ statement
cin >> memory[ operand ];
A question mark (?) should be displayed on the screen before the cin is executed to prompt the user for input. The Sim-
pletron waits for the user to type a value and then press the Return key. The value is then read into location 09.
At this point, simulation of the first instruction is completed. All that remains is to prepare the Simpletron to execute the next
instruction. Since the instruction just performed was not a transfer of control, we need merely increment the instruction counter
register as follows:
++counter;
This completes the simulated execution of the first instruction. The entire process (i.e., the instruction execution cycle) begins
anew with the fetch of the next instruction to be executed.
Now let us consider how the branching instructions—the transfers of control—are simulated. All we need to do is adjust the
value in the instruction counter appropriately. Therefore, the unconditional branch instruction (40) is simulated within the
switch as
counter = operand;
The conditional “branch if accumulator is zero” instruction is simulated as
if ( accumulator == 0 )
counter = operand;
At this point you should implement your Simpletron simulator and run each of the SML programs you wrote in Exercise 5.18.
You may embellish SML with additional features and provide for these in your simulator.
Your simulator should check for various types of errors. During the program loading phase, for example, each number the
Chapter 5 Pointers and Strings Solutions 185
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
user types into the Simpletron’s memory must be in the range -9999 to +9999. Your simulator should use a while loop to test
that each number entered is in this range and, if not, keep prompting the user to reenter the number until the user enters a correct
number.
During the execution phase, your simulator should check for various serious errors, such as attempts to divide by zero,
attempts to execute invalid operation codes, accumulator overflows (i.e., arithmetic operations resulting in values larger than
+9999 or smaller than -9999) and the like. Such serious errors are called fatal errors. When a fatal error is detected, your simu-
lator should print an error message such as
*** Attempt to divide by zero ***
*** Simpletron execution abnormally terminated ***
and should print a full computer dump in the format we have discussed previously. This will help the user locate the error in the
program.
REGISTERS:
accumulator +0000
counter 00
instructionRegister +0000
operationCode 00
operand 00
MEMORY:
0 1 2 3 4 5 6 7 8 9
0 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
10 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
20 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
30 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
40 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
50 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
60 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
70 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
80 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
90 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
Fig. 5.38 A sample dump.
1// Exercise 5.19 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setfill;
12 using std::setw;
13 using std::setiosflags;
14 using std::resetiosflags;
15
16 const int SIZE = 100, MAX_WORD = 9999, MIN_WORD = -9999;
17 const long SENTINEL = -99999;
18 enum Commands { READ = 10, WRITE, LOAD = 20, STORE, ADD = 30, SUBTRACT,
19 DIVIDE, MULTIPLY, BRANCH = 40, BRANCHNEG, BRANCHZERO, HALT };
20
21 void load( int * const );
22 void execute( int * const, int * const, int * const, int * const,
186 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
23 int * const, int * const);
24 void dump( const int * const, int, int, int, int, int );
25 bool validWord( int );
26
27 int main()
28 {
29 int memory[ SIZE ] = { 0 }, accumulator = 0, instructionCounter = 0,
30 opCode = 0, operand = 0, instructionRegister = 0;
31
32 load( memory );
33 execute( memory, &accumulator, &instructionCounter, &instructionRegister,
34 &opCode, &operand );
35 dump( memory, accumulator, instructionCounter, instructionRegister,
36 opCode, operand );
37
38 return 0;
39 }
40
41 void load( int * const loadMemory )
42 {
43 long instruction;
44 int i = 0;
45
46 cout << "*** Welcome to Simpletron ***\n"
47 << "*** Please enter your program one instruction ***\n"
48 << "*** (or data word) at a time. I will type the ***\n"
49 << "*** location number and a question mark (?). ***\n"
50 << "*** You then type the word for that location. ***\n"
51 << "*** Type the sentinel -99999 to stop entering ***\n"
52 << "*** your program. ***\n" << "00 ? ";
53 cin >> instruction;
54
55 while ( instruction != SENTINEL ) {
56
57 if ( !validWord( instruction ) )
58 cout << "Number out of range. Please enter again.\n";
59 else
60 loadMemory[ i++ ] = instruction;
61
62 // function setfill sets the padding character for unused
63 // field widths.
64 cout << setw( 2 ) << setfill( '0' ) << i << " ? ";
65 cin >> instruction;
66 }
67 }
68
69 void execute( int * const memory, int * const acPtr, int * const icPtr,
70 int * const irPtr, int * const opCodePtr, int * const opPtr )
71 {
72 bool fatal = false;
73 int temp;
74 const char *messages[] = { "Accumulator overflow ***",
75 "Attempt to divide by zero ***",
76 "Invalid opcode detected ***" },
77 *termString = "\n*** Simpletron execution abnormally terminated ***",
78 *fatalString = "*** FATAL ERROR: ";
79
80 cout << "\n************START SIMPLETRON EXECUTION************\n\n";
81
82 do {
83 *irPtr = memory[ *icPtr ];
84 *opCodePtr = *irPtr / 100;
Chapter 5 Pointers and Strings Solutions 187
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
85 *opPtr = *irPtr % 100;
86
87 switch ( *opCodePtr ) {
88 case READ:
89 cout << "Enter an integer: ";
90 cin >> temp;
91
92 while ( !validWord( temp ) ) {
93 cout << "Number out of range. Please enter again: ";
94 cin >> temp;
95 }
96
97 memory[ *opPtr ] = temp;
98 ++( *icPtr );
99 break;
100 case WRITE:
101 cout << "Contents of " << setw( 2 ) << setfill( '0' ) << *opPtr
102 << ": " << memory[ *opPtr ] << '\n';
103 ++( *icPtr );
104 break;
105 case LOAD:
106 *acPtr = memory[ *opPtr ];
107 ++( *icPtr );
108 break;
109 case STORE:
110 memory[ *opPtr ] = *acPtr;
111 ++( *icPtr );
112 break;
113 case ADD:
114 temp = *acPtr + memory[ *opPtr ];
115
116 if ( !validWord( temp ) ) {
117 cout << fatalString << messages[ 0 ] << termString << '\n';
118 fatal = true;
119 }
120 else {
121 *acPtr = temp;
122 ++( *icPtr );
123 }
124
125 break;
126 case SUBTRACT:
127 temp = *acPtr - memory[ *opPtr ];
128
129 if ( !validWord( temp ) ) {
130 cout << fatalString << messages[ 0 ] << termString << '\n';
131 fatal = true;
132 }
133 else {
134 *acPtr = temp;
135 ++( *icPtr );
136 }
137
138 break;
139 case DIVIDE:
140 if ( memory[ *opPtr ] == 0 ) {
141 cout << fatalString << messages[ 1 ] << termString << '\n';
142 fatal = true;
143 }
144 else {
145 *acPtr /= memory[ *opPtr ];
146 ++( *icPtr );
147 }
188 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
148
149 break;
150 case MULTIPLY:
151 temp = *acPtr * memory[ *opPtr ];
152
153 if ( !validWord( temp ) ) {
154 cout << fatalString << messages[ 0 ] << termString << '\n';
155 fatal = true;
156 }
157 else {
158 *acPtr = temp;
159 ++( *icPtr );
160 }
161 break;
162 case BRANCH:
163 *icPtr = *opPtr;
164 break;
165 case BRANCHNEG:
166 *acPtr < 0 ? *icPtr = *opPtr : ++( *icPtr );
167 break;
168 case BRANCHZERO:
169 *acPtr == 0 ? *icPtr = *opPtr : ++( *icPtr );
170 break;
171 case HALT:
172 cout << "*** Simpletron execution terminated ***\n";
173 break;
174 default:
175 cout << fatalString << messages[ 2 ] << termString << '\n';
176 fatal = true;
177 break;
178 }
179 } while ( *opCodePtr != HALT && !fatal );
180
181 cout << "\n*************END SIMPLETRON EXECUTION*************\n";
182 }
183
184 void dump( const int * const memory, int accumulator, int instructionCounter,
185 int instructionRegister, int operationCode, int operand )
186 {
187 void output( const char * const, int, int, bool ); // prototype
188
189 cout << "\nREGISTERS:\n";
190 output( "accumulator", 5, accumulator, true );
191 output( "instructionCounter", 2, instructionCounter, false );
192 output( "instructionRegister", 5, instructionRegister, true );
193 output( "operationCode", 2, operationCode, false );
194 output( "operand", 2, operand, false );
195 cout << "\n\nMEMORY:\n";
196
197 int i = 0;
198 cout << setfill( ' ' ) << setw( 3 ) << ' ';
199
200 // print header
201 for ( ; i <= 9; ++i )
202 cout << setw( 5 ) << i << ' ';
203
204 for ( i = 0; i < SIZE; ++i ) {
205 if ( i % 10 == 0 )
206 cout << '\n' << setw( 2 ) << i << ' ';
207
208 cout << setiosflags( ios::internal | ios::showpos )
209 << setw( 5 ) << setfill( '0' ) << memory[ i ] << ' '
210 << resetiosflags( ios::internal | ios::showpos );
Chapter 5 Pointers and Strings Solutions 189
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
211 }
212
213 cout << endl;
214 }
215
216 bool validWord( int word )
217 {
218 return word >= MIN_WORD && word <= MAX_WORD;
219 }
220
221 void output( const char * const sPtr, int width, int value, bool sign )
222 {
223 // format of "accumulator", etc.
224 cout << setfill( ' ' ) << setiosflags( ios::left ) << setw( 20 )
225 << sPtr << ' ';
226
227 // is a +/- sign needed?
228 if ( sign )
229 cout << setiosflags( ios::showpos | ios::internal );
230
231 // setup for displaying accumulator value, etc.
232 cout << resetiosflags( ios::left ) << setfill( '0' );
233
234 // determine the field widths and display value
235 if ( width == 5 )
236 cout << setw( width ) << value << '\n';
237 else // width is 2
238 cout << setfill( ' ' ) << setw( 3 ) << ' ' << setw( width )
239 << setfill( '0' ) << value << '\n';
240
241 // disable sign if it was set
242 if ( sign )
243 cout << resetiosflags( ios::showpos | ios::internal );
244 }
190 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
MORE POINTER EXERCISES
5.20 Modify the card-shuffling and dealing program of Fig. 5.24 so the shuffling and dealing operations are performed by the
same function (shuffleAndDeal). The function should contain one nested looping structure that is similar to function shuffle
in Fig. 5.24.
*** Welcome to Simpletron ***
*** Please enter your program one instruction ***
*** (or data word) at a time. I will type the ***
*** location number and a question mark (?). ***
*** You then type the word for that location. ***
*** Type the sentinel -99999 to stop entering ***
*** your program. ***
00 ? 1099
01 ? 1098
02 ? 2099
03 ? 3398
04 ? 2150
05 ? 1150
06 ? 1199
07 ? 1198
08 ? 4300
09 ? -99999
************START SIMPLETRON EXECUTION************
Enter an integer: 4
Enter an integer: 9
Contents of 50: 36
Contents of 99: 4
Contents of 98: 9
*** Simpletron execution terminated ***
*************END SIMPLETRON EXECUTION*************
REGISTERS:
accumulator +0036
instructionCounter 08
instructionRegister +4300
operationCode 43
operand 00
MEMORY:
0 1 2 3 4 5 6 7 8 9
0 +1099 +1098 +2099 +3398 +2150 +1150 +1199 +1198 +4300 +0000
10 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
20 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
30 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
40 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
50 +0036 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
60 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
70 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
80 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
90 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0009 +0004
1// Exercise 5.20 Solution
2#include <iostream>
3
4using std::cout;
Chapter 5 Pointers and Strings Solutions 191
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5using std::ios;
6
7#include <iomanip>
8
9using std::setw;
10 using std::setiosflags;
11 using std::resetiosflags;
12
13 #include <cstdlib>
14 #include <ctime>
15
16 void shuffleAndDeal( int [][ 13 ], const char *[], const char *[] );
17
18 int main()
19 {
20 const char *suit[ 4 ] = { "Hearts", "Diamonds", "Clubs", "Spades" };
21 const char *face[ 13 ] = { "Ace", "Deuce", "Three", "Four", "Five",
22 "Six", "Seven", "Eight", "Nine", "Ten",
23 "Jack", "Queen", "King" };
24 int deck[ 4 ][ 13 ] = { 0 };
25
26 srand( time( 0 ) );
27 shuffleAndDeal( deck, face, suit );
28
29 return 0;
30 }
31
32 void shuffleAndDeal( int workDeck[][ 13 ], const char *workFace[],
33 const char *workSuit[] )
34 {
35 int row, column;
36
37 for ( int card = 1; card <= 52; ++card ) {
38
39 do {
40 row = rand() % 4;
41 column = rand() % 13;
42 } while ( workDeck[ row ][ column ] != 0 );
43
44 workDeck[ row ][ column ] = card;
45 cout << setw( 8 ) << workFace[ column ] << " of "
46 << setiosflags( ios::left ) << setw( 8 )
47 << workSuit[ row ] << resetiosflags( ios::left )
48 << ( card % 2 == 0 ? '\n' : '\t' );
49 }
50 }
192 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.21 What does this program do?
Six of Hearts Ten of Diamonds
Deuce of Spades Five of Hearts
Ace of Spades Nine of Spades
Seven of Diamonds King of Spades
Nine of Diamonds Eight of Spades
Five of Clubs Seven of Spades
Deuce of Clubs Four of Clubs
Ten of Hearts Jack of Diamonds
Nine of Clubs Four of Diamonds
Ace of Hearts Five of Spades
Jack of Hearts Deuce of Diamonds
Ten of Spades Queen of Hearts
Queen of Spades Queen of Diamonds
King of Clubs Six of Spades
Deuce of Hearts Three of Spades
King of Diamonds Three of Hearts
Four of Hearts Jack of Spades
Jack of Clubs Three of Clubs
Four of Spades Three of Diamonds
Ace of Diamonds Nine of Hearts
Seven of Clubs Eight of Diamonds
Eight of Clubs Seven of Hearts
Eight of Hearts Queen of Clubs
Six of Clubs Ace of Clubs
Five of Diamonds King of Hearts
Ten of Clubs Six of Diamonds
1// ex05_21.cpp
2#include <iostream>
3
4using std::cout;
5using std::cin;
6using std::endl;
7
8void mystery1( char *, const char * );
9
10 int main()
11 {
12 char string1[ 80 ], string2[ 80 ];
13
14 cout << "Enter two strings: ";
15 cin >> string1 >> string2;
16 mystery1( string1, string2 );
17 cout << string1 << endl;
18
19 return 0;
20 }
21
22 void mystery1( char *s1, const char *s2 )
23 {
24 while ( *s1 != '\0' )
25 ++s1;
26
27 for ( ; *s1 = *s2; s1++, s2++ )
28 ; // empty statement
29 }
Chapter 5 Pointers and Strings Solutions 193
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.22 What does this program do?
5.23 Find the error in each of the following program segments. If the error can be corrected, explain how.
a) int *number;
cout << number << endl;
ANS: Pointer number does not "point" to a valid address. Assigning number to an address would correct the problem.
b) double *realPtr;
long *integerPtr;
integerPtr = realPtr;
ANS: A pointer of type float cannot be directly assigned to a pointer of type long.
c) int * x, y;
x = y;
ANS: Variable y is not a pointer, and therefore cannot be assigned to x. Change the assignment statement to x = &y;.
d) char s[] = "this is a character array";
for ( ; *s != '\0'; s++)
cout << *s << ' ';
ANS: s is not a modifiable value. Attempting to use operator ++ is a syntax error. Changing to [] notation corrects the
problem as in:
for ( int t = 0; s[ t ] != ’\0’; ++t )
cout << s[ t ] << ’ ’;
Enter two strings: string1 string2
string1string2
1// ex05_22.cpp
2#include <iostream>
3
4using std::cout;
5using std::cin;
6using std::endl;
7
8int mystery2( const char * );
9
10 int main()
11 {
12 char string[ 80 ];
13
14 cout << "Enter a string: ";
15 cin >> string;
16 cout << mystery2( string ) << endl;
17
18 return 0;
19 }
20
21 int mystery2( const char *s )
22 {
23 int x;
24
25 for ( x = 0; *s != '\0'; s++ )
26 ++x;
27
28 return x;
29 }
Enter a string: length
6
194 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
e) short *numPtr, result;
void *genericPtr = numPtr;
result = *genericPtr + 7;
ANS: A void * pointer cannot be dereferenced.
f) double x = 19.34;
double xPtr = &x;
cout << xPtr << endl;
ANS: xPtr is not a pointer and therefore cannot be assigned an address. Place a * before xPtr (in the declaration) to
correct the problem. The cout statement display’s the address to which xPtr points (once the previous correction is
made)—this is not an error.
g) char *s;
cout << s << endl;
ANS: s does not "point" to anything. s should be provided with an address.
5.24 (Quicksort) In the examples and exercises of Chapter 4, we discussed the sorting techniques of the bubble sort, bucket sort,
and selection sort. We now present the recursive sorting technique called Quicksort. The basic algorithm for a single-subscripted
array of values is as follows:
a) Partitioning Step: Take the first element of the unsorted array and determine its final location in the sorted array (i.e.,
all values to the left of the element in the array are less than the element, and all values to the right of the element in the
array are greater than the element). We now have one element in its proper location and two unsorted subarrays.
b) Recursive Step: Perform step 1 on each unsorted subarray.
Each time step 1 is performed on a subarray, another element is placed in its final location of the sorted array, and two unsorted
subarrays are created. When a subarray consists of one element, it must be sorted, therefore that element is in its final location.
The basic algorithm seems simple enough, but how do we determine the final position of the first element of each subarray.
As an example, consider the following set of values (the element in bold is the partitioning element—it will be placed in its final
location in the sorted array):
37 2 6 4 89 8 10 12 68 45
a) Starting from the rightmost element of the array, compare each element with 37 until an element less than 37 is found.
Then swap 37 and that element. The first element less than 37 is 12, so 37 and 12 are swapped. The new array is
12 2 6 4 89 8 10 37 68 45
Element 12 is in italic to indicate that it was just swapped with 37.
b) Starting from the left of the array, but beginning with the element after 12, compare each element with 37 until an ele-
ment greater than 37 is found. Then swap 37 and that element. The first element greater than 37 is 89, so 37 and 89 are
swapped. The new array is
12 2 6 4 37 8 10 89 68 45
c) Starting from the right, but beginning with the element before 89, compare each element with 37 until an element less
than 37 is found. Then swap 37 and that element. The first element less than 37 is 10, so 37 and 10 are swapped. The
new array is
12 2 6 4 10 8 37 89 68 45
d) Starting from the left, but beginning with the element after 10, compare each element with 37 until an element greater
than 37 is found. Then swap 37 and that element. There are no more elements greater than 37, so when we compare 37
with itself, we know that 37 has been placed in its final location of the sorted array.
Once the partition has been applied on the array, there are two unsorted subarrays. The subarray with values less than 37 contains
12, 2, 6, 4, 10 and 8. The subarray with values greater than 37 contains 89, 68 and 45. The sort continues with both subarrays being
partitioned in the same manner as the original array.
Based on the preceding discussion, write recursive function quickSort to sort a single-subscripted integer array. The func-
tion should receive as arguments an integer array, a starting subscript and an ending subscript. Function partition should be
called by quickSort to perform the partitioning step.
Chapter 5 Pointers and Strings Solutions 195
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1// Exercise 5.24 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <iomanip>
8
9using std::setw;
10
11 #include <cstdlib>
12 #include <ctime>
13
14 const int SIZE = 10, MAX_NUMBER = 1000;
15
16 void quicksort( int * const, int, int );
17 void swap( int * const, int * const );
18
19 int main()
20 {
21 int arrayToBeSorted[ SIZE ] = { 0 };
22 int loop;
23
24 srand( time( 0 ) );
25
26 for ( loop = 0; loop < SIZE; ++loop )
27 arrayToBeSorted[ loop ] = rand() % MAX_NUMBER;
28
29 cout << "Initial array values are:\n";
30
31 for ( loop = 0; loop < SIZE; ++loop )
32 cout << setw( 4 ) << arrayToBeSorted[ loop ];
33
34 cout << "\n\n";
35
36 if ( SIZE == 1 )
37 cout << "Array is sorted: " << arrayToBeSorted[ 0 ] << '\n';
38 else {
39 quicksort( arrayToBeSorted, 0, SIZE - 1 );
40 cout << "The sorted array values are:\n";
41
42 for ( loop = 0; loop < SIZE; ++loop )
43 cout << setw( 4 ) << arrayToBeSorted[ loop ];
44
45 cout << endl;
46 }
47
48 return 0;
49 }
50
51 void quicksort( int * const array, int first, int last )
52 {
53 int partition( int * const, int, int );
54 int currentLocation;
55
56 if ( first >= last )
57 return;
58
59 currentLocation = partition( array, first, last ); // place an element
60 quicksort( array, first, currentLocation - 1 ); // sort left side
196 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
61 quicksort( array, currentLocation + 1, last ); // sort right side
62 }
63
64 int partition( int * const array, int left, int right )
65 {
66 int position = left;
67
68 while ( true ) {
69 while ( array[ position ] <= array[ right ] && position != right )
70 --right;
71
72 if ( position == right )
73 return position;
74
75 if ( array[ position ] > array[ right ]) {
76 swap( &array[ position ], &array[ right ] );
77 position = right;
78 }
79
80 while ( array[ left ] <= array[ position ] && left != position )
81 ++left;
82
83 if ( position == left )
84 return position;
85
86 if ( array[ left ] > array[ position ] ) {
87 swap( &array[ position ], &array[ left ] );
88 position = left;
89 }
90 }
91 }
92
93 void swap( int * const ptr1, int * const ptr2 )
94 {
95 int temp;
96
97 temp = *ptr1;
98 *ptr1 = *ptr2;
99 *ptr2 = temp;
100 }
Initial array values are:
407 766 451 328 17 50 551 620 192 35
The sorted array values are:
17 35 50 192 328 407 451 551 620 766
Chapter 5 Pointers and Strings Solutions 197
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.25 (Maze Traversal) The following grid of hashes (#) and dots (.) is a double-subscripted array representation of a maze:
In the preceding double-subscripted array, the hashes ( #), represent the walls of the maze and the dots represent squares in the pos-
sible paths through the maze. Moves can only be made to a location in the array that contains a dot.
There is a simple algorithm for walking through a maze that guarantees finding the exit (assuming that there is an exit). If
there is not an exit, you will arrive at the starting location again. Place your right hand on the wall to your right and begin walking
forward. Never remove your hand from the wall. If the maze turns to the right, you follow the wall to the right. As long as you do
not remove your hand from the wall, eventually you will arrive at the exit of the maze. There may be a shorter path than the one
you have taken, but you are guaranteed to get out of the maze if you follow the algorithm.
Write recursive function mazeTraverse to walk through the maze. The function should receive as arguments a 12-by-12
character array representing the maze and the starting location of the maze. As mazeTraverse attempts to locate the exit from
the maze, it should place the character X in each square in the path. The function should display the maze after each move so the
user can watch as the maze is solved.
# # # # # # # # # # # #
# . . . # . . . . . . #
. . # . # . # # # # . #
# # # . # . . . . # . #
# . . . . # # # . # . .
# # # # . # . # . # . #
# . . # . # . # . # . #
# # . # . # . # . # . #
# . . . . . . . . # . #
# # # # # # . # # # . #
# . . . . . . # . . . #
# # # # # # # # # # # #
1// Exercise 5.25 Solution
2// This solution assumes that there is only one
3// entrance and one exit for a given maze, and
4// these are the only two zeroes on the borders.
5#include <iostream>
6
7using std::cout;
8using std::cin;
9
10 #include <cstdlib>
11
12 enum Direction { DOWN, RIGHT, UP, LEFT };
13 const int X_START = 2, Y_START = 0; // starting coordinate for maze
14
15 void mazeTraversal( char [][ 12 ], int, int, int );
16 void printMaze( const char[][ 12 ] );
17 bool validMove( const char [][ 12 ], int, int );
18 bool coordsAreEdge( int, int );
19
20 int main()
21 {
22 char maze[ 12 ][ 12 ] =
23 { {'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'},
24 {'#', '.', '.', '.', '#', '.', '.', '.', '.', '.', '.', '#'},
25 {'.', '.', '#', '.', '#', '.', '#', '#', '#', '#', '.', '#'},
26 {'#', '#', '#', '.', '#', '.', '.', '.', '.', '#', '.', '#'},
27 {'#', '.', '.', '.', '.', '#', '#', '#', '.', '#', '.', '.'},
28 {'#', '#', '#', '#', '.', '#', '.', '#', '.', '#', '.', '#'},
29 {'#', '.', '.', '#', '.', '#', '.', '#', '.', '#', '.', '#'},
30 {'#', '#', '.', '#', '.', '#', '.', '#', '.', '#', '.', '#'},
198 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
31 {'#', '.', '.', '.', '.', '.', '.', '.', '.', '#', '.', '#'},
32 {'#', '#', '#', '#', '#', '#', '.', '#', '#', '#', '.', '#'},
33 {'#', '.', '.', '.', '.', '.', '.', '#', '.', '.', '.', '#'},
34 {'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'} };
35
36 mazeTraversal( maze, X_START, Y_START, RIGHT );
37
38 return 0;
39 }
40
41 // Assume that there is exactly 1 entrance and exactly 1 exit to the maze.
42 void mazeTraversal( char maze[][ 12 ], int xCoord, int yCoord, int direction )
43 {
44 static bool flag = false;
45
46 maze[ xCoord ][ yCoord ] = 'x';
47 printMaze( maze );
48
49 if ( coordsAreEdge(xCoord, yCoord) && xCoord != X_START &&
50 yCoord != Y_START ) {
51 cout << "\nMaze successfully exited!\n\n";
52 return; // maze is complete
53 }
54 else if ( xCoord == X_START && yCoord == X_START && flag ) {
55 cout << "\nArrived back at the starting location.\n\n";
56 return;
57 }
58 else {
59 flag = true;
60
61 for ( int move = direction, count = 0; count < 4; ++count,
62 ++move, move %= 4 )
63 switch( move ) {
64 case DOWN:
65 if ( validMove( maze, xCoord + 1, yCoord ) ) { // move down
66 mazeTraversal( maze, xCoord + 1, yCoord, LEFT );
67 return;
68 }
69 break;
70 case RIGHT:
71 if ( validMove( maze, xCoord, yCoord + 1 ) ) { // move right
72 mazeTraversal( maze, xCoord, yCoord + 1, DOWN );
73 return;
74 }
75 break;
76 case UP:
77 if ( validMove( maze, xCoord - 1, yCoord ) ) { // move up
78 mazeTraversal( maze, xCoord - 1, yCoord, RIGHT );
79 return;
80 }
81 break;
82 case LEFT:
83 if ( validMove( maze, xCoord, yCoord - 1 ) ) { // move left
84 mazeTraversal( maze, xCoord, yCoord - 1, UP );
85 return;
86 }
87 break;
88 }
89 }
90 }
91
92 bool validMove( const char maze[][ 12 ], int r, int c )
Chapter 5 Pointers and Strings Solutions 199
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
93 {
94 return ( r >= 0 && r <= 11 && c >= 0 && c <= 11 && maze[ r ][ c ] != '#' );
95 }
96
97 bool coordsAreEdge( int x, int y )
98 {
99 if ( ( x == 0 || x == 11 ) && ( y >= 0 && y <= 11 ) )
100 return true;
101 else if ( ( y == 0 || y == 11 ) && ( x >= 0 && x <= 11 ) )
102 return true;
103 else
104 return false;
105 }
106
107 void printMaze( const char maze[][ 12 ] )
108 {
109 for ( int x = 0; x < 12; ++x ) {
110
111 for ( int y = 0; y < 12; ++y )
112 cout << maze[ x ][ y ] << ' ';
113
114 cout << '\n';
115 }
116
117 cout << "\nHit return to see next move\n";
118 cin.get();
119 }
200 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.26 (Generating Mazes Randomly) Write a function mazeGenerator that takes as an argument a double-subscripted 12-by-
12 character array and randomly produces a maze. The function should also provide the starting and ending locations of the maze.
Try your function mazeTraverse from Exercise 5.25 using several randomly generated mazes.
...
# # # # # # # # # # # #
# x x x # x x x x x x #
x x # x # x # # # # x #
# # # x # x x x x # x #
# x x x x # # # x # x .
# # # # x # . # x # x #
# x x # x # . # x # x #
# # x # x # . # x # x #
# x x x x x x x x # x #
# # # # # # x # # # x #
# x x x x x x # x x x #
# # # # # # # # # # # #
Hit return to see next move
# # # # # # # # # # # #
# x x x # x x x x x x #
x x # x # x # # # # x #
# # # x # x x x x # x #
# x x x x # # # x # x x
# # # # x # . # x # x #
# x x # x # . # x # x #
# # x # x # . # x # x #
# x x x x x x x x # x #
# # # # # # x # # # x #
# x x x x x x # x x x #
# # # # # # # # # # # #
Hit return to see next move
Maze successfully exited!
1// Exercise 5.26 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6
7#include <cstdlib>
8#include <ctime>
9
10 enum Direction { DOWN, RIGHT, UP, LEFT };
11 const int MAX_DOTS = 100; // maximum possible dots for maze
12
13 void mazeTraversal( char [][ 12 ], const int, const int, int, int, int );
14 void mazeGenerator( char [][ 12 ], int *, int * );
15 void printMaze( const char[][ 12 ] );
16 bool validMove( const char [][ 12 ], int, int );
17 bool coordsAreEdge( int, int );
18
19 int main()
20 {
21 char maze[ 12 ][ 12 ];
Chapter 5 Pointers and Strings Solutions 201
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
22 int xStart, yStart, x, y;
23
24 srand( time( 0 ) );
25
26 for ( int loop = 0; loop < 12; ++loop )
27 for ( int loop2 = 0; loop2 < 12; ++loop2 )
28 maze[ loop ][ loop2 ] = '#';
29
30 mazeGenerator( maze, &xStart, &yStart );
31
32 x = xStart; // starting row
33 y = yStart; // starting col
34
35 mazeTraversal( maze, xStart, yStart, x, y, RIGHT );
36
37 return 0;
38 }
39
40 // Assume that there is exactly 1 entrance and exactly 1 exit to the maze.
41 void mazeTraversal( char maze[][ 12 ], const int xCoord, const int yCoord,
42 int row, int col, int direction )
43 {
44 static bool flag = false; // starting position flag
45
46 maze[ row ][ col ] = 'x'; // insert X at current location
47 printMaze( maze );
48
49 if ( coordsAreEdge( row, col ) && row != xCoord && col != yCoord ) {
50 cout << "Maze successfully exited!\n\n";
51 return; // maze is complete
52 }
53 else if ( row == xCoord && col == yCoord && flag ) {
54 cout << "Arrived back at the starting location.\n\n";
55 return;
56 }
57 else {
58 flag = true;
59
60 for ( int move = direction, count = 0; count < 4;
61 ++count, ++move, move %= 4 )
62
63 switch( move ) {
64 case DOWN:
65 if ( validMove( maze, row + 1, col ) ) { // move down
66 mazeTraversal( maze, xCoord, yCoord, row + 1, col, LEFT );
67 return;
68 }
69 break;
70 case RIGHT:
71 if ( validMove( maze, row, col + 1 ) ) { // move right
72 mazeTraversal( maze, xCoord, yCoord, row, col + 1, DOWN );
73 return;
74 }
75 break;
76 case UP:
77 if ( validMove( maze, row - 1, col ) ) { // move up
78 mazeTraversal( maze, xCoord, yCoord, row - 1, col, RIGHT );
79 return;
80 }
81 break;
82 case LEFT:
83 if ( validMove( maze, row, col - 1 ) ) { // move left
202 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
84 mazeTraversal( maze, xCoord, yCoord, row, col - 1, UP );
85 return;
86 }
87 break;
88 }
89 }
90 }
91
92 bool validMove( const char maze[][ 12 ], int r, int c )
93 {
94 return ( r >= 0 && r <= 11 && c >= 0 && c <= 11 && maze[ r ][ c ] != '#' );
95 }
96
97 bool coordsAreEdge( int x, int y )
98 {
99 if ( ( x == 0 || x == 11 ) && ( y >= 0 && y <= 11 ) )
100 return true;
101 else if ( ( y == 0 || y == 11 ) && ( x >= 0 && x <= 11 ) )
102 return true;
103 else
104 return false;
105 }
106
107 void printMaze( const char maze[][ 12 ] )
108 {
109 for ( int x = 0; x < 12; ++x ) {
110
111 for ( int y = 0; y < 12; ++y )
112 cout << maze[ x ][ y ] << ' ';
113
114 cout << '\n';
115 }
116
117 cout << "Hit return to see next move";
118 cin.get();
119 }
120
121 void mazeGenerator(char maze[][ 12 ], int *xPtr, int *yPtr )
122 {
123 int a, x, y, entry, exit;
124
125 do {
126 entry = rand() % 4;
127 exit = rand() % 4;
128 } while ( entry == exit );
129
130 // Determine entry position
131
132 if ( entry == 0 ) {
133 *xPtr = 1 + rand() % 10; // avoid corners
134 *yPtr = 0;
135 maze[ *xPtr ][ 0 ] = '.';
136 }
137 else if ( entry == 1 ) {
138 *xPtr = 0;
139 *yPtr = 1 + rand() % 10;
140 maze[ 0 ][ *yPtr ] = '.';
141 }
142 else if ( entry == 2 ) {
143 *xPtr = 1 + rand() % 10;
144 *yPtr = 11;
145 maze[ *xPtr ][ 11 ] = '.';
Chapter 5 Pointers and Strings Solutions 203
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
146 }
147 else {
148 *xPtr = 11;
149 *yPtr = 1 + rand() % 10;
150 maze[ 11 ][ *yPtr ] = '.';
151 }
152
153 // Determine exit location
154
155 if ( exit == 0 ) {
156 a = 1 + rand() % 10;
157 maze[ a ][ 0 ] = '.';
158 }
159 else if ( exit == 1 ) {
160 a = 1 + rand() % 10;
161 maze[ 0 ][ a ] = '.';
162 }
163 else if ( exit == 2 ) {
164 a = 1 + rand() % 10;
165 maze[ a ][ 11 ] = '.';
166 }
167 else {
168 a = 1 + rand() % 10;
169 maze[ 11 ][ a ] = '.';
170 }
171
172 for ( int loop = 1; loop < MAX_DOTS; ++loop ) { // add dots randomly
173 x = 1 + rand() % 10;
174 y = 1 + rand() % 10;
175 maze[ x ][ y ] = '.';
176 }
177 }
204 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.27 (Mazes of Any Size) Generalize functions mazeTraverse and mazeGenerator of Exercises 5.25 and 5.26 to process
mazes of any width and height.
...
# # # # # # # # # # # #
# # . # # # x # # # # #
# # . . . # x x x # x #
# . # # # x x x x x x #
# . . # # # # x . x x #
# # . # x x x x # x # .
# # . # x x x # # x x #
# # # x x # x . . . x #
# # x x x # x x x x x #
# # # # # x # x x # x #
# . # x x x x x # # # #
# # # # # # # x # # # #
Hit return to see next move
# # # # # # # # # # # #
# # . # # # x # # # # #
# # . . . # x x x # x #
# . # # # x x x x x x #
# . . # # # # x . x x #
# # . # x x x x # x # .
# # . # x x x # # x x #
# # # x x # x . . . x #
# # x x x # x x x x x #
# # # # # x # x x # x #
# . # x x x x x # # # #
# # # # # # # x # # # #
Hit return to see next move
Arrived back at the starting location.
1// Exercise 5.27 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstdlib>
9#include <ctime>
10
11 enum Direction { DOWN, RIGHT, UP, LEFT };
12 const int ROWS = 15, COLS = 30;
13
14 void mazeTraversal( char [][ COLS ], const int, const int, int, int, int );
15 void mazeGenerator( char [][ COLS ], int *, int * );
16 void printMaze( const char[][ COLS ] );
17 bool validMove( const char [][ COLS ], int, int );
18 bool coordsAreEdge( int, int );
19
20 int main()
21 {
22 char maze[ ROWS ][ COLS ];
23 int xStart, yStart, x, y;
24
25 srand( time( 0 ) );
26
27 for ( int loop = 0; loop < ROWS; ++loop )
28 for ( int loop2 = 0; loop2 < COLS; ++loop2 )
Chapter 5 Pointers and Strings Solutions 205
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
29 maze[ loop ][ loop2 ] = '#';
30
31 mazeGenerator( maze, &xStart, &yStart );
32
33 x = xStart; // starting row
34 y = yStart; // starting col
35
36 mazeTraversal( maze, xStart, yStart, x, y, RIGHT );
37
38 return 0;
39 }
40
41 // Assume that there is exactly 1 entrance and exactly 1 exit to the maze.
42 void mazeTraversal( char maze[][ COLS ], const int xCoord, const int yCoord,
43 int row, int col, int direction )
44 {
45 static bool flag = false; // starting position flag
46
47 maze[ row ][ col ] = 'x'; // insert x at current location
48 printMaze( maze );
49
50 if ( coordsAreEdge( row, col ) && row != xCoord && col != yCoord ) {
51 cout << endl << "Maze successfully exited!\n\n";
52 return; // maze is complete
53 }
54 else if ( row == xCoord && col == yCoord && flag ) {
55 cout << "\nArrived back at the starting location.\n\n";
56 return;
57 }
58 else {
59 flag = true;
60
61 for ( int move = direction, count = 0; count < 4;
62 ++count, ++move, move %= 4 )
63 switch( move ) {
64 case DOWN:
65 if ( validMove( maze, row + 1, col ) ) { // move down
66 mazeTraversal( maze, xCoord, yCoord, row + 1, col, LEFT );
67 return;
68 }
69 break;
70 case RIGHT:
71 if ( validMove( maze, row, col + 1 ) ) { // move right
72 mazeTraversal( maze, xCoord, yCoord, row, col + 1, DOWN );
73 return;
74 }
75 break;
76 case UP:
77 if ( validMove( maze, row - 1, col ) ) { // move up
78 mazeTraversal( maze, xCoord, yCoord, row - 1, col, RIGHT );
79 return;
80 }
81 break;
82 case LEFT:
83 if ( validMove( maze, row, col - 1 ) ) { // move left
84 mazeTraversal( maze, xCoord, yCoord, row, col - 1, UP );
85 return;
86 }
87 break;
88 }
89 }
90 }
206 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
91
92 bool validMove( const char maze[][ COLS ], int r, int c )
93 {
94 return ( r >= 0 && r <= ROWS - 1 && c >= 0 && c <= COLS - 1 &&
95 maze[ r ][ c ] != '#' ); // a valid move
96 }
97
98 bool coordsAreEdge( int x, int y )
99 {
100 if ( ( x == 0 || x == ROWS - 1 ) && ( y >= 0 && y <= COLS - 1 ) )
101 return true;
102 else if ( ( y == 0 || y == COLS - 1 ) && ( x >= 0 && x <= ROWS - 1 ) )
103 return true;
104 else
105 return false;
106 }
107
108 void printMaze( const char maze[][ COLS ] )
109 {
110 for ( int x = 0; x < ROWS; ++x ) {
111
112 for ( int y = 0; y < COLS; ++y )
113 cout << maze[ x ][ y ] << ' ';
114
115 cout << '\n';
116 }
117
118 cout << "\nHit return to see next move";
119 cin.get();
120 }
121
122 void mazeGenerator( char maze[][ COLS ], int *xPtr, int *yPtr )
123 {
124 int a, x, y, entry, exit;
125
126 do {
127 entry = rand() % 4;
128 exit = rand() % 4;
129 } while ( entry == exit );
130
131 // Determine entry position
132 if ( entry == 0 ) {
133 *xPtr = 1 + rand() % ( ROWS - 2 ); // avoid corners
134 *yPtr = 0;
135 maze[ *xPtr ][ *yPtr ] = '.';
136 }
137 else if ( entry == 1 ) {
138 *xPtr = 0;
139 *yPtr = 1 + rand() % ( COLS - 2 );
140 maze[ *xPtr ][ *yPtr ] = '.';
141 }
142 else if ( entry == 2 ) {
143 *xPtr = 1 + rand() % ( ROWS - 2 );
144 *yPtr = COLS - 1;
145 maze[ *xPtr ][ *yPtr ] = '.';
146 }
147 else {
148 *xPtr = ROWS - 1;
149 *yPtr = 1 + rand() % ( COLS - 2 );
150 maze[ *xPtr ][ *yPtr ] = '.';
151 }
152
Chapter 5 Pointers and Strings Solutions 207
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
153 // Determine exit location
154 if ( exit == 0 ) {
155 a = 1 + rand() % ( ROWS - 2 );
156 maze[ a ][ 0 ] = '.';
157 }
158 else if ( exit == 1 ) {
159 a = 1 + rand() % ( COLS - 2 );
160 maze[ 0 ][ a ] = '.';
161 }
162 else if ( exit == 2 ) {
163 a = 1 + rand() % ( ROWS - 2 );
164 maze[ a ][ COLS - 1 ] = '.';
165 }
166 else {
167 a = 1 + rand() % ( COLS - 2 );
168 maze[ ROWS - 1 ][ a ] = '.';
169 }
170
171 for ( int loop = 1; loop < ( ROWS - 2 ) * ( COLS - 2 ); ++loop ) {
172 x = 1 + rand() % ( ROWS - 2 ); // add dots to maze
173 y = 1 + rand() % ( COLS - 2 );
174 maze[ x ][ y ] = '.';
175 }
176 }
208 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.28 (Arrays of Pointers to Functions) Rewrite the program of Fig. 4.23 to use a menu-driven interface. The program should
offer the user five options as follows (these should be displayed on the screen):
One restriction on using arrays of pointers to functions is that all the pointers must have the same type. The pointers must be to
functions of the same return type that receive arguments of the same type. For this reason, the functions in Fig. 4.23 must be mod-
ified so they each return the same type and take the same parameters. Modify functions minimum and maximum to print the min-
imum or maximum value and return nothing. For option 3, modify function average of Fig. 4.23 to output the average for each
student (not a specific student). Function average should return nothing and take the same parameters as printArray, min-
imum and maximum. Store the pointers to the four functions in array processGrades, and use the choice made by the user as
...
Hit return to see next move
# # # # # # # # # # # # # # . # # # # # # # # # # # # # # #
# . . # . . . . . . # . . # x x x # x x x x x x # . # . # #
# . . . . # # . # # # # # . . . x x x # # x x x x # . . # #
# . # . # . # # . # # . # # . . # . # . # x # # # . . # # #
# . # # . . . # # . . # # . . . . # . . x x x x x # . # # #
# . # # # . . . # . # . # # . . . . # . x # # x x x # . # #
# # # . # . . . . . # . # # . . # # # . x # . # x # . . # #
# . x x x x x x . # # . . . . . # . # . x x # x # . # . # #
# x x # # x # x . . . . # # . . # # . # # x x x x # . . . #
# x # # x x # x x . . . . . . . . # . . # . # # x # . . . #
x x # x x x x # x x x . . x x x x x x x . x x x x x # # . #
# # x x x # # x # # x . # x # x x # # x x x # x # x # # # #
# # x x # . # x # x x x x x x # x # # # # # x x x # # . . #
# . # x # . # x x x x # x # # # x x x # # x x # x # . . . #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Hit return to see next move
# # # # # # # # # # # # # # x # # # # # # # # # # # # # # #
# . . # . . . . . . # . . # x x x # x x x x x x # . # . # #
# . . . . # # . # # # # # . . . x x x # # x x x x # . . # #
# . # . # . # # . # # . # # . . # . # . # x # # # . . # # #
# . # # . . . # # . . # # . . . . # . . x x x x x # . # # #
# . # # # . . . # . # . # # . . . . # . x # # x x x # . # #
# # # . # . . . . . # . # # . . # # # . x # . # x # . . # #
# . x x x x x x . # # . . . . . # . # . x x # x # . # . # #
# x x # # x # x . . . . # # . . # # . # # x x x x # . . . #
# x # # x x # x x . . . . . . . . # . . # . # # x # . . . #
x x # x x x x # x x x . . x x x x x x x . x x x x x # # . #
# # x x x # # x # # x . # x # x x # # x x x # x # x # # # #
# # x x # . # x # x x x x x x # x # # # # # x x x # # . . #
# . # x # . # x x x x # x # # # x x x # # x x # x # . . . #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Hit return to see next move
Maze successfully exited!
Enter a choice:
0 Print the array of grades
1 Find the minimum grade
2 Find the maximum grade
3 Print the average on all tests for each student
4 End program
Chapter 5 Pointers and Strings Solutions 209
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
the subscript into the array for calling each function.
1// Exercise 5.28 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6using std::ios;
7
8#include <iomanip>
9
10 using std::setw;
11 using std::setprecision;
12 using std::setiosflags;
13 using std::resetiosflags;
14
15 const int STUDENTS = 3, EXAMS = 4;
16
17 void minimum( const int [][ EXAMS ], int, int );
18 void maximum( const int [][ EXAMS ], int, int );
19 void average( const int [][ EXAMS ], int, int );
20 void printArray( const int [][ EXAMS ], int, int );
21 void printMenu( void );
22 int test( bool ( * )( int, int ), int, int, int, const int [][ EXAMS ] );
23
24 int main()
25 {
26 void ( *processGrades[ 4 ] )( const int [][ EXAMS ], int, int )
27 = { printArray, minimum, maximum, average };
28
29 int choice = 0,
30 studentGrades[ STUDENTS ][ EXAMS ] = { { 77, 68, 86, 73 },
31 { 96, 87, 89, 78 },
32 { 70, 90, 86, 81 } };
33
34 while ( choice != 4 ) {
35
36 do {
37 printMenu();
38 cin >> choice;
39 } while ( choice < 0 || choice > 4 );
40
41 if ( choice != 4 )
42 ( *processGrades[ choice ] )( studentGrades, STUDENTS, EXAMS );
43 else
44 cout << "Program Ended.\n";
45 }
46
47 return 0;
48 }
49
50 void minimum( const int grades[][ EXAMS ], int pupils, int tests )
51 {
52 bool smaller( int, int );
53
54 cout << "\n\tThe lowest grade is "
55 << test( smaller, pupils, tests, 100, grades ) << '\n';
56 }
57
58 void maximum( const int grades[][ EXAMS ], int pupils, int tests )
59 {
60 bool greater( int, int );
210 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
61
62 cout << "\n\tThe highest grade is "
63 << test( greater, pupils, tests, 0, grades ) << '\n';
64 }
65
66 int test( bool ( *ptr )( int, int ), int p, int t, int value,
67 const int g[][ EXAMS ] )
68 {
69 for ( int i = 0; i < p; ++i )
70 for ( int j = 0; j < t; ++j )
71 if ( ( *ptr )( g[ i ][ j ], value ) )
72 value = g[ i ][ j ];
73
74 return value; // return max/min value
75 }
76
77 void average( const int grades[][ EXAMS ], int pupils, int tests )
78 {
79 int total;
80
81 cout << setiosflags( ios::fixed | ios::showpoint ) << '\n';
82
83 for ( int i = 0; i < pupils; ++i ) {
84 total = 0; // reset total
85
86 for ( int j = 0; j < tests; ++j )
87 total += grades[ i ][ j ];
88
89 cout << "\tThe average for student " << pupils + 1 << " is "
90 << setprecision( 1 )
91 << static_cast< double > ( total ) / tests << '\n';
92 }
93
94 cout << resetiosflags( ios::fixed | ios::showpoint );
95 }
96
97 void printArray( const int grades[][ EXAMS ], int pupils, int tests )
98 {
99 cout << "\n [0] [1] [2] [3]";
100
101 for ( int i = 0; i < pupils; ++i ) {
102 cout << "\nstudentGrades[" << i << ']';
103
104 for ( int j = 0; j < tests; ++j )
105 cout << setw( 5 ) << grades[ i ][ j ];
106 }
107
108 cout << '\n';
109 }
110
111 void printMenu( void )
112 {
113 cout << "\nEnter a choice:\n"
114 << " 0 Print the array of grades\n"
115 << " 1 Find the minimum grade\n"
116 << " 2 Find the maximum grade\n"
117 << " 3 Print the average on all tests for each student\n"
118 << " 4 End program\n? ";
119 }
120
121 bool greater( int a, int b )
122 {
Chapter 5 Pointers and Strings Solutions 211
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
123 return a > b;
124 }
125
126 bool smaller( int a, int b )
127 {
128 return a < b;
129 }
212 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.29 (Modifications to the Simpletron Simulator) In Exercise 5.19, you wrote a software simulation of a computer that executes
programs written in Simpletron Machine Language (SML). In this exercise, we propose several modifications and enhancements
to the Simpletron Simulator. In Exercises 15.26 and 15.27, we propose building a compiler that converts programs written in a high-
level programming language (a variation of BASIC) to SML. Some of the following modifications and enhancements may be re-
quired to execute the programs produced by the compiler. (Note: Some modifications may conflict with others and therefore must
be done separately.)
Enter a choice:
0 Print the array of grades
1 Find the minimum grade
2 Find the maximum grade
3 Print the average on all tests for each student
4 End program
? 0
[0] [1] [2] [3]
studentGrades[0] 77 68 86 73
studentGrades[1] 96 87 89 78
studentGrades[2] 70 90 86 81
Enter a choice:
0 Print the array of grades
1 Find the minimum grade
2 Find the maximum grade
3 Print the average on all tests for each student
4 End program
? 1
The lowest grade is 68
Enter a choice:
0 Print the array of grades
1 Find the minimum grade
2 Find the maximum grade
3 Print the average on all tests for each student
4 End program
? 2
The highest grade is 96
Enter a choice:
0 Print the array of grades
1 Find the minimum grade
2 Find the maximum grade
3 Print the average on all tests for each student
4 End program
? 3
The average for student 4 is 76.0
The average for student 4 is 87.5
The average for student 4 is 81.8
Enter a choice:
0 Print the array of grades
1 Find the minimum grade
2 Find the maximum grade
3 Print the average on all tests for each student
4 End program
? 4
Program Ended.
Chapter 5 Pointers and Strings Solutions 213
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
a) Extend the Simpletron Simulator’s memory to contain 1000 memory locations to enable the Simpletron to handle larger
programs.
b) Allow the simulator to perform modulus calculations. This requires an additional Simpletron Machine Language in-
struction.
c) Allow the simulator to perform exponentiation calculations. This requires an additional Simpletron Machine Language
instruction.
d) Modify the simulator to use hexadecimal values rather than integer values to represent Simpletron Machine Language
instructions.
e) Modify the simulator to allow output of a newline. This requires an additional Simpletron Machine Language instruc-
tion.
f) Modify the simulator to process floating-point values in addition to integer values.
g) Modify the simulator to handle string input. [Hint: Each Simpletron word can be divided into two groups, each holding
a two-digit integer. Each two-digit integer represents the ASCII decimal equivalent of a character. Add a machine-lan-
guage instruction that will input a string and store the string beginning at a specific Simpletron memory location. The
first half of the word at that location will be a count of the number of characters in the string (i.e., the length of the
string). Each succeeding half-word contains one ASCII character expressed as two decimal digits. The machine-lan-
guage instruction converts each character into its ASCII equivalent and assigns it to a half-word.]
h) Modify the simulator to handle output of strings stored in the format of part (g). [Hint: Add a machine language instruc-
tion that will print a string beginning at a certain Simpletron memory location. The first half of the word at that location
is a count of the number of characters in the string (i.e., the length of the string). Each succeeding half-word contains
one ASCII character expressed as two decimal digits. The machine-language instruction checks the length and prints
the string by translating each two-digit number into its equivalent character.]
i) Modify the simulator to include instruction SML_DEBUG that prints a memory dump after each instruction is executed.
Give SML_DEBUG an operation code of 44. The word +4401 turns on debug mode and +4400 turns off debug mode.
5.30 What does this program do?
ANS: Function mystery3 compares two strings for equality.
1// ex05_30.cpp
2#include <iostream>
3
4using std::cout;
5using std::cin;
6using std::endl;
7
8bool mystery3( const char *, const char * );
9
10 int main()
11 {
12 char string1[ 80 ], string2[ 80 ];
13
14 cout << "Enter two strings: ";
15 cin >> string1 >> string2;
16 cout << "The result is "
17 << mystery3( string1, string2 ) << endl;
18
19 return 0;
20 }
21
22 bool mystery3( const char *s1, const char *s2 )
23 {
24 for ( ; *s1 != '\0' && *s2 != '\0'; s1++, s2++ )
25
26 if ( *s1 != *s2 )
27 return false;
28
29 return true;
30 }
214 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
STRING MANIPULATION EXERCISES
5.31 Write a program that uses function strcmp to compare two strings input by the user. The program should state whether
the first string is less than, equal to or greater than the second string.
5.32 Write a program that uses function strncmp to compare two strings input by the user. The program should input the num-
ber of characters to be compared. The program should state whether the first string is less than, equal to or greater than the second
string.
1// Exercise 5.31 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstring>
9
10 const int SIZE = 20;
11
12 int main()
13 {
14 char string1[ SIZE ], string2[ SIZE ];
15 int result;
16
17 cout << "Enter two strings: ";
18 cin >> string1 >> string2;
19
20 result = strcmp( string1, string2 );
21
22 if ( result > 0 )
23 cout << '\"' << string1 << '\"' << " is greater than \""
24 << string2 << '\"' << endl;
25 else if ( result == 0 )
26 cout << '\"' << string1 << '\"' << " is equal to \"" << string2
27 << '\"' << endl;
28 else
29 cout << '\"' << string1 << '\"' << " is less than \"" << string2
30 << '\"' << endl;
31
32 return 0;
33 }
Enter two strings: green leaf
"green" is less than "leaf"
1// Exercise 5.32 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstring>
9
10 const int SIZE = 20;
11
12 int main()
13 {
Chapter 5 Pointers and Strings Solutions 215
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.33 Write a program that uses random-number generation to create sentences. The program should use four arrays of pointers
to char called article, noun, verb and preposition. The program should create a sentence by selecting a word at random
from each array in the following order: article, noun, verb, preposition, article and noun. As each word is picked,
it should be concatenated to the previous words in an array that is large enough to hold the entire sentence. The words should be
separated by spaces. When the final sentence is output, it should start with a capital letter and end with a period. The program should
generate 20 such sentences.
The arrays should be filled as follows: the article array should contain the articles "the", "a", "one", "some" and
"any"; the noun array should contain the nouns "boy", "girl", "dog", "town" and "car"; the verb array should con-
tain the verbs "drove", "jumped", "ran", "walked" and "skipped"; the preposition array should contain the prep-
ositions "to", "from", "over", "under" and "on".
After the preceding program is written and working, modify the program to produce a short story consisting of several of
these sentences. (How about the possibility of a random term paper writer!)
14 char string1[ SIZE ], string2[ SIZE ];
15 int result, compareCount;
16
17 cout << "Enter two strings: ";
18 cin >> string1 >> string2;
19 cout << "How many characters should be compared: ";
20 cin >> compareCount;
21
22 result = strncmp( string1, string2, compareCount );
23
24 if ( result > 0 )
25 cout << '\"' << string1 << "\" is greater than \"" << string2
26 << "\" up to " << compareCount << " characters\n";
27 else if ( result == 0 )
28 cout << '\"' << string1 << "\" is equal to \"" << string2
29 << "\" up to " << compareCount << " characters\n";
30 else
31 cout << '\"' << string1 << "\" is less than \"" << string2
32 << "\" up to " << compareCount << " characters\n";
33
34 cout << endl;
35
36 return 0;
37 }
Enter two strings: sand sandpaper
How many characters should be compared: 4
"sand" is equal to "sandpaper" up to 4 characters
1// Exercise 5.33 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <cstdlib>
8#include <ctime>
9
10 #include <cstring>
11 #include <cctype>
12
13 const int SIZE = 100;
14
15 int main()
16 {
216 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.34 (Limericks) A limerick is a humorous five-line verse in which the first and second lines rhyme with the fifth, and the third
line rhymes with the fourth. Using techniques similar to those developed in Exercise 5.33, write a C++ program that produces ran-
dom limericks. Polishing this program to produce good limericks is a challenging problem, but the result will be worth the effort!
5.35 Write a program that encodes English language phrases into pig Latin. Pig Latin is a form of coded language often used for
amusement. Many variations exist in the methods used to form pig Latin phrases. For simplicity, use the following algorithm:
To form a pig-Latin phrase from an English-language phrase, tokenize the phrase into words with function strtok. To trans-
late each English word into a pig-Latin word, place the first letter of the English word at the end of the English word, and add the
letters “ay.” Thus the word “jump” becomes “umpjay,” the word “the” becomes “hetay” and the word “computer
becomes “omputercay.” Blanks between words remain as blanks. Assume that the: the English phrase consists of words sepa-
rated by blanks, there are no punctuation marks and all words have two or more letters. Function printLatinWord should dis-
17 const char *article[] = { "the", "a", "one", "some", "any" },
18 *noun[] = { "boy", "girl", "dog", "town", "car" },
19 *verb[] = { "drove", "jumped", "ran", "walked", "skipped" },
20 *preposition[] = { "to", "from", "over", "under", "on" };
21 char sentence[ SIZE ] = "";
22
23 for ( int i = 1; i <= 20; ++i ) {
24 strcat( sentence, article[ rand() % 5 ] );
25 strcat( sentence, " " );
26 strcat( sentence, noun[ rand() % 5 ] );
27 strcat( sentence, " " );
28 strcat( sentence, verb[ rand() % 5 ] );
29 strcat( sentence, " " );
30 strcat( sentence, preposition[ rand() % 5 ] );
31 strcat( sentence, " " );
32 strcat( sentence, article[ rand() % 5 ] );
33 strcat( sentence, " " );
34 strcat( sentence, noun[ rand() % 5 ] );
35 cout << static_cast< char > ( toupper( sentence[ 0 ] ) )
36 << &sentence[ 1 ] << ".\n";
37 sentence[ 0 ] = '\0';
38 }
39
40 cout << endl;
41
42 return 0;
43 }
A dog skipped to any car.
Some town ran on the boy.
A dog jumped from the dog.
One girl jumped on one town.
One dog jumped from some boy.
One girl jumped under any dog.
One car drove on some girl.
One town walked on a girl.
Some town ran on one dog.
One car walked from any town.
A boy drove over some girl.
The dog skipped under a boy.
The car drove to a girl.
Some town skipped under any car.
A boy jumped from a town.
Any car jumped under one town.
Some dog skipped from some boy.
Any town skipped to one girl.
Some girl jumped to any dog.
The car ran under one dog.
Chapter 5 Pointers and Strings Solutions 217
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
play each word. (Hint: Each time a token is found in a call to strtok, pass the token pointer to function printLatinWord,
and print the pig Latin word.)
1// Exercise 5.35 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstring>
9
10 const int SIZE = 80;
11
12 void printLatinWord( char const * const );
13
14 int main()
15 {
16 char sentence[ SIZE ], *tokenPtr;
17
18 cout << "Enter a sentence:\n";
19 cin.getline( sentence, SIZE );
20
21 cout << "\nThe sentence in Pig Latin is:\n";
22 tokenPtr = strtok( sentence, " .,;" );
23
24 while ( tokenPtr ) {
25 printLatinWord( tokenPtr );
26 tokenPtr = strtok( 0, " .,;" );
27
28 if ( tokenPtr )
29 cout << ' ';
30 }
31
32 cout << '.' << endl;
33
34 return 0;
35 }
36
37 void printLatinWord( char const * const wordPtr )
38 {
39 int len = strlen( wordPtr );
40 for (int i = 1; i < len; ++i )
41 cout << *( wordPtr + i );
42
43 cout << *wordPtr << "ay";
44 }
Enter a sentence:
mirror mirror on the wall
The sentence in Pig Latin is:
irrormay irrormay noay hetay allway.
218 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.36 Write a program that inputs a telephone number as a string in the form (555) 555-5555. The program should use func-
tion strtok to extract the area code as a token, the first three digits of the phone number as a token, and the last four digits of the
phone number as a token. The seven digits of the phone number should be concatenated into one string. The program should convert
the area code string to int and convert the phone number string to long. Both the area code and the phone number should be
printed.
5.37 Write a program that inputs a line of text, tokenizes the line with function strtok and outputs the tokens in reverse order.
1// Exercise 5.36 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstring>
9#include <cstdlib>
10
11 int main()
12 {
13 const int SIZE1 = 20, SIZE2 = 10;
14 char p[ SIZE1 ],
15 phoneNumber[ SIZE2 ] = { '\0' }, *tokenPtr;
16 int areaCode;
17 long phone;
18
19 cout << "Enter a phone number in the form (555) 555-5555:\n";
20 cin.getline( p, SIZE1 );
21
22 areaCode = atoi( strtok( p, "()" ) );
23
24 tokenPtr = strtok( 0, "-" );
25 strcpy( phoneNumber, tokenPtr );
26 tokenPtr = strtok( 0, "" );
27 strcat( phoneNumber, tokenPtr );
28 phone = atol( phoneNumber );
29
30 cout << "\nThe integer area code is " << areaCode
31 << "\nThe long integer phone number is " << phone << endl;
32
33 return 0;
34 }
Enter a phone number in the form (555) 555-5555:
(555) 492-4195
The integer area code is 555
The long integer phone number is 4924195
1// Exercise 5.37 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstring>
9
10 void reverseTokens( char * const );
Chapter 5 Pointers and Strings Solutions 219
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.38 Use the string comparison functions discussed in Section 5.12.2 and the techniques for sorting arrays developed in Chapter
4 to write a program that alphabetizes a list of strings. Use the names of 10 or 15 towns in your area as data for your program.
11
12 int main()
13 {
14 const int SIZE = 80;
15 char text[ SIZE ];
16
17 cout << "Enter a line of text:\n";
18 cin.getline( text, SIZE );
19 reverseTokens( text );
20 cout << endl;
21
22 return 0;
23 }
24
25 void reverseTokens( char * const sentence )
26 {
27 char *pointers[ 50 ], *temp;
28 int count = 0;
29
30 temp = strtok( sentence, " " );
31
32 while ( temp ) {
33 pointers[ count++ ] = temp;
34 temp = strtok( 0, " " );
35 }
36
37 cout << "\nThe tokens in reverse order are:\n";
38
39 for ( int i = count - 1; i >= 0; --i )
40 cout << pointers[ i ] << ' ';
41 }
Enter a line of text:
twinkle twinkle little star
The tokens in reverse order are:
star little twinkle twinkle
1// Exercise 5.38 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstring>
9
10 const int SIZE = 50;
11 void bubbleSort( char [][ SIZE ] );
12
13 int main()
14 {
15 char array[ 10 ][ SIZE ];
16 int i;
17
18 for ( i = 0; i < 10; ++i ) {
220 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.39 Write two versions of each of the string copy and string concatenation functions in Fig. 5.29. The first version should use
array subscripting, and the second version should use pointers and pointer arithmetic.
19 cout << "Enter a string: ";
20 cin >> &array[ i ][ 0 ];
21 }
22
23 bubbleSort( array );
24 cout << "\nThe strings in sorted order are:\n";
25
26 for ( i = 0; i < 10; ++i )
27 cout << &array[ i ][ 0 ] << endl;
28
29 return 0;
30 }
31
32 void bubbleSort( char a[][ SIZE ] )
33 {
34 char temp[ SIZE ];
35
36 for ( int i = 0; i <= 8; ++i )
37 for ( int j = 0; j <= 8; ++j )
38 if ( strcmp( &a[ j ][ 0 ], &a[ j + 1 ][ 0 ] ) > 0 ) {
39 strcpy( temp, &a[ j ][ 0 ] );
40 strcpy( &a[ j ][ 0 ], &a[ j + 1 ][ 0 ] );
41 strcpy(&a[ j + 1 ][ 0 ], temp );
42 }
43 }
Enter a string: Windsor
Enter a string: Pittsford
Enter a string: Warren
Enter a string: Killington
Enter a string: Marlboro
Enter a string: Grafton
Enter a string: Middlebury
Enter a string: Barre
Enter a string: Montpelier
Enter a string: Wolcott
The strings in sorted order are:
Barre
Grafton
Killington
Marlboro
Middlebury
Montpelier
Pittsford
Warren
Windsor
Wolcott
1// Exercise 5.39 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
Chapter 5 Pointers and Strings Solutions 221
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
8char *stringCopy1( char *, const char * );
9char *stringCopy2( char *, const char * );
10 char *stringNCopy1( char *, const char *, unsigned );
11 char *stringNCopy2( char *, const char *, unsigned );
12 char *stringCat1( char *, const char * );
13 char *stringCat2( char *, const char * );
14 char *stringNCat1( char *, const char *, unsigned );
15 char *stringNCat2( char *, const char *, unsigned );
16
17 int main()
18 {
19 int n = 4;
20 char string1[ 100 ], string2[ 100 ];
21
22 cout << "Enter a string: ";
23 cin >> string2;
24
25 cout << "Copied string returned from stringCopy1 is "
26 << stringCopy1( string1, string2 )
27 << "\nCopied string returned from stringCopy2 is "
28 << stringCopy2( string1, string2 );
29 cout << "\nCopied " << n << " elements returned from stringNCopy1 is "
30 << stringNCopy1( string1, string2, n );
31 cout << "\nCopied " << n << " elements returned from stringNCopy2 is "
32 << stringNCopy2(string1, string2, n);
33 cout << "\nConcatenated string returned from stringCat1 is "
34 << stringCat1( string1, string2 );
35 cout << "\nConcatenated string returned from stringCat2 is "
36 << stringCat2( string1, string2 );
37 cout << "\nConcatenated string returned from stringNCat1 is "
38 << stringNCat1( string1, string2, n );
39 cout << "\nConcatenated string returned from stringNCat2 is "
40 << stringNCat2( string1, string2, n ) << endl;
41
42 return 0;
43 }
44
45 char *stringCopy1( char *s1, const char *s2 )
46 {
47 for ( int sub = 0; s1[ sub ] = s2[ sub ]; ++sub )
48 ; // empty body
49
50 return s1;
51 }
52
53 char *stringCopy2( char *s1, const char *s2 )
54 {
55 char *ptr = s1;
56
57 for ( ; *s1 = *s2; ++s1, ++s2 )
58 ; // empty body
59
60 return ptr;
61 }
62
63 char *stringNCopy1( char *s1, const char *s2, unsigned n )
64 {
65 unsigned c;
66
67 for ( c = 0; c < n && ( s1[ c ] = s2[ c ] ); ++c )
68 ; // empty body
69
222 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
70 s1[ c ] = '\0';
71 return s1;
72 }
73
74 char *stringNCopy2( char *s1, const char *s2, unsigned n )
75 {
76 char *ptr = s1;
77
78 for ( unsigned c = 0; c < n; ++c, ++s1, ++s2 )
79 *s1 = *s2;
80
81 *s1 = '\0';
82 return ptr;
83 }
84
85 char *stringCat1( char *s1, const char *s2 )
86 {
87 int x;
88
89 for ( x = 0; s1[ x ] != '\0'; ++x )
90 ; // empty body
91
92 for ( int y = 0; s1[ x ] = s2[ y ]; ++x, ++y )
93 ; // empty body
94
95 return s1;
96 }
97
98 char *stringCat2( char *s1, const char *s2 )
99 {
100 char *ptr = s1;
101
102 for ( ; *s1 != '\0'; ++s1 )
103 ; // empty body
104
105 for ( ; *s1 = *s2; ++s1, ++s2 )
106 ; // empty body
107
108 return ptr;
109 }
110
111 char *stringNCat1( char *s1, const char *s2, unsigned n )
112 {
113 int x;
114
115 for ( x = 0; s1[ x ] != '\0'; ++x )
116 ; // empty body
117
118 for ( unsigned y = 0; y < n && ( s1[ x ] = s2[ y ] ); ++x, ++y )
119 ; // empty body
120
121 s1[ x ] = '\0';
122 return s1;
123 }
124
125 char *stringNCat2( char *s1, const char *s2, unsigned n )
126 {
127 char *ptr = s1;
128
129 for ( ; *s1 != '\0'; ++s1 )
130 ; // empty body
131
Chapter 5 Pointers and Strings Solutions 223
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.40 Write two versions of each string comparison function in Fig. 5.29. The first version should use array subscripting, and the
second version should use pointers and pointer arithmetic.
132 for ( unsigned c = 0 ; c < n && ( *s1 = *s2 ); ++s1, ++s2 )
133 ; // empty body
134
135 *s1 = '\0';
136 return ptr;
137 }
Enter a string: coo
Copied string returned from stringCopy1 is coo
Copied string returned from stringCopy2 is coo
Copied 4 elements returned from stringNCopy1 is coo
Copied 4 elements returned from stringNCopy2 is coo
Concatenated string returned from stringCat1 is coocoo
Concatenated string returned from stringCat2 is coocoocoo
Concatenated string returned from stringNCat1 is coocoocoocoo
Concatenated string returned from stringNCat2 is coocoocoocoocoo
1// Exercise 5.40 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int stringCompare1( const char *, const char * );
9int stringCompare2( const char *, const char * );
10 int stringNCompare1( const char *, const char *, unsigned );
11 int stringNCompare2( const char *, const char *, unsigned );
12
13 int main()
14 {
15 char string1[ 100 ], string2[ 100 ];
16 unsigned n = 3; // number of characters to be compared
17
18 cout << "Enter two strings: ";
19 cin >> string1 >> string2;
20
21 cout << "The value returned from stringCompare1(\"" << string1
22 << "\", \"" << string2 << "\") is "
23 << stringCompare1(string1, string2)
24 << "\nThe value returned from stringCompare2(\"" << string1
25 << "\", \"" << string2 << "\") is "
26 << stringCompare2(string1, string2) << '\n';
27
28 cout << "\nThe value returned from stringNCompare1(\"" << string1
29 << "\", \"" << string2 << "\", " << n << ") is "
30 << stringNCompare1(string1, string2, n)
31 << "\nThe value returned from stringNCompare2(\"" << string1
32 << "\", \"" << string2 << "\", " << n << ") is "
33 << stringNCompare2( string1, string2, n ) << endl;
34
35 return 0;
36 }
37
38 int stringCompare1( const char *s1, const char *s2 )
39 {
224 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
40 int sub;
41
42 // array subscript notation
43 for ( sub = 0; s1[ sub ] == s2[ sub ]; ++sub )
44 ; // empty statement
45
46 --sub;
47
48 if ( s1[ sub ] == '\0' && s2[ sub ] == '\0')
49 return 0;
50 else if ( s1[ sub] < s2[ sub ] )
51 return -1;
52 else
53 return 1;
54 }
55
56 int stringCompare2( const char *s1, const char *s2 )
57 {
58 // pointer notation
59 for ( ; *s1 == *s2; s1++, s2++ )
60 ; // empty statement
61
62 --s1;
63 --s2;
64
65 if ( *s1 == '\0' && *s2 == '\0' )
66 return 0;
67 else if ( *s1 < *s2 )
68 return -1;
69 else
70 return 1;
71 }
72
73 int stringNCompare1( const char *s1, const char *s2, unsigned n )
74 {
75 unsigned sub;
76
77 // array subscript notation
78 for ( sub = 0; sub < n && ( s1[ sub ] == s2[ sub ] ); sub++ )
79 ; // empty body
80
81 --sub;
82
83 if ( s1[ sub ] == s2[ sub ] )
84 return 0;
85 else if ( s1[ sub ] < s2[ sub ] )
86 return -1;
87 else
88 return 1;
89 }
90
91 int stringNCompare2( const char *s1, const char *s2, unsigned n )
92 {
93 // pointer notation
94 for ( unsigned c = 0; c < n && (*s1 == *s2); c++, s1++, s2++ )
95 ; // empty statement
96
97 --s1;
98 --s2;
99
100 if ( *s1 == *s2 )
101 return 0;
Chapter 5 Pointers and Strings Solutions 225
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.41 Write two versions of function strlen in Fig. 5.29. The first version should use array subscripting, and the second version
should use pointers and pointer arithmetic.
102 else if ( *s1 < *s2 )
103 return -1;
104 else
105 return 1;
106 }
Enter two strings: tommy tomato
The value returned from stringCompare1("tommy", "tomato") is 1
The value returned from stringCompare2("tommy", "tomato") is 1
The value returned from stringNCompare1("tommy", "tomato", 3) is 0
The value returned from stringNCompare2("tommy", "tomato", 3) is 0
1// Exercise 5.41 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8unsigned long stringLength1( const char * );
9unsigned long stringLength2( const char * );
10
11 int main()
12 {
13 char string[ 100 ];
14
15 cout << "Enter a string: ";
16 cin >> string;
17
18 cout << "\nAccording to stringLength1 the string length is: "
19 << stringLength1( string )
20 << "\nAccording to stringLength2 the string length is: "
21 << stringLength2( string ) << endl;
22
23 return 0;
24 }
25
26 unsigned long stringLength1( const char *sPtr )
27 {
28 // array subscript notation
29 for ( int length = 0; sPtr[ length ] != '\0'; ++length )
30 ; // empty body
31
32 return length;
33 }
34
35 unsigned long stringLength2( const char *sPtr )
36 {
37 // pointer notation
38 for ( int length = 0; *sPtr != '\0'; ++sPtr, ++length )
39 ; // empty body
40
41 return length;
42 }
226 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
SPECIAL SECTION: ADVANCED STRING MANIPULATION EXERCISES
The preceding exercises are keyed to the text and designed to test the reader's understanding of fundamental string manipulation
concepts. This section includes a collection of intermediate and advanced string manipulation exercises. The reader should find
these problems challenging, yet enjoyable. The problems vary considerably in difficulty. Some require an hour or two of program
writing and implementation. Others are useful for lab assignments that might require two or three weeks of study and implementa-
tion. Some are challenging term projects.
5.42 (Text Analysis) The availability of computers with string manipulation capabilities has resulted in some rather interesting
approaches to analyzing the writings of great authors. Much attention has been focused on whether William Shakespeare ever lived.
Some scholars believe there is substantial evidence indicating that Christopher Marlowe or other authors actually penned the mas-
terpieces attributed to Shakespeare. Researchers have used computers to find similarities in the writings of these two authors. This
exercise examines three methods for analyzing texts with a computer.
a) Write a program that reads several lines of text from the keyboard and prints a table indicating the number of occur-
rences of each letter of the alphabet in the text. For example, the phrase
To be, or not to be: that is the question:
contains one “a,” two “b’s,” no “c’s,” etc.
b) Write a program that reads several lines of text and prints a table indicating the number of one-letter words, two-letter
words, three-letter words, etc., appearing in the text. For example, the phrase
Whether 'tis nobler in the mind to suffer
contains
c) Write a program that reads several lines of text and prints a table indicating the number of occurrences of each different
word in the text. The first version of your program should include the words in the table in the same order in which they
appear in the text. For example, the lines
To be, or not to be: that is the question:
Whether 'tis nobler in the mind to suffer
contain the words “to” three times, the word “be” two times, the word “or” once, etc. A more interesting
(and useful) printout should then be attempted in which the words are sorted alphabetically.
Enter a string: howLongCanThisNameWithoutQuestionPossiblyBe?
According to stringLength1 the string length is: 44
According to stringLength2 the string length is: 44
Word length Occurrences
1 0
2 2
3 1
42 (including 'tis)
5 0
6 2
7 1
Chapter 5 Pointers and Strings Solutions 227
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1// Exercise 5.42 Part A Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <iomanip>
9
10 using std::setw;
11
12 #include <cctype>
13
14 const int SIZE = 80;
15
16 int main()
17 {
18 char letters[ 26 ] = { 0 }, text[ 3 ][ SIZE ], i;
19
20 cout << "Enter three lines of text:\n";
21
22 for ( i = 0; i <= 2; ++i )
23 cin.getline( &text[ i ][ 0 ], SIZE );
24
25 for ( i = 0; i <= 2; ++i )
26 for ( int j = 0; text[ i ][ j ] != '\0'; ++j )
27 if ( isalpha( text[ i ][ j ] ) )
28 ++letters[ tolower( text[ i ][ j ] ) - 'a' ];
29
30 cout << "\nTotal letter counts:\n";
31
32 for ( i = 0; i <= 25; ++i )
33 cout << setw( 3 ) << static_cast< char > ( 'a' + i ) << ':' << setw( 3 )
34 << static_cast< int > ( letters[ i ] ) << endl;
35
36 return 0;
37 }
228 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Enter three lines of text:
when the cats are away the mice will play
still waters run deep
out of sight out of mind
Total letter counts:
a: 6
b: 0
c: 2
d: 2
e: 8
f: 2
g: 1
h: 4
i: 5
j: 0
k: 0
l: 5
m: 2
n: 3
o: 4
p: 2
q: 0
r: 3
s: 4
t: 8
u: 3
v: 0
w: 4
x: 0
y: 2
z: 0
1// Exercise 5.42 Part B Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstring>
9
10 int main()
11 {
12 const int SIZE = 80;
13 char text[ 3 ][ SIZE ], *temp;
14 int lengths[ 20 ] = { 0 }, i;
15
16 cout << "Enter three lines of text:\n";
17
18 for ( i = 0; i <= 2; ++i )
19 cin.getline( &text[ i ][ 0 ], SIZE );
20
21 for ( i = 0; i <= 2; ++i ) {
22 temp = strtok( &text[ i ][ 0 ], ". \n" );
23
24 while ( temp ) {
25 ++lengths[ strlen( temp ) ];
26 temp = strtok( 0, ". \n" );
27 }
Chapter 5 Pointers and Strings Solutions 229
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
28 }
29
30 cout << '\n';
31
32 for ( i = 1; i <= 19; ++i )
33 if ( lengths[ i ] )
34 cout << lengths[ i ] << " word(s) of length " << i << endl;
35
36 return 0;
37 }
Enter three lines of text:
the five time super bowl champion dallas cowboys
americas team the dallas cowboys
the once and future champion dallas cowboys
4 word(s) of length 3
5 word(s) of length 4
1 word(s) of length 5
4 word(s) of length 6
3 word(s) of length 7
3 word(s) of length 8
1// Exercise 5.42 Part C Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstring>
9
10 const int SIZE = 80;
11
12 int main()
13 {
14 char text[ 3 ][ SIZE ], *temp, words[ 100 ][ 20 ] = { "" };
15 int count[ 100 ] = { 0 }, i;
16
17 cout << "Enter three lines of text:\n";
18
19 for ( i = 0; i <= 2; ++i )
20 cin.getline( &text[ i ][ 0 ], SIZE );
21
22 for ( i = 0; i <= 2; ++i ) {
23 temp = strtok( &text[ i ][ 0 ], ". \n" );
24
25 while ( temp ) {
26 int j;
27
28 for ( j = 0; words[ j ][ 0 ] &&
29 strcmp( temp, &words[ j ][ 0 ] ) != 0; ++j )
30 ; // empty body
31
32 ++count[ j ];
33
34 if ( !words[ j ][ 0 ] )
35 strcpy( &words[ j ][ 0 ], temp );
36
37 temp = strtok( 0, ". \n" );
230 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.43 (Word Processing) One important function in word-processing systems is type justification—the alignment of words to
both the left and right margins of a page. This generates a professional-looking document that gives the appearance of being set in
type rather than prepared on a typewriter. Type justification can be accomplished on computer systems by inserting blank characters
between each of the words in a line so that the rightmost word aligns with the right margin.
Write a program that reads several lines of text and prints this text in type-justified format. Assume that the text is to be
printed on 8-1/2-inch-wide paper, and that one-inch margins are to be allowed on both the left and right sides of the printed page.
Assume that the computer prints 10 characters to the horizontal inch. Therefore, your program should print 6 1/2 inches of text, or
65 characters per line.
5.44 (Printing Dates in Various Formats) Dates are commonly printed in several different formats in business correspondence.
Two of the more common formats are
07/21/1955 and July 21, 1955
Write a program that reads a date in the first format and prints that date in the second format.
38 }
39 }
40
41 cout << '\n';
42
43 for ( int k = 0; words[ k ][ 0 ] != '\0' && k <= 99; ++k )
44 cout << "\"" << &words[ k ][ 0 ] << "\" appeared " << count[ k ]
45 << " time(s)\n";
46
47 cout << endl;
48
49 return 0;
50 }
Enter three lines of text:
lovebirds make great pets
the dallas cowboys are a great organization
peach faced lovebirds are small birds
"lovebirds" appeared 2 time(s)
"make" appeared 1 time(s)
"great" appeared 2 time(s)
"pets" appeared 1 time(s)
"the" appeared 1 time(s)
"dallas" appeared 1 time(s)
"cowboys" appeared 1 time(s)
"are" appeared 2 time(s)
"a" appeared 1 time(s)
"organization" appeared 1 time(s)
"peach" appeared 1 time(s)
"faced" appeared 1 time(s)
"small" appeared 1 time(s)
"birds" appeared 1 time(s)
1// Exercise 5.44 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8int main()
9{
Chapter 5 Pointers and Strings Solutions 231
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.45 (Check Protection) Computers are frequently employed in check-writing systems such as payroll and accounts payable ap-
plications. Many strange stories circulate regarding weekly paychecks being printed (by mistake) for amounts in excess of $1 mil-
lion. Weird amounts are printed by computerized check-writing systems, because of human error or machine failure. Systems
designers build controls into their systems to prevent such erroneous checks from being issued.
Another serious problem is the intentional alteration of a check amount by someone who intends to cash a check fraudulently.
To prevent a dollar amount from being altered, most computerized check-writing systems employ a technique called check protec-
tion.
Checks designed for imprinting by computer contain a fixed number of spaces in which the computer may print an amount.
Suppose a paycheck contains eight blank spaces in which the computer is supposed to print the amount of a weekly paycheck. If
the amount is large, then all eight of those spaces will be filled, for example,
1,230.60 (check amount)
--------
12345678 (position numbers)
On the other hand, if the amount is less than $1000, then several of the spaces would ordinarily be left blank. For example,
99.87
--------
12345678
contains three blank spaces. If a check is printed with blank spaces, it is easier for someone to alter the amount of the check. To
prevent a check from being altered, many check-writing systems insert leading asterisks to protect the amount as follows:
***99.87
--------
12345678
Write a program that inputs a dollar amount to be printed on a check and then prints the amount in check-protected format
with leading asterisks if necessary. Assume that nine spaces are available for printing an amount.
10 const char *months[ 13 ] = { "", "January", "February", "March", "April",
11 "May", "June", "July", "August", "September",
12 "October", "November", "December" };
13 int m, d, y;
14
15 cout << "Enter a date in the form mm/dd/yy: \n";
16 cin >> m;
17 cin.ignore();
18 cin >> d;
19 cin.ignore();
20 cin >> y;
21
22 cout << "The date is: " << months[ m ] << ' ' << d << ' '
23 << ( ( y < 50 ) ? y + 2000 : y + 1900 ) << endl;
24
25 return 0;
26 }
Enter a date in the form mm/dd/yy:
6/7/00
The date is: June 7 2000
232 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.46 (Writing the Word Equivalent of a Check Amount) Continuing the discussion of the previous example, we reiterate the im-
portance of designing check-writing systems to prevent alteration of check amounts. One common security method requires that the
check amount be written both in numbers, and “spelled out” in words as well. Even if someone is able to alter the numerical amount
of the check, it is extremely difficult to change the amount in words.
Many computerized check-writing systems do not print the amount of the check in words. Perhaps the main reason for this
omission is the fact that most high-level languages used in commercial applications do not contain adequate string manipulation
features. Another reason is that the logic for writing word equivalents of check amounts is somewhat involved.
Write a program that inputs a numeric check amount and writes the word equivalent of the amount. For example, the amount
112.43 should be written as
ONE HUNDRED TWELVE and 43/100
1// Exercise 5.45 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setfill;
12 using std::setw;
13 using std::setprecision;
14 using std::setiosflags;
15
16 int main()
17 {
18 double amount, base = 100000.0;
19 int i;
20
21 cout << "Enter check amount: ";
22 cin >> amount;
23 cout << "The protected amount is $";
24
25 for ( i = 0; amount < base; ++i )
26 base /= 10;
27
28 for ( int j = 1; j <= i; ++j )
29 cout << '*';
30
31 cout << setiosflags( ios::fixed | ios::showpoint )
32 << setw( 9 - i ) << setfill( '*' )
33 << setprecision( 2 ) << amount << endl;
34
35 return 0;
36 }
Enter check amount: 22.88
The protected amount is $****22.88
Chapter 5 Pointers and Strings Solutions 233
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
5.47 (Morse Code) Perhaps the most famous of all coding schemes is the Morse code, developed by Samuel Morse in 1832 for
use with the telegraph system. The Morse code assigns a series of dots and dashes to each letter of the alphabet, each digit and a
few special characters (such as period, comma, colon and semicolon). In sound-oriented systems, the dot represents a short sound,
and the dash represents a long sound. Other representations of dots and dashes are used with light-oriented systems and signal-flag
systems.
Separation between words is indicated by a space, or, quite simply, the absence of a dot or dash. In a sound-oriented system, a
space is indicated by a short period of time during which no sound is transmitted. The international version of the Morse code
appears in Fig. 5.39.
1// Exercise 5.46 Solution
2// NOTE: THIS PROGRAM ONLY HANDLES VALUES UP TO $99.99
3// The program is easily modified to process larger values
4#include <iostream>
5
6using std::cout;
7using std::endl;
8using std::cin;
9
10 int main()
11 {
12 const char *digits[ 10 ] = { "", "ONE", "TWO", "THREE", "FOUR", "FIVE",
13 "SIX", "SEVEN", "EIGHT", "NINE" };
14 const char *teens[ 10 ] = { "TEN", "ELEVEN", "TWELVE", "THIRTEEN",
15 "FOURTEEN", "FIFTEEN", "SIXTEEN",
16 "SEVENTEEN", "EIGHTEEN", "NINETEEN"};
17 const char *tens[ 10 ] = { "", "TEN", "TWENTY", "THIRTY", "FORTY", "FIFTY",
18 "SIXTY", "SEVENTY", "EIGHTY", "NINETY" };
19 int dollars, cents, digit1, digit2;
20
21 cout << "Enter the check amount (0.00 to 99.99): ";
22 cin >> dollars;
23 cin.ignore();
24 cin >> cents;
25 cout << "The check amount in words is:\n";
26
27 if ( dollars < 10 )
28 cout << digits[ dollars ] << ' ';
29 else if ( dollars < 20 )
30 cout << teens[ dollars - 10 ] << ' ';
31 else {
32 digit1 = dollars / 10;
33 digit2 = dollars % 10;
34
35 if ( !digit2 )
36 cout << tens[ digit1 ] << ' ';
37 else
38 cout << tens[ digit1 ] << "-" << digits[ digit2 ] << ' ';
39 }
40
41 cout << "Dollars and " << cents << "/100" << endl;
42
43 return 0;
44 }
Enter the check amount (0.00 to 99.99): 72.68
The check amount in words is:
SEVENTY-TWO Dollars and 68/100
234 Pointers and Strings Solutions Chapter 5
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Write a program that reads an English-language phrase and encodes the phrase into Morse code. Also write a program that
reads a phrase in Morse code and converts the phrase into the English-language equivalent. Use one blank between each Morse-
coded letter and three blanks between each Morse-coded word.
5.48 (A Metric Conversion Program) Write a program that will assist the user with metric conversions. Your program should
allow the user to specify the names of the units as strings (i.e., centimeters, liters, grams, etc. for the metric system and inches, quarts,
pounds, etc., for the English system) and should respond to simple questions such as
"How many inches are in 2 meters?"
"How many liters are in 10 quarts?"
Your program should recognize invalid conversions. For example, the question
"How many feet in 5 kilograms?"
is not meaningful, because "feet" are units of length, while "kilograms" are units of weight.
A CHALLENGING STRING MANIPULATION PROJECT
5.49 (A Crossword Puzzle Generator) Most people have worked a crossword puzzle, but few have ever attempted to generate
one. Generating a crossword puzzle is a difficult problem. It is suggested here as a string manipulation project requiring substantial
sophistication and effort. There are many issues the programmer must resolve to get even the simplest crossword puzzle generator
program working. For example, how does one represent the grid of a crossword puzzle inside the computer? Should one use a series
of strings, or should double-subscripted arrays be used? The programmer needs a source of words (i.e., a computerized dictionary)
that can be directly referenced by the program. In what form should these words be stored to facilitate the complex manipulations
required by the program? The really ambitious reader will want to generate the “clues” portion of the puzzle in which the brief hints
for each “across” word and each “down” word are printed for the puzzle worker. Merely printing a version of the blank puzzle itself
is not a simple problem.
Character Code Character Code
A.- T -
B-... U ..-
C-.-. V ...-
D-.. W .--
E.X -..-
F..-. Y -.--
G--. Z --..
H....
I .. Digits
J .--- 1.----
K -.- 2..---
L .-.. 3...--
M -- 4....-
N -. 5.....
O --- 6-....
P .--. 7--...
Q --.- 8---..
R .-. 9----.
S ... 0-----
Fig. 5.39 The letters of the alphabet as expressed in international Morse code.
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
6
Classes and
Data Abstraction
Solutions
Solutions
6.3 What is the purpose of the scope resolution operator?
ANS: The scope resolution operator is used to specify the class to which a function belongs. It also resolves the ambiguity
caused by multiple classes having member functions of the same name.
6.4 Compare and contrast the notions of struct and class in C++.
ANS: In C++, the keywords struct and class are used to define types containing data members (and member func-
tions for classes). The differences occur in the default access privileges for each. The default access for class members
is private and the default access for struct members is public. The access privileges for class and struct can
be specified explicitly.
6.5 Provide a constructor that is capable of using the current time from the time() function—declared in the C Standard Li-
brary header ctime—to initialize an object of the Time class.
1// P6_05.H
2#ifndef p6_05_H
3#define p6_05_H
4#include <iostream>
5
6class Time {
7public:
8 Time();
9 void setHour( int h ) { hour = ( h >= 0 && h < 24 ) ? h : 0; }
10 void setMinute( int m ) { minute = ( m >= 0 && m < 60 ) ? m : 0; }
11 void setSecond( int s ) { second = ( s >= 0 && s < 60 ) ? s : 0; }
12 int getHour( void ) { return hour; }
13 int getMinute( void ) { return minute; }
14 int getSecond( void ) { return second; }
15 void printStandard( void );
16 private:
17 int hour;
18 int minute;
19 int second;
20 };
21
22 #endif
236 Classes and Data Abstraction Solutions Chapter 6
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
23 // P6_5M.cpp
24 // member function definitions for p6_05.cpp
25 #include <iostream>
26
27 using std::cout;
28
29 #include <ctime>
30
31 #include "p6_05.h"
32
33 Time::Time()
34 {
35 long int totalTime; // time in seconds since 1970
36 int currentYear = 1998 - 1970; // current year
37 double totalYear; // current time in years
38 double totalDay; // days since beginning of year
39 double day; // current time in days
40 double divisor; // conversion divisor
41 int timeShift = 7; // time returned by time() is
42 // given as the number of seconds
43 // elapsed since 1/1/70 GMT.
44 // Depending on the time zone
45 // you are in, you must shift
46 // the time by a certain
47 // number of hours. For this
48 // problem, 7 hours is the
49 // current shift for EST.
50 double tempMinute; // Used in conversion to seconds.
51 double tempSecond; // Used to set seconds.
52
53 totalTime = time( 0 );
54 divisor = ( 60.0 * 60.0 * 24.0 * 365.0 );
55 totalYear = totalTime / divisor - currentYear;
56 totalDay = 365 * totalYear; // leap years ignored
57 day = totalDay - static_cast< int >( totalDay );
58 tempMinute = totalDay * 24 * 60;
59 setHour( day * 24 + timeShift );
60 setMinute( ( day * 24 - static_cast< int >( day * 24 ) ) * 60 );
61 tempMinute -= static_cast< int > ( tempMinute ) * 60;
62 tempSecond = tempMinute;
63 setSecond( tempSecond );
64 }
65
66 void Time::printStandard()
67 {
68 cout << ( ( hour % 12 == 0 ) ? 12 : hour % 12 ) << ':'
69 << ( minute < 10 ? "0" : "" ) << minute << ':'
70 << ( second < 10 ? "0" : "" ) << second << '\n';
71 }
72 // driver for p6_05.cpp
73 #include <iostream>
74
75 using std::cout;
76 using std::endl;
77 using std::cin;
78 using std::ios;
79 #include "p6_05.h"
80
81 int main()
82 {
Chapter 6 Classes and Data Abstraction Solutions 237
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
6.6 Create a class called Complex for performing arithmetic with complex numbers. Write a driver program to test your class.
Complex numbers have the form
realPart + imaginaryPart * i
where i is
Use double variables to represent the private data of the class. Provide a constructor function that enables an object of this
class to be initialized when it is declared. The constructor should contain default values in case no initializers are provided. Provide
public member functions for each of the following:
a) Addition of two Complex numbers: The real parts are added together and the imaginary parts are added together.
b) Subtraction of two Complex numbers: The real part of the right operand is subtracted from the real part of the left
operand and the imaginary part of the right operand is subtracted from the imaginary part of the left operand.
c) Printing Complex numbers in the form (a, b) where a is the real part and b is the imaginary part.
83 Time t;
84
85 t.printStandard();
86
87 return 0;
88 }
11:26:00
1// P6_06.H
2#ifndef p6_06_H
3#define p6_06_H
4
5class Complex {
6public:
7 Complex( double = 0.0, double = 0.0 ); // default constructor
8 void addition( const Complex & );
9 void subtraction( const Complex & );
10 void printComplex( void );
11 void setComplexNumber( double, double );
12 private:
13 double realPart;
14 double imaginaryPart;
15 };
16
17 #endif
18 // p6_06M.cpp
19 // member function definitions for p6_06.cpp
20 #include <iostream>
21
22 using std::cout;
23
24 #include "p6_06.h"
25
26 Complex::Complex( double real, double imaginary )
27 { setComplexNumber( real, imaginary ); }
28
29 void Complex::addition( const Complex &a )
30 {
31 realPart += a.realPart;
-1
238 Classes and Data Abstraction Solutions Chapter 6
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
6.7 Create a class called Rational for performing arithmetic with fractions. Write a driver program to test your class.
Use integer variables to represent the private data of the class—the numerator and the denominator. Provide a constructor
function that enables an object of this class to be initialized when it is declared. The constructor should contain default values in
case no initializers are provided and should store the fraction in reduced form (i.e., the fraction
32 imaginaryPart += a.imaginaryPart;
33 }
34
35 void Complex::subtraction( const Complex &s )
36 {
37 realPart -= s.realPart;
38 imaginaryPart -= s.imaginaryPart;
39 }
40
41 void Complex::printComplex( void )
42 { cout << '(' << realPart << ", " << imaginaryPart << ')'; }
43
44 void Complex::setComplexNumber( double rp, double ip )
45 {
46 realPart = rp;
47 imaginaryPart = ip;
48 }
49 // driver for p6_06.cpp
50 #include <iostream>
51
52 using std::cout;
53 using std::endl;
54
55 #include "p6_06.h"
56
57 int main()
58 {
59 Complex b( 1, 7 ), c( 9, 2 );
60
61 b.printComplex();
62 cout << " + ";
63 c.printComplex();
64 cout << " = ";
65 b.addition( c );
66 b.printComplex();
67
68 cout << '\n';
69 b.setComplexNumber( 10, 1 ); // reset realPart and imaginaryPart
70 c.setComplexNumber( 11, 5 );
71 b.printComplex();
72 cout << " - ";
73 c.printComplex();
74 cout << " = ";
75 b.subtraction( c );
76 b.printComplex();
77 cout << endl;
78
79 return 0;
80 }
(1, 7) + (9, 2) = (10, 9)
(10, 1) - (11, 5) = (-1, -4)
Chapter 6 Classes and Data Abstraction Solutions 239
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
would be stored in the object as 1 in the numerator and 2 in the denominator). Provide public member functions for each of the
following:
a) Addition of two Rational numbers. The result should be stored in reduced form.
b) Subtraction of two Rational numbers. The result should be stored in reduced form.
c) Multiplication of two Rational numbers. The result should be stored in reduced form.
d) Division of two Rational numbers. The result should be stored in reduced form.
e) Printing Rational numbers in the form a/b where a is the numerator and b is the denominator.
f) Printing Rational numbers in double floating-point format.
1// P6_07.H
2#ifndef P6_07_H
3#define P6_07_H
4
5class Rational {
6public:
7 Rational( int = 0, int = 1 ); // default constructor
8 Rational addition( const Rational & );
9 Rational subtraction( const Rational & );
10 Rational multiplication( const Rational & );
11 Rational division( Rational & );
12 void printRational( void );
13 void printRationalAsDouble( void );
14 private:
15 int numerator;
16 int denominator;
17 void reduction( void ); // utility function
18 };
19
20 #endif
21 // P6_07M.cpp
22 // member function definitions for p6_07.cpp
23 #include <iostream>
24
25 using std::cout;
26
27 #include "p6_07.h"
28
29 Rational::Rational( int n, int d )
30 {
31 numerator = n;
32 denominator = d;
33 }
34
35 Rational Rational::addition( const Rational &a )
36 {
37 Rational t;
38
39 t.numerator = a.numerator * denominator;
40 t.numerator += a.denominator * numerator;
41 t.denominator = a.denominator * denominator;
42 t.reduction();
43
44 return t;
45 }
46
47 Rational Rational::subtraction( const Rational &s )
2
4
---
240 Classes and Data Abstraction Solutions Chapter 6
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
48 {
49 Rational t;
50
51 t.numerator = s.denominator * numerator;
52 t.numerator -= denominator * s.numerator;
53 t.denominator = s.denominator * denominator;
54 t.reduction();
55
56 return t;
57 }
58
59 Rational Rational::multiplication( const Rational &m )
60 {
61 Rational t;
62
63 t.numerator = m.numerator * numerator;
64 t.denominator = m.denominator * denominator;
65 t.reduction();
66
67 return t;
68 }
69
70 Rational Rational::division( Rational &v )
71 {
72 Rational t;
73
74 t.numerator = v.denominator * numerator;
75 t.denominator = denominator * v.numerator;
76 t.reduction();
77
78 return t;
79 }
80
81 void Rational::printRational( void )
82 {
83 if ( denominator == 0 )
84 cout << "\nDIVIDE BY ZERO ERROR!!!" << '\n';
85 else if ( numerator == 0 )
86 cout << 0;
87 else
88 cout << numerator << '/' << denominator;
89 }
90
91 void Rational::printRationalAsDouble( void )
92 { cout << static_cast< double >( numerator ) / denominator; }
93
94 void Rational::reduction( void )
95 {
96 int largest;
97 largest = numerator > denominator ? numerator : denominator;
98
99 int gcd = 0; // greatest common divisor
100
101 for ( int loop = 2; loop <= largest; ++loop )
102 if ( numerator % loop == 0 && denominator % loop == 0 )
103 gcd = loop;
104
105 if (gcd != 0) {
106 numerator /= gcd;
107 denominator /= gcd;
108 }
109 }
Chapter 6 Classes and Data Abstraction Solutions 241
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
110 // driver for P6_07.cpp
111 #include <iostream>
112
113 using std::cout;
114 using std::endl;
115
116 #include "p6_07.h"
117
118 int main()
119 {
120 Rational c( 1, 3 ), d( 7, 8 ), x;
121
122 c.printRational();
123 cout << " + ";
124 d.printRational();
125 x = c.addition( d );
126 cout << " = ";
127 x.printRational();
128 cout << '\n';
129 x.printRational();
130 cout << " = ";
131 x.printRationalAsDouble();
132 cout << "\n\n";
133
134 c.printRational();
135 cout << " - ";
136 d.printRational();
137 x = c.subtraction( d );
138 cout << " = ";
139 x.printRational();
140 cout << '\n';
141 x.printRational();
142 cout << " = ";
143 x.printRationalAsDouble();
144 cout << "\n\n";
145
146 c.printRational();
147 cout << " x ";
148 d.printRational();
149 x = c.multiplication( d );
150 cout << " = ";
151 x.printRational();
152 cout << '\n';
153 x.printRational();
154 cout << " = ";
155 x.printRationalAsDouble();
156 cout << "\n\n";
157
158 c.printRational();
159 cout << " / ";
160 d.printRational();
161 x = c.division( d );
162 cout << " = ";
163 x.printRational();
164 cout << '\n';
165 x.printRational();
166 cout << " = ";
167 x.printRationalAsDouble();
168 cout << endl;
169
170 return 0;
171 }
242 Classes and Data Abstraction Solutions Chapter 6
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
6.8 Modify the Time class of Fig. 6.10 to include a tick member function that increments the time stored in a Time object
by one second. The Time object should always remain in a consistent state. Write a driver program that tests the tick member
function in a loop that prints the time in standard format during each iteration of the loop to illustrate that the tick member function
works correctly. Be sure to test the following cases:
a) Incrementing into the next minute.
b) Incrementing into the next hour.
c) Incrementing into the next day (i.e., 11:59:59 PM to 12:00:00 AM).
1/3 + 7/8 = 29/24
29/24 = 1.20833
1/3 - 7/8 = -13/24
-13/24 = -0.541667
1/3 x 7/8 = 7/24
7/24 = 0.291667
1/3 / 7/8 = 8/21
8/21 = 0.380952
1// P6_08.H
2#ifndef p6_08_H
3#define p6_08_H
4
5class Time {
6public:
7 Time( int = 0, int = 0, int = 0 );
8 void setTime( int, int, int );
9 void setHour( int );
10 void setMinute( int );
11 void setSecond( int );
12 int getHour( void );
13 int getMinute( void );
14 int getSecond( void );
15 void printStandard( void );
16 void tick( void );
17 private:
18 int hour;
19 int minute;
20 int second;
21 };
22
23 #endif
24 // P6_08M.cpp
25 // member function definitions for p6_08.cpp
26 #include <iostream>
27
28 using std::cout;
29
30 #include "p6_08.h"
31
32 Time::Time( int hr, int min, int sec ) { setTime( hr, min, sec ); }
33
34 void Time::setTime( int h, int m, int s )
35 {
36 setHour( h );
37 setMinute( m );
Chapter 6 Classes and Data Abstraction Solutions 243
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
38 setSecond( s );
39 }
40
41 void Time::setHour( int h ) { hour = ( h >= 0 && h < 24 ) ? h : 0; }
42
43 void Time::setMinute( int m )
44 {
45 minute = ( m >= 0 && m < 60 ) ? m : 0;
46 }
47
48 void Time::setSecond( int s )
49 {
50 second = ( s >= 0 && s < 60 ) ? s : 0;
51 }
52
53 int Time::getHour( void ) { return hour; }
54
55 int Time::getMinute( void ) { return minute; }
56
57 int Time::getSecond( void ) { return second; }
58
59 void Time::printStandard( void )
60 {
61 cout << ( ( hour % 12 == 0 ) ? 12 : hour % 12 ) << ':'
62 << ( minute < 10 ? "0" : "" ) << minute << ':'
63 << ( second < 10 ? "0" : "" ) << second
64 << ( hour < 12 ? " AM" : " PM" );
65 }
66
67 void Time::tick( void )
68 {
69 setSecond( getSecond() + 1 );
70
71 if ( getSecond() == 0 ) {
72 setMinute( getMinute() + 1 );
73
74 if ( getMinute() == 0 )
75 setHour( getHour() + 1 );
76 }
77 }
78 // driver for p6_08.cpp
79 #include <iostream>
80
81 using std::cout;
82 using std::endl;
83
84 #include "p6_08.h"
85
86 const int MAX_TICKS = 3000;
87
88 main()
89 {
90 Time t;
91
92 t.setTime( 23, 59, 57 );
93
94 for ( int ticks = 1; ticks < MAX_TICKS; ++ticks ) {
95 t.printStandard();
96 cout << endl;
97 t.tick();
244 Classes and Data Abstraction Solutions Chapter 6
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
6.9 Modify the Date class of Fig. 6.12 to perform error checking on the initializer values for data members month, day and
year. Also, provide a member function nextDay to increment the day by one. The Date object should always remain in a con-
sistent state. Write a driver program that tests the nextDay function in a loop that prints the date during each iteration of the loop
to illustrate that the nextDay function works correctly. Be sure to test the following cases:
a) Incrementing into the next month.
b) Incrementing into the next year.
98 }
99
100 return 0;
101 }
11:59:57 PM
.
.
.
.
12:49:50 AM
12:49:51 AM
12:49:52 AM
12:49:53 AM
12:49:54 AM
12:49:55 AM
1// P6_09.H
2#ifndef p6_09_H
3#define p6_09_H
4
5class Date {
6public:
7 Date( int = 1, int = 1, int = 1900 ); // default constructor
8 void print( void );
9 void setDate( int, int, int );
10 void setMonth( int );
11 void setDay( int );
12 void setYear( int );
13 int getMonth( void );
14 int getDay( void );
15 int getYear( void );
16 bool leapYear( void );
17 int monthDays( void );
18 void nextDay( void );
19 private:
20 int month;
21 int day;
22 int year;
23 };
24
25 #endif
26 // p6_09M.cpp
27 // member function definitions for p6_09.cpp
28 #include <iostream>
29
30 using std::cout;
31
32 #include "p6_09.h"
33
Chapter 6 Classes and Data Abstraction Solutions 245
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
34 Date::Date( int m, int d, int y ) { setDate( m, d, y ); }
35
36 int Date::getDay() { return day; }
37
38 int Date::getMonth() { return month; }
39
40 int Date::getYear() { return year; }
41
42 void Date::setDay( int d )
43 {
44 if ( month == 2 && leapYear() )
45 day = ( d <= 29 && d >= 1 ) ? d : 1;
46 else
47 day = ( d <= monthDays() && d >= 1 ) ? d : 1;
48 }
49
50 void Date::setMonth( int m ) { month = m <= 12 && m >= 1 ? m : 1; }
51
52 void Date::setYear( int y )
53 {
54 year = y <= 2000 && y >= 1900 ? y : 1900;
55 }
56
57 void Date::setDate( int mo, int dy, int yr )
58 {
59 setMonth( mo );
60 setDay( dy );
61 setYear( yr );
62 }
63
64 void Date::print()
65 { cout << month << '-' << day << '-' << year << '\n'; }
66
67 void Date::nextDay()
68 {
69 setDay( day + 1 );
70
71 if ( day == 1 ) {
72 setMonth( month + 1 );
73
74 if ( month == 1 )
75 setYear( year + 1 );
76 }
77 }
78
79 bool Date::leapYear( void )
80 {
81 if ( year % 400 == 0 || ( year % 4 == 0 && year % 100 != 0 ) )
82 return true;
83 else
84 return false; // not a leap year
85 }
86
87 int Date::monthDays( void )
88 {
89 const int days[ 12 ] = { 31, 28, 31, 30, 31, 30,
90 31, 31, 30, 31, 30, 31 };
91
92 return month == 2 && leapYear() ? 29 : days[ month - 1 ];
93 }
246 Classes and Data Abstraction Solutions Chapter 6
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
6.10 Combine the modified Time class of Exercise 6.8 and the modified Date class of Exercise 6.9 into one class called Date-
AndTime (in Chapter 9 we will discuss inheritance, which will enable us to accomplish this task quickly without modifying the
existing class definitions). Modify the ticks function to call the nextDay function if the time is incremented into the next day.
Modify function printStandard and printMilitary to output the date in addition to the time. Write a driver program to
test the new class DateAndTime. Specifically, test incrementing the time into the next day.
94 // driver for p6_09.cpp
95 #include <iostream>
96
97 using std::cout;
98 using std::endl;
99
100 #include "p6_09.h"
101
102 int main()
103 {
104 const int MAXDAYS = 160;
105 Date d( 9, 2, 1998 );
106
107 for ( int loop = 1; loop <= MAXDAYS; ++loop ) {
108 d.print();
109 d.nextDay();
110 }
111
112 cout << endl;
113
114 return 0;
115 }
9-2-1998
9-3-1998
.
.
.
2-5-1999
2-6-1999
2-7-1999
2-8-1999
1// P6_10.H
2#ifndef p6_10_H
3#define p6_10_H
4
5class DateAndTime {
6public:
7 DateAndTime( int = 1, int = 1, int = 1900,
8 int = 0, int = 0, int = 0 );
9 void setDate( int, int, int );
10 void setMonth( int );
11 void setDay( int );
12 void setYear( int );
13 int getMonth( void );
14 int getDay( void );
15 int getYear( void );
16 void nextDay( void );
17 void setTime( int, int, int );
18 void setHour( int );
19 void setMinute( int );
20 void setSecond( int );
Chapter 6 Classes and Data Abstraction Solutions 247
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
21 int getHour( void );
22 int getMinute( void );
23 int getSecond( void );
24 void printStandard( void );
25 void printMilitary( void );
26 int monthDays( void );
27 void tick( void );
28 bool leapYear( void );
29 private:
30 int month;
31 int day;
32 int year;
33 int hour;
34 int minute;
35 int second;
36 };
37
38 #endif
39 // P6_10M.cpp
40 // member function definitions for p6_10.cpp
41 #include <iostream>
42
43 using std::cout;
44 using std::endl;
45
46 #include "p6_10.h"
47
48 DateAndTime::DateAndTime( int m, int d, int y, int hr,
49 int min, int sec )
50 {
51 setDate( m, d, y );
52 setTime( hr, min, sec );
53 }
54
55 void DateAndTime::setDate( int mo, int dy, int yr )
56 {
57 setMonth( mo );
58 setDay( dy );
59 setYear( yr );
60 }
61
62 int DateAndTime::getDay( void ) { return day; }
63
64 int DateAndTime::getMonth( void ) { return month; }
65
66 int DateAndTime::getYear( void ) { return year; }
67
68 void DateAndTime::setDay( int d )
69 {
70 if ( month == 2 && leapYear() )
71 day = ( d <= 29 && d >= 1 ) ? d : 1;
72 else
73 day = ( d <= monthDays() && d >= 1 ) ? d : 1;
74 }
75
76 void DateAndTime::setMonth( int m )
77 { month = m <= 12 && m >= 1 ? m : 1; }
78
79 void DateAndTime::setYear( int y )
80 { year = y <= 2000 && y >= 1900 ? y : 1900; }
248 Classes and Data Abstraction Solutions Chapter 6
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
81
82 void DateAndTime::nextDay( void )
83 {
84 setDay( day + 1 );
85
86 if ( day == 1 ) {
87 setMonth( month + 1 );
88
89 if ( month == 1 )
90 setYear( year + 1 );
91 }
92 }
93
94 void DateAndTime::setTime( int hr, int min, int sec )
95 {
96 setHour( hr );
97 setMinute( min );
98 setSecond( sec );
99 }
100
101 void DateAndTime::setHour( int h )
102 {
103 hour = ( h >= 0 && h < 24 ) ? h : 0;
104 }
105
106 void DateAndTime::setMinute( int m )
107 {
108 minute = ( m >= 0 && m < 60 ) ? m : 0;
109 }
110
111 void DateAndTime::setSecond( int s )
112 {
113 second = ( s >= 0 && s < 60 ) ? s : 0;
114 }
115
116 int DateAndTime::getHour( void ) { return hour; }
117
118 int DateAndTime::getMinute( void ) { return minute; }
119
120 int DateAndTime::getSecond( void ) { return second; }
121
122 void DateAndTime::printStandard( void )
123 {
124 cout << ( ( hour % 12 == 0 ) ? 12 : hour % 12 ) << ':'
125 << ( minute < 10 ? "0" : "" ) << minute << ':'
126 << ( second < 10 ? "0" : "" ) << second
127 << ( hour < 12 ? " AM " : " PM " )
128 << month << '-' << day << '-' << year << endl;
129 }
130
131 void DateAndTime::printMilitary( void )
132 {
133 cout << ( hour < 10 ? "0" : "" ) << hour << ':'
134 << ( minute < 10 ? "0" : "" ) << minute << ':'
135 << ( second < 10 ? "0" : "" ) << second << " "
136 << month << '-' << day << '-' << year << endl;
137 }
138
139 void DateAndTime::tick( void )
140 {
141 setSecond( second + 1 );
142
Chapter 6 Classes and Data Abstraction Solutions 249
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
143 if ( second == 0 ) {
144 setMinute( minute + 1 );
145
146 if ( minute == 0 ) {
147 setHour( hour + 1 );
148
149 if ( hour == 0 )
150 nextDay();
151 }
152 }
153 }
154
155 bool DateAndTime::leapYear( void )
156 {
157 if ( year % 400 == 0 || ( year % 4 == 0 && year % 100 != 0 ) )
158 return true;
159 else
160 return false; // not a leap year
161 }
162
163 int DateAndTime::monthDays( void )
164 {
165 const int days[ 12 ] = { 31, 28, 31, 30, 31, 30,
166 31, 31, 30, 31, 30, 31 };
167
168 return ( month == 2 && leapYear() ) ? 29 : days[ ( month - 1 ) ];
169 }
170 // driver for p6_10.cpp
171 #include <iostream>
172
173 using std::cout;
174 using std::endl;
175
176 #include "p6_10.h"
177
178 int main()
179 {
180 const int MAXTICKS = 3000;
181
182 DateAndTime d( 3, 2, 1998, 23, 50, 0 );
183
184 for ( int ticks = 1; ticks <= MAXTICKS; ++ticks ) {
185 cout << "Military time: ";
186 d.printMilitary();
187 cout << "Standard time: ";
188 d.printStandard();
189 d.tick();
190 }
191
192 cout << endl;
193
194 return 0;
195 }
250 Classes and Data Abstraction Solutions Chapter 6
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
6.11 Modify the set functions in the program of Fig. 6.10 to return appropriate error values if an attempt is made to set a data
member of an object of class Time to an invalid value.
Military time: 23:50:00 3-2-1998
Standard time: 11:50:00 PM 3-2-1998
.
.
.
Standard time: 12:39:56 AM 3-3-1998
Military time: 00:39:57 3-3-1998
Standard time: 12:39:57 AM 3-3-1998
Military time: 00:39:58 3-3-1998
Standard time: 12:39:58 AM 3-3-1998
Military time: 00:39:59 3-3-1998
Standard time: 12:39:59 AM 3-3-1998
1// P6_11.H
2#ifndef P6_11_H
3#define P6_11_H
4
5class Time {
6public:
7 Time( int = 0, int = 0, int = 0 );
8 void setTime( int, int, int );
9 void setHour( int );
10 void setMinute( int );
11 void setSecond( int );
12 void setInvalidTime( int t ) { invalidTime = t; }
13 int getHour( void ) { return hour; }
14 int getMinute( void ) { return minute; }
15 int getSecond( void ) { return second; }
16 int getInvalidTime( void ) { return invalidTime; }
17 void printMilitary( void );
18 void printStandard( void );
19 private:
20 int hour;
21 int minute;
22 int second;
23 int invalidTime; // set if an invalid time is attempted
24 };
25
26 #endif
27 // P6_11M.cpp
28 // member function defintions for p6_11.cpp
29 #include <iostream>
30
31 using std::cout;
32
33 #include "p6_11.h"
34
35 Time::Time( int hr, int min, int sec )
36 { setTime( hr, min, sec ); }
37
38 void Time::setTime( int h, int m, int s )
39 {
40 setHour( h );
41 setMinute( m );
42 setSecond( s );
Chapter 6 Classes and Data Abstraction Solutions 251
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
43 }
44
45 void Time::setHour( int hr )
46 {
47 if ( hr >= 0 && hr < 24 ) {
48 hour = hr;
49 setInvalidTime( 1 ); // hour is valid
50 }
51 else {
52 hour = 0;
53 setInvalidTime( 0 ); // hour is invalid
54 }
55 }
56
57 void Time::setMinute( int min )
58 {
59 if ( min >= 0 && min < 60 ) {
60 minute = min;
61 setInvalidTime( 1 ); // minute is valid
62 }
63 else {
64 minute = 0;
65 setInvalidTime( 0 ); // minute is invalid
66 }
67 }
68
69 void Time::setSecond( int sec )
70 {
71 if ( sec >= 0 && sec < 60 ) {
72 second = sec;
73 setInvalidTime( 1 ); // second is valid
74 }
75 else {
76 second = 0;
77 setInvalidTime( 0 ); // second is invalid
78 }
79 }
80
81 void Time::printMilitary( void )
82 {
83 cout << ( hour < 10 ? "0" : "" ) << hour << ':'
84 << ( minute < 10 ? "0" : "" ) << minute << ':'
85 << ( second < 10 ? "0" : "" ) << second;
86 }
87
88 void Time::printStandard( void )
89 {
90 cout << ( ( hour % 12 == 0 ) ? 12 : hour % 12 ) << ':'
91 << ( minute < 10 ? "0": "" ) << minute << ':'
92 << ( second < 10 ? "0": "" ) << second
93 << ( hour < 12 ? " AM" : " PM" );
94 }
95 // driver for p6_11.cpp
96 #include <iostream>
97
98 using std::cout;
99 using std::endl;
100
101 #include "p6_11.h"
102
252 Classes and Data Abstraction Solutions Chapter 6
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
6.12 Create a class Rectangle. The class has attributes length and width, each of which defaults to 1. It has member func-
tions that calculate the perimeter and the area of the rectangle. It has set and get functions for both length and width. The
set functions should verify that length and width are each floating-point numbers larger than 0.0 and less than 20.0.
103 int main()
104 {
105 Time t1( 17, 34, 25 ), t2( 99, 345, -897 );
106
107 // all t1 object's times are valid
108 if ( !t1.getInvalidTime() )
109 cout << "Error: invalid time setting(s) attempted." << '\n'
110 << "Invalid setting(s) changed to zero." << '\n';
111
112 t1.printStandard();
113
114 // object t2 has invalid time settings
115 if ( !t2.getInvalidTime() )
116 cout << "\nError: invalid time setting(s) attempted.\n"
117 << "Invalid setting(s) changed to zero.\n";
118
119 t2.printMilitary();
120 cout << endl;
121
122 return 0;
123 }
5:34:25 PM
Error: invalid time setting(s) attempted.
Invalid setting(s) changed to zero.
00:00:00
1// P6_12.H
2#ifndef P6_12_H
3#define P6_12_H
4
5class Rectangle {
6public:
7 Rectangle( double = 1.0, double = 1.0 );
8 double perimeter( void );
9 double area( void );
10 void setWidth( double w );
11 void setLength( double l );
12 double getWidth( void );
13 double getLength( void );
14 private:
15 double length;
16 double width;
17 };
18
19 #endif
20 // P6_12M.cpp
21 // member function definitions for p6_12.cpp
22 #include <iostream>
23
24 using std::cout;
25 using std::endl;
26 using std::cin;
Chapter 6 Classes and Data Abstraction Solutions 253
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
27 using std::ios;
28
29
30 #include "p6_12.h"
31
32 Rectangle::Rectangle( double w, double l )
33 {
34 setWidth(w);
35 setLength(l);
36 }
37
38 double Rectangle::perimeter( void )
39 {
40 return 2 * ( width + length );
41 }
42
43 double Rectangle::area( void )
44 {
45 return width * length;
46 }
47
48 void Rectangle::setWidth( double w )
49 {
50 width = w > 0 && w < 20.0 ? w : 1.0;
51 }
52
53 void Rectangle::setLength( double l )
54 {
55 length = l > 0 && l < 20.0 ? l : 1.0;
56 }
57
58 double Rectangle::getWidth( void ) { return width; }
59
60 double Rectangle::getLength( void ) { return length; }
61 // driver for p6_12.cpp
62
63 #include "p6_12.h"
64
65 int main()
66 {
67 Rectangle a, b( 4.0, 5.0 ), c( 67.0, 888.0 );
68
69 cout << setiosflags( ios::fixed | ios::showpoint );
70 cout << setprecision( 1 );
71
72 // output Rectangle a
73 cout << "a: length = " << a.getLength()
74 << "; width = " << a.getWidth()
75 << "; perimeter = " << a.perimeter() << "; area = "
76 << a.area() << '\n';
77
78 // output Rectangle b
79 cout << "b: length = " << b.getLength()
80 << "; width = " << b.getWidth()
81 << "; perimeter = " << b.perimeter() << "; area = "
82 << b.area() << '\n';
83
84 // output Rectangle c; bad values attempted
85 cout << "c: length = " << c.getLength()
86 << "; width = " << c.getWidth()
254 Classes and Data Abstraction Solutions Chapter 6
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
6.13 Create a more sophisticated Rectangle class than the one you created in Exercise 6.12. This class stores only the Carte-
sian coordinates of the four corners of the rectangle. The constructor calls a set function that accepts four sets of coordinates and
verifies that each of these is in the first quadrant with no single x or y coordinate larger than 20.0. The set function also verifies that
the supplied coordinates do, in fact, specify a rectangle. Member functions calculate the length, width, perimeter and area.
The length is the larger of the two dimensions. Include a predicate function square that determines if the rectangle is a square.
87 << "; perimeter = " << c.perimeter() << "; area = "
88 << c.area() << endl;
89
90 return 0;
91 }
a: length = 1.0; width = 1.0; perimeter = 4.0; area = 1.0
b: length = 5.0; width = 4.0; perimeter = 18.0; area = 20.0
c: length = 1.0; width = 1.0; perimeter = 4.0; area = 1.0
1// P6_13.H
2#ifndef P6_13_H
3#define P6_13_H
4
5class Rectangle {
6public:
7 Rectangle( double *, double *, double *, double * );
8 void setCoord( double *, double *, double *, double * );
9 void perimeter( void );
10 void area( void );
11 void square( void );
12 private:
13 double point1[ 2 ];
14 double point2[ 2 ];
15 double point3[ 2 ];
16 double point4[ 2 ];
17 };
18
19 #endif
20 // P6_13M.cpp
21 // member function definitions for p6_13.cpp
22 #include <iostream>
23
24 using std::cout;
25 using std::ios;
26
27 #include <iomanip>
28
29 using std::setprecision;
30 using std::setiosflags;
31
32 #include <cmath>
33
34 #include "p6_13.h"
35
36 Rectangle::Rectangle( double *a, double *b,
37 double *c, double *d )
38 { setCoord( a, b, c, d ); }
39
40 void Rectangle::setCoord( double *p1, double *p2,
41 double *p3, double *p4 )
Chapter 6 Classes and Data Abstraction Solutions 255
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
42 {
43 // Arrangement of points
44 // p4.........p3
45 // . .
46 // . .
47 // p1.........p2
48
49 const int x = 0, y = 1; // added for clarity
50
51 // validate all points
52 point1[ x ] = ( p1[ x ] > 20.0 || p1[ x ] < 0.0 )? 0.0 : p1[ x ];
53 point1[ y ] = ( p1[ y ] > 20.0 || p1[ y ] < 0.0 )? 0.0 : p1[ y ];
54 point2[ x ] = ( p2[ x ] > 20.0 || p2[ x ] < 0.0 )? 0.0 : p2[ x ];
55 point2[ y ] = ( p2[ y ] > 20.0 || p2[ y ] < 0.0 )? 0.0 : p2[ y ];
56 point3[ x ] = ( p3[ x ] > 20.0 || p3[ x ] < 0.0 )? 0.0 : p3[ x ];
57 point3[ y ] = ( p3[ y ] > 20.0 || p3[ y ] < 0.0 )? 0.0 : p3[ y ];
58 point4[ x ] = ( p4[ x ] > 20.0 || p4[ x ] < 0.0 )? 0.0 : p4[ x ];
59 point4[ y ] = ( p4[ y ] > 20.0 || p4[ y ] < 0.0 )? 0.0 : p4[ y ];
60
61 // verify that points form a rectangle
62 if ( p1[ y ] == p2[ y ] && p1[ x ] ==
63 p4[ x ] && p2[ x ] == p3[ x ] && p3[ y ] == p4[ y ] )
64 {
65
66 perimeter();
67 area();
68 square();
69 }
70 else
71 cout << "Coordinates do not form a rectangle!\n";
72 }
73
74 void Rectangle::perimeter( void )
75 {
76 double l = fabs( point4[ 1 ] - point1[ 1 ] ),
77 w = fabs( point2[ 0 ] - point1[ 0 ] );
78
79 cout << setiosflags( ios::fixed | ios::showpoint )
80 << "length = " << setprecision( 1 ) << ( l > w ? l : w )
81 << '\t' << "width = " << ( l > w ? w : l )
82 << "\nThe perimeter is: " << 2 * ( w + l ) << '\n'
83 << resetiosflags( ios::fixed | ios::showpoint );
84 }
85
86 void Rectangle::area( void )
87 {
88 double l = fabs( point4[ 1 ] - point1[ 1 ] ),
89 w = fabs( point2[ 0 ] - point1[ 0 ] );
90
91 cout << setiosflags( ios::fixed | ios::showpoint )
92 << "The area is: " << setprecision( 1 ) << w * l
93 << resetiosflags( ios::fixed | ios::showpoint )
94 << "\n\n" ;
95 }
96
97 void Rectangle::square( void )
98 {
99 const int x = 0, y = 1; // added for clarity
100
101 if ( fabs( point4[ y ] - point1[ y ] ) ==
102 fabs( point2[ x ] - point1[ x ] ) )
103 cout << "The rectangle is a square.\n\n";
256 Classes and Data Abstraction Solutions Chapter 6
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
6.14 Modify the Rectangle class of Exercise 6.13 to include a draw function that displays the rectangle inside a 25-by-25
box enclosing the portion of the first quadrant in which the rectangle resides. Include a setFillCharacter function to specify
the character out of which the body of the rectangle will be drawn. Include a setPerimeterCharacter function to specify the
character that will be used to draw the border of the rectangle. If you feel ambitious, you might include functions to scale the size
of the rectangle, rotate it, and move it around within the designated portion of the first quadrant.
104 }
105 // driver for p6_13.cpp
106
107 #include "p6_13.h"
108
109 int main()
110 {
111 double w[ 2 ] = { 1.0, 1.0 }, x[ 2 ] = { 5.0, 1.0 },
112 y[ 2 ] = { 5.0, 3.0 }, z[ 2 ] = { 1.0, 3.0 },
113 j[ 2 ] = { 0.0, 0.0 }, k[ 2 ] = { 1.0, 0.0 },
114 m[ 2 ] = { 1.0, 1.0 }, n[ 2 ] = { 0.0, 1.0 },
115 v[ 2 ] = { 99.0, -2.3 };
116 Rectangle a( z, y, x, w ), b( j, k, m, n ),
117 c( w, x, m, n ), d( v, x, y, z );
118
119 return 0;
120 }
length = 4.0 width = 2.0
The perimeter is: 12.0
The area is: 8.0
length = 1.0 width = 1.0
The perimeter is: 4.0
The area is: 1.0
The rectangle is a square.
Coordinates do not form a rectangle!
Coordinates do not form a rectangle!
1// P6_14.H
2#ifndef P6_14_H
3#define P6_14_H
4
5class Rectangle {
6public:
7 Rectangle( double *, double *, double *, double *, char, char );
8 void setCoord( double *, double *, double *, double * );
9 void perimeter( void );
10 void area( void );
11 void draw( void );
12 void square( void );
13 void setFillCharacter( char c ) { fillChar = c; }
14 void setPerimeterCharacter( char c ) { periChar = c;}
15 bool isValid( void ) { return valid; }
16 void setValid( bool v ) { valid = v; }
17 private:
18 double point1[ 2 ];
19 double point2[ 2 ];
20 double point3[ 2 ];
Chapter 6 Classes and Data Abstraction Solutions 257
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
21 double point4[ 2 ];
22 char fillChar;
23 char periChar;
24 bool valid;
25 };
26
27 #endif
28 // P6_14M.cpp
29 // member function definitions for p6_14.cpp
30 #include <iostream>
31
32 using std::cout;
33 using std::ios;
34
35 #include <iomanip>
36
37 using std::setprecision;
38 using std::setiosflags;
39 using std::resetiosflags;
40
41 #include <cmath>
42
43 #include "p6_14.h"
44
45 Rectangle::Rectangle( double *a, double *b, double *c, double *d,
46 char x, char y )
47 {
48 setCoord( a, b, c, d );
49 setFillCharacter( x );
50 setPerimeterCharacter( y );
51 }
52
53 void Rectangle::setCoord( double *p1, double *p2,
54 double *p3, double *p4 )
55 {
56 // Arrangement of points
57 // p4.........p3
58 // . .
59 // . .
60 // p1.........p2
61
62 const int x = 0, y = 1; // added for clarity
63
64 // validate all points
65 point1[ x ] = ( p1[ x ] > 20.0 || p1[ x ] < 0.0 )? 0.0 : p1[ x ];
66 point1[ y ] = ( p1[ y ] > 20.0 || p1[ y ] < 0.0 )? 0.0 : p1[ y ];
67 point2[ x ] = ( p2[ x ] > 20.0 || p2[ x ] < 0.0 )? 0.0 : p2[ x ];
68 point2[ y ] = ( p2[ y ] > 20.0 || p2[ y ] < 0.0 )? 0.0 : p2[ y ];
69 point3[ x ] = ( p3[ x ] > 20.0 || p3[ x ] < 0.0 )? 0.0 : p3[ x ];
70 point3[ y ] = ( p3[ y ] > 20.0 || p3[ y ] < 0.0 )? 0.0 : p3[ y ];
71 point4[ x ] = ( p4[ x ] > 20.0 || p4[ x ] < 0.0 )? 0.0 : p4[ x ];
72 point4[ y ] = ( p4[ y ] > 20.0 || p4[ y ] < 0.0 )? 0.0 : p4[ y ];
73
74 // verify that points form a rectangle
75 if (point1[ y ] == point2[ y ] && point1[ x ] == point4[ x ] &&
76 point2[ x ] == point3[ x ] && point3[ y ] == point4[ y ]) {
77
78 perimeter();
79 area();
80 square();
258 Classes and Data Abstraction Solutions Chapter 6
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
81 setValid( true ); // valid set of points
82 }
83 else {
84 cout << "Coordinates do not form a rectangle!\n";
85 setValid( false ); // invalid set of points
86 }
87 }
88
89 void Rectangle::perimeter( void )
90 {
91 double l = fabs( point4[ 1 ] - point1[ 1 ] ),
92 w = fabs( point2[ 0 ] - point1[ 0 ] );
93
94 cout << setiosflags( ios::fixed | ios::showpoint )
95 << "length = " << setprecision( 1 ) << ( l > w ? l : w )
96 << "\twidth = " << ( l > w ? w : l )
97 << "\nThe perimeter is: " << 2 * ( w + l ) << '\n'
98 << resetiosflags( ios::fixed | ios::showpoint );
99 }
100 void Rectangle::area( void )
101 {
102 double l = fabs( point4[ 1 ] - point1[ 1 ] ),
103 w = fabs( point2[ 0 ] - point1[ 0 ] );
104
105 cout << setiosflags( ios::fixed | ios::showpoint )
106 << "The area is: " << setprecision( 1 ) << w * l
107 << resetiosflags( ios::fixed | ios::showpoint )
108 << "\n\n";
109 }
110
111 void Rectangle::square( void )
112 {
113 const int x = 0, y = 1; // added for clarity
114
115 if ( fabs( point4[ y ] - point1[ y ] ) == fabs( point2[ x ] - point1[ x ] ) )
116 cout << "The rectangle is a square.\n\n";
117 }
118
119 void Rectangle::draw( void )
120 {
121 for ( double y = 25.0; y >= 0.0; --y ) {
122 for ( double x = 0.0; x <= 25.0; ++x ) {
123 if ( ( point1[ 0 ] == x && point1[ 1 ] == y ) ||
124 ( point4[ 0 ] == x && point4[ 1 ] == y ) ) {
125
126 // print horizontal perimeter of rectangle
127 while ( x <= point2[ 0 ] ) {
128 cout << periChar;
129 ++x;
130 }
131
132 // print remainder of quadrant
133 cout << '.';
134 }
135 // prints vertical perimeter of rectangle
136 else if ( ( ( x <= point4[ 0 ] && x >= point1[ 0 ] ) ) &&
137 point4[ 1 ] >= y && point1[ 1 ] <= y ) {
138 cout << periChar;
139
140 // fill inside of rectangle
141 for ( x++; x < point2[ 0 ]; ) {
142 cout << fillChar;
Chapter 6 Classes and Data Abstraction Solutions 259
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
143 ++x;
144 }
145
146 cout << periChar;
147 }
148 else
149 cout << '.'; // print quadrant background
150 }
151
152 cout << '\n';
153 }
154 }
155 // driver for p6_14.cpp
156
157 #include "p6_14.h"
158
159 int main()
160 {
161 double xy1[ 2 ] = { 12.0, 12.0 }, xy2[ 2 ] = { 18.0, 12.0 },
162 xy3[ 2 ] = { 18.0, 20.0 }, xy4[ 2 ] = { 12.0, 20.0 };
163 Rectangle a( xy1, xy2, xy3, xy4, '?', '*' );
164
165 if ( a.isValid() )
166 a.draw();
167
168 return 0;
169 }
length = 8.0 width = 6.0
The perimeter is: 28.0
The area is: 48.0
..........................
..........................
..........................
............*******.......
............*?????*.......
............*?????*.......
............*?????*.......
............*?????*.......
............*?????*.......
............*?????*.......
............*?????*.......
............*******.......
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
..........................
260 Classes and Data Abstraction Solutions Chapter 6
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
6.15 Create a class HugeInteger that uses a 40-element array of digits to store integers as large as 40-digits each. Provide
member functions inputHugeInteger, outputHugeInteger, addHugeIntegers and substractHugeIntegers.
For comparing HugeInteger objects, provide functions isEqualTo, isNotEqualTo, isGreaterThan, isLessThan,
IsGreaterThanOrEqualTo and isLessThanOrEqualTo—each of these is a “predicate” function that simply returns
true if the relationship holds between the two huge integers and returns false if the relationship does not hold. Provide a pred-
icate function isZero. If you feel ambitious, also provide member functions multiplyHugeIntegers, di-
videHugeIntegers and modulusHugeIntegers.
6.16 Create a class TicTacToe that will enable you to write a complete program to play the game of tic-tac-toe. The class con-
tains as private data a 3-by-3 double array of integers. The constructor should initialize the empty board to all zeros. Allow two
human players. Wherever the first player moves, place a 1 in the specified square; place a 2 wherever the second player moves. Each
move must be to an empty square. After each move, determine if the game has been won or if the game is a draw. If you feel am-
bitious, modify your program so that the computer makes the moves for one of the players automatically. Also, allow the player t o
specify whether he or she wants to go first or second. If you feel exceptionally ambitious, develop a program that will play three-
dimensional tic-tac-toe on a 4-by-4-by-4 board (Caution: This is an extremely challenging project that could take many weeks of
effort!).
1// p6.16_H
2#ifndef P6_16_H
3#define P6_16_H
4
5class TicTacToe {
6private:
7 enum Status { WIN, DRAW, CONTINUE };
8 int board[ 3 ][ 3 ];
9public:
10 TicTacToe();
11 void makeMove( void );
12 void printBoard( void );
13 bool validMove( int, int );
14 bool xoMove( int );
15 Status gameStatus( void );
16 };
17
18 #endif
19 // P6_16M.cpp
20 // member function definitions for p6_16.cpp
21 #include <iostream>
22
23 using std::cout;
24 using std::cin;
25
26 #include <iomanip>
27
28 using std::setw;
29
30 #include "p6_16.h"
31
32 TicTacToe::TicTacToe()
33 {
34 for ( int j = 0; j < 3; ++j ) // initialize board
35 for ( int k = 0; k < 3; ++k )
36 board[ j ][ k ] = ' ';
37 }
38
39 bool TicTacToe::validMove( int r, int c )
40 {
41 return r >= 0 && r < 3 && c >= 0 && c < 3 && board[ r ][ c ] == ' ';
42 }
Chapter 6 Classes and Data Abstraction Solutions 261
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
43
44 // must specify that type Status is part of the TicTacToe class.
45 // See Chapter 21 for a discussion of namespaces.
46 TicTacToe::Status TicTacToe::gameStatus( void )
47 {
48 int a;
49
50 // check for a win on diagonals
51 if ( board[ 0 ][ 0 ] != ' ' && board[ 0 ][ 0 ] == board[ 1 ][ 1 ] &&
52 board[ 0 ][ 0 ] == board[ 2 ][ 2 ] )
53 return WIN;
54 else if ( board[ 2 ][ 0 ] != ' ' && board[ 2 ][ 0 ] ==
55 board[ 1 ][ 1 ] && board[ 2 ][ 0 ] == board[ 0 ][ 2 ] )
56 return WIN;
57
58 // check for win in rows
59 for ( a = 0; a < 3; ++a )
60 if ( board[ a ][ 0 ] != ' ' && board[ a ][ 0 ] ==
61 board[ a ][ 1 ] && board[ a ][ 0 ] == board[ a ][ 2 ] )
62 return WIN;
63
64 // check for win in columns
65 for ( a = 0; a < 3; ++a )
66 if ( board[ 0 ][ a ] != ' ' && board[ 0 ][ a ] ==
67 board[ 1 ][ a ] && board[ 0 ][ a ] == board[ 2 ][ a ] )
68 return WIN;
69
70 // check for a completed game
71 for ( int r = 0; r < 3; ++r )
72 for ( int c = 0; c < 3; ++c )
73 if ( board[ r ][ c ] == ' ' )
74 return CONTINUE; // game is not finished
75
76 return DRAW; // game is a draw
77 }
78
79 void TicTacToe::printBoard( void )
80 {
81 cout << " 0 1 2\n\n";
82
83 for ( int r = 0; r < 3; ++r ) {
84 cout << r;
85
86 for ( int c = 0; c < 3; ++c ) {
87 cout << setw( 3 ) << static_cast< char > ( board[ r ][ c ] );
88
89 if ( c != 2 )
90 cout << " |";
91 }
92
93 if ( r != 2 )
94 cout << "\n ____|____|____"
95 << "\n | | \n";
96 }
97
98 cout << "\n\n";
99 }
100
101 void TicTacToe::makeMove( void )
102 {
103 printBoard();
104
262 Classes and Data Abstraction Solutions Chapter 6
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
105 while ( true ) {
106 if ( xoMove( 'X' ) )
107 break;
108 else if ( xoMove( 'O' ) )
109 break;
110 }
111 }
112
113 bool TicTacToe::xoMove( int symbol )
114 {
115 int x, y;
116
117 do {
118 cout << "Player " << static_cast< char >( symbol )
119 << " enter move: ";
120 cin >> x >> y;
121 cout << '\n';
122 } while ( !validMove( x, y ) );
123
124 board[ x ][ y ] = symbol;
125 printBoard();
126 Status xoStatus = gameStatus();
127
128 if ( xoStatus == WIN ) {
129 cout << "Player " << static_cast< char >( symbol )
130 << " wins!\n";
131 return true;
132 }
133 else if ( xoStatus == DRAW ) {
134 cout << "Game is a draw.\n";
135 return true;
136 }
137 else // CONTINUE
138 return false;
139 }
140 // driver for p6_16.cpp
141 #include "p6_16.h"
142
143 int main()
144 {
145 TicTacToe g;
146 g.makeMove();
147
148 return 0;
149 }
Chapter 6 Classes and Data Abstraction Solutions 263
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
0 1 2
0 | |
____|____|____
| |
1 | |
____|____|____
| |
2 | |
Player X enter move: 2 0
0 1 2
0 | |
____|____|____
| |
1 | |
____|____|____
| |
2 X | |
Player O enter move: 2 2
0 1 2
0 | |
____|____|____
| |
1 | |
____|____|____
| |
2 X | | O
Player X enter move: 1 1
...
Player X enter move: 0 2
0 1 2
0 | | X
____|____|____
| |
1 | X | O
____|____|____
| |
2 X | | O
Player X wins!Player X wins!
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
7
Classes: Part II
Solutions
Solutions
7.3 Compare and contrast dynamic memory allocation using the C++ operators new and delete, with dynamic memory al-
location using the C Standard Library functions malloc and free.
ANS: In C, dynamic memory allocation requires function calls to malloc and free. Also, malloc must be told the
exact number of bytes to allocate (normally this is accomplished with the sizeof operator), then it returns a void pointer.
C++ uses operators new and delete. The new operator automatically determines the number of bytes to allocate and
returns a pointer to the appropriate type. The delete operator guarantees a call to the destructor for the object(s) being
deleted.
7.4 Explain the notion of friendship in C++. Explain the negative aspects of friendship as described in the text.
ANS: Functions that are declared as friends of a class have access to that class’s private and protected members.
Some people in the object-oriented programming community prefer not to use friend functions because they break the
encapsulation of a class—i.e., they allow direct access to a class’s impementation details that are supposed to be hidden.
7.5 Can a correct Time class definition include both of the following constructors? If not, explain why not.
Time( int h = 0, int m = 0, int s = 0 );
Time();
ANS: No, because there is ambiguity between the two constructors. When a call is made to the default constructor, the
compiler cannot determine which one to use because they can both be called with no arguments.
7.6 What happens when a return type, even void, is specified for a constructor or destructor?
ANS: A compiler syntax error occurs. No return types can be specified for constructors.
7.7 Create a Date class with the following capabilities:
a) Output the date in multiple formats such as
DDD YYYY
MM/DD/YY
June 14, 1992
b) Use overloaded constructors to create Date objects initialized with dates of the formats in part (a).
c) Create a Date constructor that reads the system date using the standard library functions of the ctime header and sets
the Date members.
In Chapter 8, we will be able to create operators for testing the equality of two dates and for comparing dates to determine if one
date is prior to, or after, another.
Chapter 7 Classes: Part II Solutions 265
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1// P7_07.H
2#ifndef p7_07_H
3#define p7_07_H
4
5#include <ctime>
6#include <cstring>
7
8class Date {
9public:
10 Date();
11 Date( int, int );
12 Date( int, int, int );
13 Date( char *, int, int );
14 void setMonth( int );
15 void setDay( int );
16 void setYear( int );
17 void printDateSlash( void ) const;
18 void printDateMonth( void ) const;
19 void printDateDay( void ) const;
20 const char *monthName( void ) const;
21 bool leapYear( void ) const;
22 int daysOfMonth( void ) const;
23 void convert1( int );
24 int convert2( void ) const;
25 void convert3( const char * const );
26 const char *monthList( int ) const;
27 int days( int ) const;
28 private:
29 int day;
30 int month;
31 int year;
32 };
33
34 #endif
35 // P7_07M.cpp
36 // member function definitions for p7_07.cpp
37 #include <iostream>
38
39 using std::cout;
40
41 #include <cstring>
42 #include <ctime>
43
44 #include "p7_07.h"
45
46 // Date constructor that uses functions from ctime
47 Date::Date()
48 {
49 struct tm *ptr; // pointer of type struct tm
50 // which holds calendar time components
51 time_t t = time( 0 ); // determine the current calendar time
52 // which is assigned to timePtr
53 ptr = localtime( &t ); // convert the current calendar time
54 // pointed to by timePtr into
55 // broken down time and assign it to ptr
56 day = ptr->tm_mday; // broken down day of month
57 month = 1 + ptr->tm_mon; // broken down month since January
266 Classes: Part II Solutions Chapter 7
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
58 year = ptr->tm_year + 1900; // broken down year since 1900
59 }
60
61 // Date constructor that uses day of year and year
62 Date::Date( int ddd, int yyyy )
63 {
64 setYear( yyyy );
65 convert1( ddd ); // convert to month and day
66 }
67
68 // Date constructor that uses month, day and year
69 Date::Date( int mm, int dd, int yy )
70 {
71 setYear( yy + 1900 );
72 setMonth( mm );
73 setDay( dd );
74 }
75
76 // Date constructor that uses month name, day and year
77 Date::Date( char *mPtr, int dd, int yyyy )
78 {
79 setYear( yyyy );
80 convert3( mPtr );
81 setDay( dd );
82 }
83
84 // Set the day
85 void Date::setDay( int d )
86 { day = d >= 1 && d <= daysOfMonth() ? d : 1; }
87
88 // Set the month
89 void Date::setMonth( int m ) { month = m >= 1 && m <= 12 ? m : 1; }
90
91 // Set the year
92 void Date::setYear( int y ) { year = y >= 1900 && y <= 1999 ? y : 1900; }
93
94 // Print Date in the form: mm/dd/yyyy
95 void Date::printDateSlash( void ) const
96 { cout << month << '/' << day << '/' << year << '\n'; }
97
98 // Print Date in the form: monthname dd, yyyy
99 void Date::printDateMonth( void ) const
100 { cout << monthName() << ' ' << day << ", " << year << '\n'; }
101
102 // Print Date in the form: ddd yyyy
103 void Date::printDateDay( void ) const
104 { cout << convert2() << ' ' << year << '\n'; }
105
106 // Return the month name
107 const char *Date::monthName( void ) const { return monthList( month - 1 ); }
108
109 // Return the number of days in the month
110 int Date::daysOfMonth( void ) const
111 { return leapYear() && month == 2 ? 29 : days( month ); }
112
113 // Test for a leap year
114 bool Date::leapYear( void ) const
115 {
116 if ( year % 400 == 0 || ( year % 4 == 0 && year % 100 != 0 ) )
117 return true;
118 else
119 return false;
Chapter 7 Classes: Part II Solutions 267
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
120 }
121
122 // Convert ddd to mm and dd
123 void Date::convert1( int ddd ) // convert to mm / dd / yyyy
124 {
125 int dayTotal = 0;
126
127 if ( ddd < 1 || ddd > 366 ) // check for invalid day
128 ddd = 1;
129
130 setMonth( 1 );
131
132 for ( int m = 1; m < 13 && ( dayTotal + daysOfMonth() ) < ddd; ++m ) {
133 dayTotal += daysOfMonth();
134 setMonth( m + 1 );
135 }
136
137 setDay( ddd - dayTotal );
138 setMonth( m );
139 }
140
141 // Convert mm and dd to ddd
142 int Date::convert2( void ) const // convert to a ddd yyyy format
143 {
144 int ddd = 0;
145
146 for ( int m = 1; m < month; ++m )
147 ddd += days( m );
148
149 ddd += day;
150 return ddd;
151 }
152
153 // Convert from month name to month number
154 void Date::convert3( const char * const mPtr ) // convert to mm / dd / yyyy
155 {
156 bool flag = false;
157
158 for ( int subscript = 0; subscript < 12; ++subscript )
159 if ( !strcmp( mPtr, monthList( subscript ) ) ) {
160 setMonth( subscript + 1 );
161 flag = true; // set flag
162 break; // stop checking for month
163 }
164
165 if ( !flag )
166 setMonth( 1 ); // invalid month default is january
167 }
168
169 // Return the name of the month
170 const char *Date::monthList( int mm ) const
171 {
172 char *months[] = { "January", "February", "March", "April", "May",
173 "June", "July", "August", "September", "October",
174 "November", "December" };
175
176 return months[ mm ];
177 }
178
179 // Return the days in the month
180 int Date::days( int m ) const
181 {
268 Classes: Part II Solutions Chapter 7
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
7.8 Create a SavingsAccount class. Use a static data member to contain the annualInterestRate for each of the
savers. Each member of the class contains a private data member savingsBalance indicating the amount the saver currently
has on deposit. Provide a calculateMonthlyInterest member function that calculates the monthly interest by multiplying
the balance by annualInterestRate divided by 12; this interest should be added to savingsBalance. Provide a stat-
182 const int monthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
183
184 return monthDays[ m - 1 ];
185 }
186 // driver for p7_07.cpp
187 #include <iostream>
188
189 using std::cout;
190 using std::endl;
191
192 #include "p7_07.h"
193
194 int main()
195 {
196 Date d1( 7, 4, 98 ), d2( 86, 1999 ),
197 d3, d4( "September", 1, 1998 );
198
199 d1.printDateSlash(); // format m / dd / yy
200 d2.printDateSlash();
201 d3.printDateSlash();
202 d4.printDateSlash();
203 cout << '\n';
204
205 d1.printDateDay(); // format ddd yyyy
206 d2.printDateDay();
207 d3.printDateDay();
208 d4.printDateDay();
209 cout << '\n';
210
211 d1.printDateMonth(); // format "month" d, yyyy
212 d2.printDateMonth();
213 d3.printDateMonth();
214 d4.printDateMonth();
215 cout << endl;
216
217 return 0;
218 }
7/4/1998
3/27/1999
6/16/2000
9/1/1998
185 1998
86 1999
167 2000
244 1998
July 4, 1998
March 27, 1999
June 16, 2000
September 1, 1998
Chapter 7 Classes: Part II Solutions 269
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
ic member function modifyInterestRate that sets the static annualInterestRate to a new value. Write a driver
program to test class SavingsAccount. Instantiate two different savingsAccount objects, saver1 and saver2, with bal-
ances of $2000.00 and $3000.00, respectively. Set annualInterestRate to 3%, then calculate the monthly interest and print
the new balances for each of the savers. Then set the annualInterestRate to 4% and calculate the next month’s interest and
print the new balances for each of the savers.
1// P7_08.H
2#ifndef P7_08_H
3#define P7_08_H
4
5class SavingsAccount {
6public:
7 SavingsAccount( double b ) { savingsBalance = b >= 0 ? b : 0; }
8 void calculateMonthlyInterest( void );
9 static void modifyInterestRate( double );
10 void printBalance( void ) const;
11 private:
12 double savingsBalance;
13 static double annualInterestRate;
14 };
15
16 #endif
17 // P7.08M.cpp
18 // Member function defintions for p7_08.cpp
19 #include "p7_08.h"
20 #include <iostream>
21
22 using std::cout;
23 using std::ios;
24
25 #include <iomanip>
26
27 using std::setprecision;
28 using std::setiosflags;
29 using std::resetiosflags;
30
31 // initialize static data member
32 double SavingsAccount::annualInterestRate = 0.0;
33
34 void SavingsAccount::calculateMonthlyInterest( void )
35 { savingsBalance += savingsBalance * ( annualInterestRate / 12.0 ); }
36
37 void SavingsAccount::modifyInterestRate( double i )
38 { annualInterestRate = ( i >= 0 && i <= 1.0 ) ? i : 0.03; }
39
40 void SavingsAccount::printBalance( void ) const
41 {
42 cout << setiosflags( ios::fixed | ios::showpoint )
43 << '$' << setprecision( 2 ) << savingsBalance
44 << resetiosflags( ios::fixed | ios::showpoint );
45 }
46 // driver for p7_08.cpp
47 #include <iostream>
48
49 using std::cout;
50 using std::endl;
51
270 Classes: Part II Solutions Chapter 7
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
52 #include <iomanip>
53
54 using std::setw;
55
56 #include "p7_08.h"
57
58 int main()
59 {
60 SavingsAccount saver1( 2000.0 ), saver2( 3000.0 );
61
62 SavingsAccount::modifyInterestRate( .03 );
63
64 cout << "\nOutput monthly balances for one year at .03"
65 << "\nBalances: Saver 1 ";
66 saver1.printBalance();
67 cout << "\tSaver 2 ";
68 saver2.printBalance();
69
70 for ( int month = 1; month <= 12; ++month ) {
71 saver1.calculateMonthlyInterest();
72 saver2.calculateMonthlyInterest();
73
74 cout << "\nMonth" << setw( 3 ) << month << ": Saver 1 ";
75 saver1.printBalance();
76 cout << "\tSaver 2 ";
77 saver2.printBalance();
78 }
79
80 SavingsAccount::modifyInterestRate( .04 );
81 saver1.calculateMonthlyInterest();
82 saver2.calculateMonthlyInterest();
83 cout << "\nAfter setting interest rate to .04"
84 << "\nBalances: Saver 1 ";
85 saver1.printBalance();
86 cout << "\tSaver 2 ";
87 saver2.printBalance();
88 cout << endl;
89
90 return 0;
91 }
Output monthly balances for one year at .03
Balances: Saver 1 $2000.00 Saver 2 $3000.00
Month 1: Saver 1 $2005.00 Saver 2 $3007.50
Month 2: Saver 1 $2010.01 Saver 2 $3015.02
Month 3: Saver 1 $2015.04 Saver 2 $3022.56
Month 4: Saver 1 $2020.08 Saver 2 $3030.11
Month 5: Saver 1 $2025.13 Saver 2 $3037.69
Month 6: Saver 1 $2030.19 Saver 2 $3045.28
Month 7: Saver 1 $2035.26 Saver 2 $3052.90
Month 8: Saver 1 $2040.35 Saver 2 $3060.53
Month 9: Saver 1 $2045.45 Saver 2 $3068.18
Month 10: Saver 1 $2050.57 Saver 2 $3075.85
Month 11: Saver 1 $2055.69 Saver 2 $3083.54
Month 12: Saver 1 $2060.83 Saver 2 $3091.25
After setting interest rate to .04
Balances: Saver 1 $2067.70 Saver 2 $3101.55
Chapter 7 Classes: Part II Solutions 271
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
7.9 Create a class called IntegerSet. Each object of class IntegerSet can hold integers in the range 0 through 100. A
set is represented internally as an array of ones and zeros. Array element a[ i ] is 1 if integer i is in the set. Array element a[ j ]
is 0 if integer j is not in the set. The default constructor initializes a set to the so-called “empty set,” i.e., a set whose array represen-
tation contains all zeros.
Provide member functions for the common set operations. For example, provide a unionOfIntegerSets member func-
tion that creates a third set which is the set-theoretic union of two existing sets (i.e., an element of the third set’s array is set to 1 if
that element is 1 in either or both of the existing sets, and an element of the third set’s array is set to 0 if that element is 0 in each of
the existing sets).
Provide an intersectionOfIntegerSets member function that creates a third set which is the set-theoretic intersec-
tion of two existing sets (i.e., an element of the third set’s array is set to 0 if that element is 0 in either or both of the existing sets,
and an element of the third set’s array is set to 1 if that element is 1 in each of the existing sets).
Provide an insertElement member function that inserts a new integer k into a set (by setting a[k] to 1). Provide a
deleteElement member function that deletes integer m (by setting a[m] to 0).
Provide a setPrint member function that prints a set as a list of numbers separated by spaces. Print only those elements
that are present in the set (i.e., their position in the array has a value of 1). Print --- for an empty set.
Provide an isEqualTo member function that determines if two sets are equal.
Provide an additional constructor to take five integer arguments which can be used to initialize a set object. If you want to pro-
vide fewer than five elements in the set, use default arguments of
-1 for the others.
Now write a driver program to test your IntegerSet class. Instantiate several IntegerSet objects. Test that all your
member functions work properly.
1P7_09.H
2#ifndef P7_09_H
3#define P7_09_H
4
5class IntegerSet {
6public:
7 IntegerSet() { emptySet(); }
8 IntegerSet( int, int = -1, int = -1, int = -1, int = -1 );
9 IntegerSet unionOfIntegerSets( const IntegerSet& );
10 IntegerSet intersectionOfIntegerSets( const IntegerSet& );
11 void emptySet( void );
12 void inputSet( void );
13 void insertElement( int );
14 void deleteElement( int );
15 void setPrint( void ) const;
16 bool isEqualTo( const IntegerSet& ) const;
17 private:
18 int set[ 101 ]; // range of 0 - 100
19 int validEntry( int x ) const { return x >= 0 && x <= 100; }
20 };
21
22 #endif
23 //P7_09M.cpp
24 //Member function definitions for p7_09.cpp
25 #include <iostream>
26
27 using std::cout;
28 using std::cin;
29 using std::cerr;
30
31 #include <iomanip>
32
272 Classes: Part II Solutions Chapter 7
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
33 using std::setw;
34
35 #include "p7_09.h"
36
37 IntegerSet::IntegerSet( int a, int b, int c, int d, int e )
38 {
39 emptySet();
40
41 if ( validEntry( a ) )
42 insertElement( a );
43
44 if ( validEntry( b ) )
45 insertElement( b );
46
47 if ( validEntry( c ) )
48 insertElement( c );
49
50 if ( validEntry( d ) )
51 insertElement( d );
52
53 if ( validEntry( e ) )
54 insertElement( e );
55 }
56
57 void IntegerSet::emptySet( void )
58 {
59 for ( int y = 0; y < 101; ++y )
60 set[ y ] = 0;
61 }
62
63 void IntegerSet::inputSet( void )
64 {
65 int number;
66
67 do {
68 cout << "Enter an element (-1 to end): ";
69 cin >> number;
70
71 if ( validEntry( number ) )
72 set[ number ] = 1;
73 else if ( number != -1 )
74 cerr << "Invalid Element\n";
75 } while ( number != -1 );
76
77 cout << "Entry complete\n";
78 }
79
80 void IntegerSet::setPrint( void ) const
81 {
82 int x;
83 bool empty = true; // assume set is empty
84
85 cout << '{';
86
87 for (int u = 0; u < 101; ++u )
88 if ( set[ u ] ) {
89 cout << setw( 4 ) << u << ( x % 10 == 0 ? "\n" : "" );
90 empty = false; // set is not empty
91 ++x;
92 }
93
94 if ( empty )
Chapter 7 Classes: Part II Solutions 273
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
95 cout << setw( 4 ) << "---"; // display an empty set
96
97 cout << setw( 4 ) << "}" << '\n';
98 }
99
100 IntegerSet IntegerSet::unionOfIntegerSets( const IntegerSet &r )
101 {
102 IntegerSet temp;
103
104 for ( int n = 0; n < 101; ++n )
105 if ( set[ n ] == 1 || r.set[ n ] == 1 )
106 temp.set[ n ] = 1;
107
108 return temp;
109 }
110
111 IntegerSet IntegerSet::intersectionOfIntegerSets( const IntegerSet &r )
112 {
113 IntegerSet temp;
114
115 for ( int w = 0; w < 101; ++w )
116 if ( set[ w ] == 1 && r.set[ w ] == 1 )
117 temp.set[ w ] = 1;
118
119 return temp;
120 }
121
122 void IntegerSet::insertElement( int k )
123 {
124 if ( validEntry( k ) )
125 set[ k ] = 1;
126 else
127 cerr << "Invalid insert attempted!\n";
128 }
129
130 void IntegerSet::deleteElement( int m )
131 {
132 if ( validEntry( m ) )
133 set[ m ] = 0;
134 else
135 cerr << "Invalid delete attempted!\n";
136 }
137
138 bool IntegerSet::isEqualTo( const IntegerSet &r ) const
139 {
140 for ( int v = 0; v < 101; ++v )
141 if ( set[ v ] != r.set[ v ] )
142 return false; // sets are not-equal
143
144 return true; // sets are equal
145 }
146 // driver for p7_09.cpp
147 #include <iostream>
148
149 using std::cout;
150 using std::endl;
151
152 #include "p7_09.h"
153
154 int main()
274 Classes: Part II Solutions Chapter 7
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
155 {
156
157 IntegerSet a, b, c, d, e( 8, 5, 7 );
158
159 cout << "Enter set A:\n";
160 a.inputSet();
161 cout << "\nEnter set B:\n";
162 b.inputSet();
163 c = a.unionOfIntegerSets( b );
164 d = a.intersectionOfIntegerSets( b );
165 cout << "\nUnion of A and B is:\n";
166 c.setPrint();
167 cout << "Intersection of A and B is:\n";
168 d.setPrint();
169
170 if ( a.isEqualTo( b ) )
171 cout << "Set A is equal to set B\n";
172 else
173 cout << "Set A is not equal to set B\n";
174
175 cout << "\nInserting 77 into set A...\n";
176 a.insertElement( 77 );
177 cout << "Set A is now:\n";
178 a.setPrint();
179
180 cout << "\nDeleting 77 from set A...\n";
181 a.deleteElement( 77 );
182 cout << "Set A is now:\n";
183 a.setPrint();
184
185 cout << "\nSet e is:\n";
186 e.setPrint();
187
188 cout << endl;
189
190 return 0;
191 }
Chapter 7 Classes: Part II Solutions 275
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
7.10 It would be perfectly reasonable for the Time class of Fig. 7.8 to represent the time internally as the number of seconds
since midnight rather than the three integer values hour, minute and second. Clients could use the same public methods and
get the same results. Modify the Time class of Fig. 7.8 to implement the Time as the number of seconds since midnight and show
that there is no visible change in functionality to the clients of the class.
Enter set A:
Enter an element (-1 to end): 1
Enter an element (-1 to end): 2
Enter an element (-1 to end): 3
Enter an element (-1 to end): 4
Enter an element (-1 to end): -1
Entry complete
Enter set B:
Enter an element (-1 to end): 3
Enter an element (-1 to end): 4
Enter an element (-1 to end): 5
Enter an element (-1 to end): 9
Enter an element (-1 to end): 22
Enter an element (-1 to end): -1
Entry complete
Union of A and B is:
{ 1 2 3 4 5 9 22 }
Intersection of A and B is:
{ 3 4 }
Set A is not equal to set B
Inserting 77 into set A...
Set A is now:
{ 1 2 3 4 77 }
Deleting 77 from set A...
Set A is now:
{ 1 2 3 4 }
Set e is:
{ 5 7 8 }
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
8
Operator
Overloading
Solutions
Solutions
8.6 Give as many examples as you can of operator overloading implicit in C++. Give a reasonable example of a situation in
which you might want to overload an operator explicitly in C++.
ANS: In C, the operators +, -, *, and & are overloaded. The context of these operators determines how they are used. It
can be argued that the arithmetic operators are all overloaded, because they can be used to perform operations on more than
one type of data. In C++, the same operators as in C are overloaded, as well as << and >>.
8.7 The C++ operators that cannot be overloaded are , , , and .
ANS: sizeof, ., ?:, .*, and ::.
8.8 String concatenation requires two operands—the two strings that are to be concatenated. In the text we showed how to im-
plement an overloaded concatenation operator that concatenates the second String object to the right of the first String object,
thus modifying the first String object. In some applications, it is desirable to produce a concatenated String object without
modifying the String arguments. Implement operator+ to allow operations such as
string1 = string2 + string3;
1// P8_08.H
2#ifndef p8_08_H
3#define p8_08_H
4
5#include <cstring>
6#include <cassert>
7
8class String {
9 friend ostream &operator<<( ostream &output, const String &s );
10 public:
11 String( const char * const = "" ); // conversion constructor
12 String( const String & ); // copy constructor
13 ~String(); // destructor
14 const String &operator=( const String & );
15 String operator+( const String & );
16 private:
17 char *sPtr;
18 int length;
19 };
Chapter 8 Overloading Solutions 277
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
20
21 #endif
22 // P8_08M.cpp
23 // member function definitions for p8_08.cpp
24 // class String
25 #include <iostream>
26
27 using std::cout;
28 using std::ostream;
29
30
31 #include <cstring>
32 #include "p8_08.h"
33
34 // Conversion constructor: Convert a char * to String
35 String::String( const char * const zPtr )
36 {
37 length = strlen( zPtr ); // compute length
38 sPtr = new char[ length + 1 ]; // allocate storage
39 assert( sPtr != 0 ); // terminate if memory not allocated
40 strcpy( sPtr, zPtr ); // copy literal to object
41 }
42
43 // Copy constructor
44 String::String( const String &copy )
45 {
46 length = copy.length; // copy length
47 sPtr = new char[ length + 1 ]; // allocate storage
48 assert( sPtr != 0 ); // ensure memory allocated
49 strcpy( sPtr, copy.sPtr ); // copy string
50 }
51
52 // Destructor
53 String::~String() { delete [] sPtr; } // reclaim string
54
55 // Overloaded = operator; avoids self assignment
56 const String &String::operator=( const String &right )
57 {
58 if ( &right != this ) { // avoid self assignment
59 delete [] sPtr; // prevents memory leak
60 length = right.length; // new String length
61 sPtr = new char[ length + 1 ]; // allocate memory
62 assert( sPtr != 0 ); // ensure memory allocated
63 strcpy( sPtr, right.sPtr ); // copy string
64 }
65 else
66 cout << "Attempted assignment of a String to itself\n";
67
68 return *this; // enables concatenated assignments
69 }
70
71
72 // Concatenate right operand and this object and
73 // store in temp object.
74 String String::operator+( const String &right )
75 {
76 String temp;
77
78 temp.length = length + right.length;
79 temp.sPtr = new char[ temp.length + 1 ]; // create space
278 Overloading Solutions Chapter 8
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
8.9 (Ultimate operator overloading exercise) To appreciate the care that should go into selecting operators for overloading, list
each of C++'s overloadable operators, and for each, list a possible meaning (or several, if appropriate) for each of several classes
you have studied in this course. We suggest you try:
a) Array
b) Stack
c) String
After doing this, comment on which operators seem to have meaning for a wide variety of classes. Which operators seem to be of
little value for overloading? Which operators seem ambiguous?
8.10 Now work the process described in the previous problem in reverse. List each of C++'s overloadable operators. For each,
list what you feel is perhaps the “ultimate operation” the operator should be used to represent. If there are several excellent opera-
tions, list them all.
8.11 (Project) C++ is an evolving language, and new languages are always being developed. What additional operators would
you recommend adding to C++ or to a future language like C++ that would support both procedural programming and object-ori-
ented programming? Write a careful justification. You might consider sending your suggestions to the ANSI C++ Committee or the
newsgroup comp.std.c++.
8.12 One nice example of overloading the function call operator () is to allow the more common form of double-array sub-
scripting. Instead of saying
80 assert( sPtr != 0 ); // terminate if memory not allocated
81 strcpy( temp.sPtr, sPtr ); // left part of new String
82 strcat( temp.sPtr, right.sPtr ); // right part of new String
83 return temp; // enables concatenated calls
84 }
85 ostream & operator<<( ostream &output, const String &s )
86 {
87 output << s.sPtr;
88 return output; // enables concatenation
89 }
90 // driver for p8_08.cpp
91 #include <iostream>
92
93 using std::cout;
94 using std::endl;
95 using std::ostream;
96
97 // Overloaded output operator
98
99
100 #include "p8_08.h"
101
102 int main()
103 {
104 String string1, string2( "The date is" );
105 String string3( " August 1, 1993" );
106
107 cout << "string1 = string2 + string3\n";
108 string1 = string2 + string3;
109 cout << string1 << " = " << string2 << " + "
110 << string3 << endl;
111
112 return 0;
113 }
string1 = string2 + string3
The date is August 1, 1993 = The date is + August 1, 1993
Chapter 8 Overloading Solutions 279
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
chessBoard[ row ][ column ]
for an array of objects, overload the function call operator to allow the alternate form
chessBoard( row, column )
8.13 Create a class DoubleSubscriptedArray that has similar features to class Array in Fig. 8.4. At construction time,
the class should be able to create an array of any number of rows and any number of columns. The class should supply opera-
tor() to perform double-subscripting operations. For example, in a 3-by-5 DoubleSubscriptedArray called a, the user
could write a( 1, 3 ) to access the element at row 1 and column 3. Remember that operator() can receive any number of
arguments (see class String in Fig. 18.5 for an example of operator()). The underlying representation of the double-sub-
1// P8_12.H
2#ifndef P8_12_H
3#define P8_12_H
4
5class CallOperator {
6public:
7 CallOperator();
8 int operator()( int, int ); // overloaded function call operator
9private:
10 int chessBoard[ 8 ][ 8 ];
11 };
12
13 #endif
14 // P8_12M.CPP
15 // member function definitions for p8_12.cpp
16 #include "p8_12.h"
17
18 CallOperator::CallOperator()
19 {
20 for ( int loop = 0; loop < 8; ++loop )
21 for ( int loop2 = 0; loop2 < 8; ++loop2 )
22 chessBoard[ loop ][ loop2 ] = loop2;
23 }
24
25 int CallOperator::operator()( int r, int c ) { return chessBoard[ r ][ c ]; }
26 // driver for p8_12.cpp
27 #include <iostream>
28
29 using std::cout;
30 using std::endl;
31
32 #include "p8_12.h"
33
34 int main()
35 {
36 CallOperator board;
37
38 cout << "board[2][5] is " << board( 2, 5 ) << endl;
39
40 return 0;
41 }
board[2][5] is 5
280 Overloading Solutions Chapter 8
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
scripted array should be a single-subscripted array of integers with rows * columns number of elements. Function operator()
should perform the proper pointer arithmetic to access each element of the array. There should be two versions of operator()
one that returns int & so an element of a DoubleSubscriptedArray can be used as an lvalue and one that returns const
int & so an element of a const DoubleSubscriptedArray can be used as an rvalue. The class should also provide the fol-
lowing operators: ==, !=, =, << (for outputting the array in row and column format) and >> (for inputting the entire array contents).
8.14 Overload the subscript operator to return the largest element of a collection, the second largest, the third largest, etc.
8.15 Consider class Complex shown in Fig. 8.7. The class enables operations on so-called complex numbers. These are num-
bers of the form realPart + imaginaryPart * i where i has the value:
a) Modify the class to enable input and output of complex numbers through the overloaded >> and << operators, respec-
tively (you should remove the print function from the class).
b) Overload the multiplication operator to enable multiplication of two complex numbers as in algebra.
c) Overload the == and != operators to allow comparisons of complex numbers
1
1// Fig. 8.7: complex1.h
2// Definition of class Complex
3#ifndef COMPLEX1_H
4#define COMPLEX1_H
5
6class Complex {
7public:
8 Complex( double = 0.0, double = 0.0 ); // constructor
9 Complex operator+( const Complex & ) const; // addition
10 Complex operator-( const Complex & ) const; // subtraction
11 const Complex &operator=( const Complex & ); // assignment
12 void print() const; // output
13 private:
14 double real; // real part
15 double imaginary; // imaginary part
16 };
17
18 #endif
19 // Fig. 8.7: complex1.cpp
20 // Member function definitions for class Complex
21 #include <iostream>
22
23 using std::cout;
24
25 #include "complex1.h"
26
27 // Constructor
28 Complex::Complex( double r, double i )
29 : real( r ), imaginary( i ) { }
30
31 // Overloaded addition operator
32 Complex Complex::operator+( const Complex &operand2 ) const
33 {
34 return Complex( real + operand2.real,
35 imaginary + operand2.imaginary );
36 }
37
38 // Overloaded subtraction operator
39 Complex Complex::operator-( const Complex &operand2 ) const
40 {
41 return Complex( real - operand2.real,
Chapter 8 Overloading Solutions 281
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
42 imaginary - operand2.imaginary );
43 }
44
45 // Overloaded = operator
46 const Complex& Complex::operator=( const Complex &right )
47 {
48 real = right.real;
49 imaginary = right.imaginary;
50 return *this; // enables cascading
51 }
52
53 // Display a Complex object in the form: (a, b)
54 void Complex::print() const
55 { cout << '(' << real << ", " << imaginary << ')'; }
56 // Fig. 8.7: fig08_07.cpp
57 // Driver for class Complex
58 #include <iostream>
59
60 using std::cout;
61 using std::endl;
62
63 #include "complex1.h"
64
65 int main()
66 {
67 Complex x, y( 4.3, 8.2 ), z( 3.3, 1.1 );
68
69 cout << "x: ";
70 x.print();
71 cout << "\ny: ";
72 y.print();
73 cout << "\nz: ";
74 z.print();
75
76 x = y + z;
77 cout << "\n\nx = y + z:\n";
78 x.print();
79 cout << " = ";
80 y.print();
81 cout << " + ";
82 z.print();
83
84 x = y - z;
85 cout << "\n\nx = y - z:\n";
86 x.print();
87 cout << " = ";
88 y.print();
89 cout << " - ";
90 z.print();
91 cout << endl;
92
93 return 0;
94 }
282 Overloading Solutions Chapter 8
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Solution:
1// P8_15.H
2#ifndef P8_15_H
3#define P8_15_H
4#include <iostream>
5
6using std::ostream;
7using std::istream;
8
9class Complex {
10 friend ostream &operator<<( ostream &, const Complex & );
11 friend istream &operator>>( istream &, Complex & );
12 public:
13 Complex( double = 0.0, double = 0.0 ); // constructor
14 Complex operator+( const Complex& ) const; // addition
15 Complex operator-( const Complex& ) const; // subtraction
16 Complex operator*( const Complex& ) const; // multiplication
17 Complex& operator=( const Complex& ); // assignment
18 bool operator==( const Complex& ) const;
19 bool operator!=( const Complex& ) const;
20 private:
21 double real; // real part
22 double imaginary; // imaginary part
23 };
24
25 #endif
26 // P8_15M.cpp
27 // member function definitions for p8_15.cpp
28 #include "p8_15.h"
29 #include <iostream>
30
31 using std::ostream;
32 using std::istream;
33
34 // Constructor
35 Complex::Complex( double r, double i )
36 {
37 real = r;
38 imaginary = i;
39 }
40
41 // Overloaded addition operator
42 Complex Complex::operator+( const Complex &operand2 ) const
43 {
44 Complex sum;
45
46 sum.real = real + operand2.real;
47 sum.imaginary = imaginary + operand2.imaginary;
48 return sum;
49 }
50
51 // Overloaded subtraction operator
52 Complex Complex::operator-( const Complex &operand2 ) const
53 {
54 Complex diff;
55
Chapter 8 Overloading Solutions 283
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
56 diff.real = real - operand2.real;
57 diff.imaginary = imaginary - operand2.imaginary;
58 return diff;
59 }
60
61 // Overloaded multiplication operator
62 Complex Complex::operator*( const Complex &operand2 ) const
63 {
64 Complex times;
65
66 times.real = real * operand2.real + imaginary * operand2.imaginary;
67 times.imaginary = real * operand2.imaginary + imaginary * operand2.real;
68 return times;
69 }
70
71 // Overloaded = operator
72 Complex& Complex::operator=( const Complex &right )
73 {
74 real = right.real;
75 imaginary = right.imaginary;
76 return *this; // enables concatenation
77 }
78
79 bool Complex::operator==( const Complex &right ) const
80 { return right.real == real && right.imaginary == imaginary ? true : false; }
81
82 bool Complex::operator!=( const Complex &right ) const
83 { return !( *this == right ); }
84
85 ostream& operator<<( ostream &output, const Complex &complex )
86 {
87 output << complex.real << " + " << complex.imaginary << 'i';
88 return output;
89 }
90
91 istream& operator>>( istream &input, Complex &complex )
92 {
93 input >> complex.real;
94 input.ignore( 3 ); // skip spaces and +
95 input >> complex.imaginary;
96 input.ignore( 2 );
97
98 return input;
99 }
100 // driver for p8_15.cpp
101 #include <iostream>
102
103 using std::cout;
104 using std::cin;
105
106 #include "p8_15.h"
107
108 int main()
109 {
110 Complex x, y( 4.3, 8.2 ), z( 3.3, 1.1 ), k;
111
112 cout << "Enter a complex number in the form: a + bi\n? ";
113 cin >> k;
114
115 cout << "x: " << x << "\ny: " << y << "\nz: " << z << "\nk: "
284 Overloading Solutions Chapter 8
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
8.16 A machine with 32-bit integers can represent integers in the range of approximately –2 billion to +2 billion. This fixed-size
restriction is rarely troublesome. But there are applications in which we would like to be able to use a much wider range of integers.
This is what C++ was built to do, namely create powerful new data types. Consider class HugeInt of Fig. 8.8. Study the class
carefully, then
a) Describe precisely how it operates.
b) What restrictions does the class have?
c) Overload the * multiplication operator.
d) Overload the / division operator.
116 << k << '\n';
117
118 x = y + z;
119 cout << "\nx = y + z:\n" << x << " = " << y << " + " << z << '\n';
120
121 x = y - z;
122 cout << "\nx = y - z:\n" << x << " = " << y << " - " << z << '\n';
123
124 x = y * z;
125 cout << "\nx = y * z:\n" << x << " = " << y << " * " << z << "\n\n";
126
127 if ( x != k )
128 cout << x << " != " << k << '\n';
129
130 cout << '\n';
131
132 x = k;
133
134 if ( x == k )
135 cout << x << " == " << k << '\n';
136
137 return 0;
138 }
Enter a complex number in the form: a + bi
? 0 + 0i
x: 0 + 0i
y: 4.3 + 8.2i
z: 3.3 + 1.1i
k: 0 + 0i
x = y + z:
7.6 + 9.3i = 4.3 + 8.2i + 3.3 + 1.1i
x = y - z:
1 + 7.1i = 4.3 + 8.2i - 3.3 + 1.1i
x = y * z:
23.21 + 31.79i = 4.3 + 8.2i * 3.3 + 1.1i
23.21 + 31.79i != 0 + 0i
0 + 0i == 0 + 0i
Chapter 8 Overloading Solutions 285
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
e) Overload all the relational and equality operators.
1// Fig. 8.8: hugeint1.h
2// Definition for class HugeInt
3#ifndef HUGEINT1_H
4#define HUGEINT1_H
5
6#include <iostream>
7
8using std::ostream;
9
10 class HugeInt {
11 friend ostream &operator<<( ostream &, const HugeInt & );
12 public:
13 HugeInt( long = 0 ); // conversion/default constructor
14 HugeInt( const char * ); // conversion constructor
15 HugeInt operator+( const HugeInt & ); // add another HugeInt
16 HugeInt operator+( int ); // add an int
17 HugeInt operator+( const char * ); // add an int in a char *
18 private:
19 short integer[ 30 ];
20 };
21
22 #endif
23 // Fig. 8.8: hugeint1.cpp
24 // Member and friend function definitions for class HugeInt
25 #include <cstring>
26 #include "hugeint1.h"
27
28 // Conversion constructor
29 HugeInt::HugeInt( long val )
30 {
31 int i;
32
33 for ( i = 0; i <= 29; i++ )
34 integer[ i ] = 0; // initialize array to zero
35
36 for ( i = 29; val != 0 && i >= 0; i-- ) {
37 integer[ i ] = val % 10;
38 val /= 10;
39 }
40 }
41
42 HugeInt::HugeInt( const char *string )
43 {
44 int i, j;
45
46 for ( i = 0; i <= 29; i++ )
47 integer[ i ] = 0;
48
49 for ( i = 30 - strlen( string ), j = 0; i <= 29; i++, j++ )
50 if ( isdigit( string[ j ] ) )
51 integer[ i ] = string[ j ] - '0';
52 }
53
54 // Addition
286 Overloading Solutions Chapter 8
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
55 HugeInt HugeInt::operator+( const HugeInt &op2 )
56 {
57 HugeInt temp;
58 int carry = 0;
59
60 for ( int i = 29; i >= 0; i-- ) {
61 temp.integer[ i ] = integer[ i ] +
62 op2.integer[ i ] + carry;
63
64 if ( temp.integer[ i ] > 9 ) {
65 temp.integer[ i ] %= 10;
66 carry = 1;
67 }
68 else
69 carry = 0;
70 }
71
72 return temp;
73 }
74
75 // Addition
76 HugeInt HugeInt::operator+( int op2 )
77 { return *this + HugeInt( op2 ); }
78
79 // Addition
80 HugeInt HugeInt::operator+( const char *op2 )
81 { return *this + HugeInt( op2 ); }
82
83 ostream& operator<<( ostream &output, const HugeInt &num )
84 {
85 int i;
86
87 for ( i = 0; ( num.integer[ i ] == 0 ) && ( i <= 29 ); i++ )
88 ; // skip leading zeros
89
90 if ( i == 30 )
91 output << 0;
92 else
93 for ( ; i <= 29; i++ )
94 output << num.integer[ i ];
95
96 return output;
97 }
98 // Fig. 8.8: fig08_08.cpp
99 // Test driver for HugeInt class
100 #include <iostream>
101
102 using std::cout;
103 using std::endl;
104
105 #include "hugeint1.h"
106
107 int main()
108 {
109 HugeInt n1( 7654321 ), n2( 7891234 ),
110 n3( "99999999999999999999999999999" ),
111 n4( "1" ), n5;
112
113 cout << "n1 is " << n1 << "\nn2 is " << n2
114 << "\nn3 is " << n3 << "\nn4 is " << n4
Chapter 8 Overloading Solutions 287
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
8.17 Create a class RationalNumber (fractions) with the following capabilities:
a) Create a constructor that prevents a 0 denominator in a fraction, reduces or simplifies fractions that are not in reduced
form and avoids negative denominators.
b) Overload the addition, subtraction, multiplication and division operators for this class.
c) Overload the relational and equality operators for this class.
115 << "\nn5 is " << n5 << "\n\n";
116
117 n5 = n1 + n2;
118 cout << n1 << " + " << n2 << " = " << n5 << "\n\n";
119
120 cout << n3 << " + " << n4 << "\n= " << ( n3 + n4 )
121 << "\n\n";
122
123 n5 = n1 + 9;
124 cout << n1 << " + " << 9 << " = " << n5 << "\n\n";
125
126 n5 = n2 + "10000";
127 cout << n2 << " + " << "10000" << " = " << n5 << endl;
128
129 return 0;
130 }
n1 is 7654321
n2 is 7891234
n3 is 99999999999999999999999999999
n4 is 1
n5 is 0
7654321 + 7891234 = 15545555
99999999999999999999999999999 + 1
= 100000000000000000000000000000
7654321 + 9 = 7654330
7891234 + 10000 = 7901234
1// P8_17.H
2#ifndef P8_17_H
3#define P8_17_H
4
5class RationalNumber {
6public:
7 RationalNumber( int = 0, int = 1 ); // default constructor
8 RationalNumber operator+( const RationalNumber& );
9 RationalNumber operator-( const RationalNumber& );
10 RationalNumber operator*( const RationalNumber& );
11 RationalNumber operator/( RationalNumber& );
12 bool operator>( const RationalNumber& ) const;
13 bool operator<( const RationalNumber& ) const;
14 bool operator>=( const RationalNumber& ) const;
15 bool operator<=( const RationalNumber& ) const;
16 bool operator==( const RationalNumber& ) const;
17 bool operator!=( const RationalNumber& ) const;
18 void printRational( void ) const;
19 private:
20 int numerator;
21 int denominator;
288 Overloading Solutions Chapter 8
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
22 void reduction( void );
23 };
24
25 #endif
26 // P8_17M.cpp
27 // member function definitions for p8_17.cpp
28 #include <cstdlib>
29
30 #include <iostream>
31
32 using std::cout;
33 using std::endl;
34
35 #include "p8_17.h"
36
37 RationalNumber::RationalNumber( int n, int d )
38 {
39 numerator = n;
40 denominator = d;
41 reduction();
42 }
43
44 RationalNumber RationalNumber::operator+( const RationalNumber &a )
45 {
46 RationalNumber sum;
47
48 sum.numerator = numerator * a.denominator + denominator * a.numerator;
49 sum.denominator = denominator * a.denominator;
50 sum.reduction();
51 return sum;
52 }
53
54 RationalNumber RationalNumber::operator-( const RationalNumber &s )
55 {
56 RationalNumber sub;
57
58 sub.numerator = numerator * s.denominator - denominator * s.numerator;
59 sub.denominator = denominator * s.denominator;
60 sub.reduction();
61 return sub;
62 }
63
64 RationalNumber RationalNumber::operator*( const RationalNumber &m )
65 {
66 RationalNumber multiply;
67
68 multiply.numerator = numerator * m.numerator;
69 multiply.denominator = denominator * m.denominator;
70 multiply.reduction();
71 return multiply;
72 }
73
74 RationalNumber RationalNumber::operator/( RationalNumber &d )
75 {
76 RationalNumber divide;
77
78 if ( d.numerator != 0 ) { // check for a zero in numerator
79 divide.numerator = numerator * d.denominator;
80 divide.denominator = denominator * d.numerator;
81 divide.reduction();
Chapter 8 Overloading Solutions 289
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
82 }
83 else {
84 cout << "Divide by zero error: terminating program" << endl;
85 exit( 1 ); // stdlib function
86 }
87
88 return divide;
89 }
90
91 bool RationalNumber::operator>( const RationalNumber &gr ) const
92 {
93 if ( static_cast<double>( numerator ) / denominator >
94 static_cast<double>( gr.numerator ) / gr.denominator )
95 return true;
96 else
97 return false;
98 }
99
100 bool RationalNumber::operator<(const RationalNumber &lr) const
101 {
102 if ( static_cast<double>( numerator ) / denominator <
103 static_cast<double>( lr.numerator ) / lr.denominator )
104 return true;
105 else
106 return false;
107 }
108
109 bool RationalNumber::operator>=( const RationalNumber &ger ) const
110 { return *this == ger || *this > ger; }
111
112 bool RationalNumber::operator<=( const RationalNumber &ler ) const
113 { return *this == ler || *this < ler; }
114
115 bool RationalNumber::operator==( const RationalNumber &er ) const
116 {
117 if ( numerator == er.numerator && denominator == er.denominator )
118 return true;
119 else
120 return false;
121 }
122
123 bool RationalNumber::operator!=( const RationalNumber &ner ) const
124 { return !( *this == ner ); }
125
126 void RationalNumber::printRational( void ) const
127 {
128 if ( numerator == 0 ) // print fraction as zero
129 cout << numerator;
130 else if ( denominator == 1 ) // print fraction as integer
131 cout << numerator;
132 else
133 cout << numerator << '/' << denominator;
134 }
135
136 void RationalNumber::reduction( void )
137 {
138 int largest, gcd = 1; // greatest common divisor;
139
140 largest = ( numerator > denominator ) ? numerator: denominator;
141
142 for ( int loop = 2; loop <= largest; ++loop )
143 if ( numerator % loop == 0 && denominator % loop == 0 )
290 Overloading Solutions Chapter 8
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
144 gcd = loop;
145
146 numerator /= gcd;
147 denominator /= gcd;
148 }
149 // driver for p8_17.cpp
150 #include "p8_17.h"
151 #include <iostream>
152
153 using std::cout;
154 using std::endl;
155
156 int main()
157 {
158 RationalNumber c( 7, 3 ), d( 3, 9 ), x;
159
160 c.printRational();
161 cout << " + " ;
162 d.printRational();
163 cout << " = ";
164 x = c + d;
165 x.printRational();
166
167 cout << '\n';
168 c.printRational();
169 cout << " - " ;
170 d.printRational();
171 cout << " = ";
172 x = c - d;
173 x.printRational();
174
175 cout << '\n';
176 c.printRational();
177 cout << " * " ;
178 d.printRational();
179 cout << " = ";
180 x = c * d;
181 x.printRational();
182
183 cout << '\n';
184 c.printRational();
185 cout << " / " ;
186 d.printRational();
187 cout << " = ";
188 x = c / d;
189 x.printRational();
190
191 cout << '\n';
192 c.printRational();
193 cout << " is:\n";
194
195 cout << ( ( c > d ) ? " > " : " <= " );
196 d.printRational();
197 cout << " according to the overloaded > operator\n";
198
199 cout << ( ( c < d ) ? " < " : " >= " );
200 d.printRational();
201 cout << " according to the overloaded < operator\n";
202
203 cout << ( ( c >= d ) ? " >= " : " < " );
Chapter 8 Overloading Solutions 291
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
8.18 Study the C string-handling library functions and implement each of the functions as part of the String class. Then, use
these functions to perform text manipulations.
8.19 Develop class Polynomial. The internal representation of a Polynomial is an array of terms. Each term contains a
coefficient and an exponent. The term
2x4
has a coefficient of 2 and an exponent of 4. Develop a full class containing proper constructor and destructor functions as well as
set and get functions. The class should also provide the following overloaded operator capabilities:
a) Overload the addition operator (+) to add two Polynomials.
b) Overload the subtraction operator (-) to subtract two Polynomials.
c) Overload the assignment operator (=) to assign one Polynomial to another.
d) Overload the multiplication operator (*) to multiply two Polynomials.
e) Overload the addition assignment operator (+=), the subtraction assignment operator
(-=), and the multiplication assignment operator (*=).
204 d.printRational();
205 cout << " according to the overloaded >= operator\n";
206
207 cout << ( ( c <= d ) ? " <= " : " > " );
208 d.printRational();
209 cout << " according to the overloaded <= operator\n";
210
211 cout << ( ( c == d ) ? " == " : " != " );
212 d.printRational();
213 cout << " according to the overloaded == operator\n";
214
215 cout << ( ( c != d ) ? " != " : " == " );
216 d.printRational();
217 cout << " according to the overloaded != operator" << endl;
218
219 return 0;
220 }
7/3 + 1/3 = 8/3
7/3 - 1/3 = 2
7/3 * 1/3 = 7/9
7/3 / 1/3 = 7
7/3 is:
> 1/3 according to the overloaded > operator
>= 1/3 according to the overloaded < operator
>= 1/3 according to the overloaded >= operator
> 1/3 according to the overloaded <= operator
!= 1/3 according to the overloaded == operator
!= 1/3 according to the overloaded != operator
1// P8_19P.H
2#ifndef P8_19P_H
3#define P8_19P_H
4
5class Polynomial {
6public:
7 Polynomial();
8 Polynomial operator+( const Polynomial& ) const;
9 Polynomial operator-( const Polynomial& ) const;
10 Polynomial operator*( const Polynomial& );
11 const Polynomial operator=( const Polynomial&);
12 Polynomial& operator+=( const Polynomial& );
13 Polynomial& operator-=( const Polynomial& );
292 Overloading Solutions Chapter 8
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
14 Polynomial& operator*=( const Polynomial& );
15 void enterTerms( void );
16 void printPolynomial( void ) const;
17 private:
18 int exponents[ 100 ];
19 int coefficients[ 100 ];
20 void polynomialCombine( Polynomial& ); // combine common terms
21 };
22
23 #endif
24 // P8_19M.cpp
25 // member function definitions for p8_19.cpp
26 // NOTE: The assignment operator does not need to be overloaded,
27 // because default member-wise copy can be used
28 #include <iostream>
29
30 using std::cout;
31 using std::endl;
32 using std::cin;
33 using std::ios;
34
35 #include <iomanip>
36
37 using std::setiosflags;
38 using std::resetiosflags;
39
40 #include "p8_19p.h"
41
42 Polynomial::Polynomial()
43 {
44 for ( int t = 0; t < 100; ++t ) {
45 coefficients[ t ] = 0;
46 exponents[ t ] = 0;
47 }
48 }
49
50 void Polynomial::printPolynomial( void ) const
51 {
52 int start;
53 bool zero = false;
54
55 if ( coefficients[ 0 ] ) { // output constants
56 cout << coefficients[ 0 ];
57 start = 1;
58 zero = true; // at least one term exists
59 }
60 else {
61
62 if ( coefficients[ 1 ] ) {
63 cout << coefficients[ 1 ] << 'x'; // constant does not exist
64 // so output first term
65 // without a sign
66 if ( ( exponents[ 1 ] != 0 ) && ( exponents[ 1 ] != 1 ) )
67 cout << '^' << exponents[ 1 ];
68
69 zero = true; // at least one term exists
70 }
71
72 start = 2;
73 }
Chapter 8 Overloading Solutions 293
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
74
75 // output remaining polynomial terms
76 for ( int x = start; x < 100; ++x ) {
77 if ( coefficients[ x ] != 0 ) {
78 cout << setiosflags( ios::showpos ) << coefficients[ x ]
79 << resetiosflags( ios::showpos ) << 'x';
80
81 if ( ( exponents[ x ] != 0 ) && ( exponents[ x ] != 1 ) )
82 cout << '^' << exponents[ x ];
83
84 zero = true; // at least one term exists
85 }
86 }
87
88 if ( !zero ) // no terms exist in the polynomial
89 cout << '0';
90
91 cout << endl;
92 }
93
94 const Polynomial Polynomial::operator=( const Polynomial& r )
95 {
96 exponents[ 0 ] = r.exponents[ 0 ];
97 coefficients[ 0 ] = r.coefficients[ 0 ];
98
99 for ( int s = 1; ( s < 100 ); ++s ) {
100 if ( r.exponents[ s ] != 0 ) {
101 exponents[ s ] = r.exponents[ s ];
102 coefficients[ s ] = r.coefficients[ s ];
103 }
104 else {
105 if ( exponents[ s ] == 0 )
106 break;
107 exponents[ s ] = 0;
108 coefficients[ s ] = 0;
109 }
110 }
111
112 return *this;
113 }
114
115 Polynomial Polynomial::operator+( const Polynomial& r ) const
116 {
117 Polynomial temp;
118 bool exponentExists;
119
120 // process element with a zero exponent
121 temp.coefficients[ 0 ] = coefficients[ 0 ] + r.coefficients[ 0 ];
122
123 // copy right arrays into temp object s will be used to keep
124 // track of first open coefficient element
125 for ( int s = 1; ( s < 100 ) && ( r.exponents[ s ] != 0 ); ++s ) {
126 temp.coefficients[ s ] = r.coefficients[ s ];
127 temp.exponents[ s ] = r.exponents[ s ];
128 }
129
130 for ( int x = 1; x < 100; ++x ) {
131 exponentExists = false; // assume exponent will not be found
132
133 for ( int t = 1; ( t < 100 ) && ( !exponentExists ); ++t )
134 if ( exponents[ x ] == temp.exponents[ t ] ) {
135 temp.coefficients[ t ] += coefficients[ x ];
294 Overloading Solutions Chapter 8
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
136 exponentExists = true; // exponent found
137 }
138
139 // exponent was not found, insert into temp
140 if ( !exponentExists ) {
141 temp.exponents[ s ] = exponents[ x ];
142 temp.coefficients[ s ] += coefficients[ x ];
143 ++s;
144 }
145 }
146
147 return temp;
148 }
149
150 Polynomial &Polynomial::operator+=( const Polynomial &r )
151 {
152 *this = *this + r;
153 return *this;
154 }
155
156 Polynomial Polynomial::operator-( const Polynomial& r ) const
157 {
158 Polynomial temp;
159 bool exponentExists;
160
161 // process element with a zero exponent
162 temp.coefficients[ 0 ] = coefficients[ 0 ] - r.coefficients[ 0 ];
163
164 // copy left arrays into temp object s will be used to keep
165 // track of first open coefficient element
166 for ( int s = 1; ( s < 100 ) && ( exponents[ s ] != 0 ); ++s ) {
167 temp.coefficients[ s ] = coefficients[ s ];
168 temp.exponents[ s ] = exponents[ s ];
169 }
170
171 for ( int x = 1; x < 100; ++x) {
172 exponentExists = false; // assume exponent will not be found
173
174 for ( int t = 1; ( t < 100 ) && ( !exponentExists ); ++t )
175 if ( r.exponents[ x ] == temp.exponents[ t ] ) {
176 temp.coefficients[ t ] -= r.coefficients[ x ];
177 exponentExists = true; // exponent found
178 }
179
180 // exponent was not found, insert into temp
181 if ( !exponentExists ) {
182 temp.exponents[ s ] = r.exponents[ x ];
183 temp.coefficients[ s ] -= r.coefficients[ x ];
184 ++s;
185 }
186 }
187
188 return temp;
189 }
190
191 Polynomial &Polynomial::operator-=( const Polynomial& r )
192 {
193 *this = *this - r;
194 return *this;
195 }
196
197 Polynomial Polynomial::operator*( const Polynomial& r )
Chapter 8 Overloading Solutions 295
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
198 {
199 Polynomial temp;
200 int s = 1; // subscript location for temp coefficients and exponents
201
202 for ( int x = 0; ( x < 100 ) && ( x == 0 || coefficients[ x ] != 0 ); ++x )
203 for ( int y = 0; ( y < 100 ) && ( y == 0 || r.coefficients[ y ] != 0 ); ++y )
204 if ( coefficients[ x ] * r.coefficients[ y ] )
205
206 if ( ( exponents[ x ] == 0 ) && ( r.exponents[ y ] == 0 ) )
207 temp.coefficients[ 0 ] += coefficients[ x ] * r.coefficients[ y ];
208 else {
209 temp.coefficients[ s ] = coefficients[ x ] * r.coefficients[ y ];
210 temp.exponents[ s ] = exponents[ x ] + r.exponents[ y ];
211 ++s;
212 }
213
214 polynomialCombine( temp ); // combine common terms
215 return temp;
216 }
217
218 void Polynomial::polynomialCombine( Polynomial& w )
219 {
220 Polynomial temp = w;
221 int exp;
222
223 // zero out elements of w
224 for ( int x = 0; x < 100; ++x ) {
225 w.coefficients[ x ] = 0;
226 w.exponents[ x ] = 0;
227 }
228
229 for ( x = 1; x < 100; ++x ) {
230 exp = temp.exponents[ x ];
231
232 for ( int y = x + 1; y < 100; ++y )
233 if ( exp == temp.exponents[ y ] ) {
234 temp.coefficients[ x ] += temp.coefficients[ y ];
235 temp.exponents[ y ] = 0;
236 temp.coefficients[ y ] = 0;
237 }
238 }
239
240 w = temp;
241 }
242
243 Polynomial &Polynomial::operator*=( const Polynomial& r )
244 {
245 *this = *this * r;
246 return *this;
247 }
248
249 void Polynomial::enterTerms( void )
250 {
251 bool found = false;
252 int numberOfTerms, c, e;
253
254 cout << "\nEnter number of polynomial terms: ";
255 cin >> numberOfTerms;
256
257 for ( int n = 1; n <= numberOfTerms; ++n ) {
258 cout << "\nEnter coefficient: ";
259 cin >> c;
296 Overloading Solutions Chapter 8
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
260 cout << "Enter exponent: ";
261 cin >> e;
262
263 if ( c != 0 ) {
264 // exponents of zero are forced into first element
265 if ( e == 0 ) {
266 coefficients[ 0 ] += c;
267 continue;
268 }
269
270 for ( int term = 1; ( term < 100 ) &&
271 ( coefficients[ term ] != 0 ); ++term )
272 if ( e == exponents[ term ] ) {
273 coefficients[ term ] += c;
274 exponents[ term ] = e;
275 found = true; // existing exponent updated
276 }
277
278 if ( !found ) { // add term
279 coefficients[ term ] += c;
280 exponents[ term ] = e;
281 }
282 }
283 }
284 }
285 // driver for p8_19.cpp
286 #include <iostream>
287
288 using std::cout;
289 using std::endl;
290
291 #include "p8_19p.h"
292
293 int main()
294 {
295 Polynomial a, b, c, t;
296
297 a.enterTerms();
298 b.enterTerms();
299 t = a; //save the value of a
300 cout << "First polynomial is:\n";
301 a.printPolynomial();
302 cout << "Second polynomial is:\n";
303 b.printPolynomial();
304 cout << "\nAdding the polynomials yields:\n";
305 c = a + b;
306 c.printPolynomial();
307 cout << "\n+= the polynomials yields:\n";
308 a += b;
309 a.printPolynomial();
310 cout << "\nSubtracting the polynomials yields:\n";
311 a = t; // reset a to original value
312 c = a - b;
313 c.printPolynomial();
314 cout << "\n-= the polynomials yields:\n";
315 a -= b;
316 a.printPolynomial();
317 cout << "\nMultiplying the polynomials yields:\n";
318 a = t; // reset a to original value
319 c = a * b;
Chapter 8 Overloading Solutions 297
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
8.20 The program of Fig. 8.3 contains the comment
// Overloaded stream-insertion operator (cannot be
// a member function if we would like to invoke it with
// cout << somePhoneNumber;)
Actually, it cannot be a member function of class ostream, but it can be a member function of class PhoneNumber if we were
willing to invoke it in either of the following ways:
somePhoneNumber.operator<<( cout );
320 c.printPolynomial();
321 cout << "\n*= the polynomials yields:\n";
322 a *= b;
323 a.printPolynomial();
324 cout << endl;
325 return 0;
326 }
Enter number of polynomial terms: 2
Enter coefficient: 2
Enter exponent: 2
Enter coefficient: 3
Enter exponent: 3
Enter number of polynomial terms: 3
Enter coefficient: 1
Enter exponent: 1
Enter coefficient: 2
Enter exponent: 2
Enter coefficient: 3
Enter exponent: 3
First polynomial is:
2x^2+3x^3
Second polynomial is:
1x+2x^2+3x^3
Adding the polynomials yields:
1x+4x^2+6x^3
+= the polynomials yields:
1x+4x^2+6x^3
Subtracting the polynomials yields:
-1x
-= the polynomials yields:
-1x
Multiplying the polynomials yields:
2x^3+7x^4+12x^5+9x^6
*= the polynomials yields:
2x^3+7x^4+12x^5+9x^6
298 Overloading Solutions Chapter 8
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
or
somePhoneNumber << cout;
Rewrite the program of Fig. 8.3 with the overloaded stream-insertion operator<< as a member function and try the two preced-
ing statements in the program to prove that they work.
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
9
Inheritance
Solutions
Solutions
9.2 Consider the class Bicycle. Given your knowledge of some common components of bicycles, show a class hierarchy in
which the class Bicycle inherits from other classes, which, in turn, inherit from yet other classes. Discuss the instantiation of
various objects of class Bicycle. Discuss inheritance from class Bicycle for other closely related derived classes.
ANS: Possible classes are displayed in bold.
Bicycle composed of:
HandleBars
Seat
Frame
Wheels composed of:
Tires
Rims composed of:
Spokes
Pedals
Chain composed of:
Links
Brakes composed of:
Wires
BrakePads
BrakeHandles
Classes that can be derived from Bicycle are Unicycle, Tricycle,
TandemBicycle, etc.
9.3 Briefly define each of the following terms: inheritance, multiple inheritance, base class and derived class.
ANS:
inheritance: The process by which a class incorporates the attributes and behaviors of a previously defined class.
multiple inheritance: The process by which a class incorporates the attributes and behaviors of two or more previously
defined classes.
base class: A class from which other classes inherit attributes and behaviors.
derived class: A class that has inherited attributes and behaviors from one or more base classes.
300 Inheritance Solutions Chapter 9
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
9.4 Discuss why converting a base-class pointer to a derived-class pointer is considered dangerous by the compiler.
ANS: The pointer must "point" to the object of the derived class, before being dereferenced. When the compiler looks at
an object through a derived-class pointer, it expects to see the all the pieces of the derived class. However, if the base-class
pointer originally pointed to a base-class object, the additional pieces added by the derived class do not exist.
9.5 Distinguish between single inheritance and multiple inheritance.
ANS: Single inheritance inherits from one class only. Multiple inheritance inherits from two or more classes.
9.6 (True/False) A derived class is often called a subclass because it represents a subset of its base class (i.e., a derived class is
generally smaller than its base class).
ANS: False. Derived classes are often larger than their base classes, because they need specific features in addition to those
inherited from the base class. The term subclass means that the derived class is a more specific version of its base class. For
example, a cat is a specific type of animal.
9.7 (True/False) A derived-class object is also an object of that derived class’ base class.
ANS: True.
9.8 Some programmers prefer not to use protected access because it breaks the encapsulation of the base class. Discuss the
relative merits of using protected access vs. insisting on using private access in base classes.
ANS: Inherited private data is hidden in the derived class and is accessible only through the public or protected
member functions of the base class. Using protected access enables the derived class to manipulate the protected
members without using the base class access functions. If the base class members are private, the public or pro-
tected member functions of the base class must be used to access private members. This can result in additional func-
tion calls—which can decrease performance.
9.9 Many programs written with inheritance could be solved with composition instead, and vice versa. Discuss the relative mer-
its of these approaches in the context of the Point, Circle, Cylinder class hierarchy in this chapter. Rewrite the program of
Fig. 9.10 (and the supporting classes) to use composition rather than inheritance. After you do this, reassess the relative merits of
the two approaches both for the Point, Circle, Cylinder problem and for object-oriented programs in general.
1// P9_09.H
2#ifndef P9_09_H
3#define P9_09_H
4
5#include <iostream>
6using std::ostream;
7
8class Point {
9 friend ostream &operator<<( ostream &, const Point & );
10 public:
11 Point( double a = 0, double b = 0 ) { setPoint( a, b ); }
12 void setPoint( double, double );
13 void print( void ) const;
14 double getX( void ) const { return x; }
15 double getY( void ) const { return y; }
16 private:
17 double x, y;
18 };
19
20 #endif
21 // P9_09PM.cpp
22 // Member functions for class Point
23 #include <iostream>
24
25 using std::cout;
Chapter 9 Inheritance Solutions 301
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
26 using std::ostream;
27
28 #include "p9_09.h"
29
30 void Point::setPoint( double a, double b )
31 {
32 x = a;
33 y = b;
34 }
35
36 ostream &operator<<( ostream &output, const Point &p )
37 {
38 p.print();
39 return output;
40 }
41
42 void Point::print( void ) const
43 { cout << '[' << getX() << ", " << getY() << ']'; }
44 // P9_09C.H
45 #ifndef P9_09C_H
46 #define P9_09C_H
47 #include "p9_09.h"
48
49 class Circle {
50 friend ostream &operator<<( ostream &, const Circle & );
51 public:
52 Circle( double = 0.0, double = 0.0, double = 0.0 );
53 void setRadius( double r ) { radius = r; }
54 double getRadius( void ) const { return radius; }
55 double area( void ) const;
56 void print( void ) const;
57 private:
58 double radius;
59 Point pointObject;
60 };
61
62 #endif
63 // P9_09CM.cpp
64 // Member function definitions for class Circle
65 #include <iostream>
66
67 using std::cout;
68 using std::ios;
69
70 #include <iomanip>
71
72 using std::setprecision;
73 using std::setiosflags;
74 using std::resetiosflags;
75
76 #include "p9_09c.h"
77
78 Circle::Circle( double r, double a, double b ) : pointObject( a, b )
79 { setRadius( r ); }
80
81 double Circle::area( void ) const
82 { return 3.14159 * getRadius() * getRadius(); }
83
302 Inheritance Solutions Chapter 9
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
84 ostream &operator<<( ostream &output, const Circle &c )
85 {
86 c.print();
87 return output;
88 }
89
90 void Circle::print( void ) const
91 {
92 cout << "Center = ";
93 pointObject.print();
94 cout << "; Radius = " << setiosflags( ios::fixed | ios::showpoint )
95 << setprecision( 2 ) << getRadius()
96 << resetiosflags( ios::fixed | ios::showpoint );
97 }
98 // P9_09CY.H
99 #ifndef P9_09CY_H
100 #define P9_09CY_H
101 #include "p9_09.h"
102 #include "p9_09c.h"
103
104 class Cylinder {
105 friend ostream& operator<<(ostream&, const Cylinder&);
106 public:
107 Cylinder(double = 0.0, double = 0.0, double = 0.0, double = 0.0);
108 void setHeight(double h) { height = h; }
109 double getHeight(void) const { return height; }
110 void print(void) const;
111 double area(void) const;
112 double volume(void) const;
113 private:
114 double height;
115 Circle circleObject;
116 };
117
118 #endif
119 // P9_09CYM.cpp
120 // Member function definitions for class Cylinder.
121 #include <iostream>
122
123 using std::cout;
124 using std::ostream;
125
126 #include "p9_09cy.h"
127
128 Cylinder::Cylinder( double h, double r, double x, double y )
129 : circleObject( r, x, y ) { height = h; }
130
131 double Cylinder::area( void ) const
132 { return 2 * circleObject.area() + 2 * 3.14159 *
133 circleObject.getRadius() * getHeight(); }
134
135 ostream& operator<<( ostream &output, const Cylinder& c )
136 {
137 c.print();
138 return output;
139 }
Chapter 9 Inheritance Solutions 303
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
9.10 Rewrite the Point, Circle, Cylinder program of Fig. 9.10 as a Point, Square, Cube program. Do this two
ways—once with inheritance and once with composition.
140
141 double Cylinder::volume( void ) const
142 { return circleObject.area() * getHeight(); }
143
144 void Cylinder::print( void ) const
145 {
146 circleObject.print();
147 cout << "; Height = " << getHeight() << '\n';
148 }
149 // P9_09.cpp
150 #include <iostream>
151
152 using std::cout;
153 using std::endl;
154
155 #include "p9_09.h"
156 #include "p9_09c.h"
157 #include "p9_09cy.h"
158
159 int main()
160 {
161 Point p( 1.1, 8.5 );
162 Circle c( 2.0, 6.4, 9.8 );
163 Cylinder cyl( 5.7, 2.5, 1.2, 2.3 );
164
165 cout << "Point: " << p << "\nCircle: " << c
166 << "\nCylinder: " << cyl << endl;
167
168 return 0;
169 }
Point: [1.1, 8.5]
Circle: Center = [6.4, 9.8]; Radius = 2.00
Cylinder: Center = [1.2, 2.3]; Radius = 2.50; Height = 5.7
1// P9_10.H
2#ifndef P9_10_H
3#define P9_10_H
4
5#include <iostream>
6using std::ostream;
7
8class Point {
9 friend ostream &operator<<( ostream&, const Point& );
10 public:
11 Point( double = 0, double = 0, double = 0 );
12 void setPoint( double, double, double );
13 double getX( void ) const { return x; }
14 double getY( void ) const { return y; }
15 double getZ( void ) const { return z; }
16 private:
304 Inheritance Solutions Chapter 9
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
17 double x, y, z;
18 };
19
20 #endif
21 //P9_10MP.cpp
22 // member function defintions for class Point
23 #include <iostream>
24
25 using std::cout;
26 using std::ios;
27 using std::ostream;
28
29 #include <iomanip>
30
31 using std::setprecision;
32 using std::setiosflags;
33 using std::resetiosflags;
34
35 #include "p9_10.h"
36
37 Point::Point( double a, double b, double c) { setPoint( a, b, c ); }
38
39 void Point::setPoint( double a, double b, double c )
40 {
41 x = a;
42 y = b;
43 z = c;
44 }
45
46 ostream &operator<<( ostream &output, const Point &p )
47 {
48 output << setiosflags( ios::fixed | ios::showpoint )
49 << "The point is: [" << setprecision( 2 ) << p.x
50 << ", " << setprecision( 2 ) << p.y << setprecision( 2 )
51 << ", " << p.z << "]\n"
52 << resetiosflags( ios::fixed | ios::showpoint );
53
54 return output;
55 }
56 //P9_10S.H
57 #ifndef P9_10S_H
58 #define P9_10S_H
59 #include "p9_10.h"
60
61 #include <iostream>
62 using std::ostream;
63
64 class Square : public Point {
65 friend ostream &operator<<( ostream &, const Square & );
66 public:
67 Square( double = 0, double = 0, double = 0, double = 1.0 );
68 void setSide( double s) { side = s > 0 && s <= 20.0 ? s : 1.0; }
69 double area( void ) const { return side * side; }
70 double getSide( void ) const { return side; }
71 protected:
72 double side;
73 };
74
Chapter 9 Inheritance Solutions 305
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
75 #endif
76 //P9_10MS.cpp
77 //member functions for class Square
78 #include <iostream>
79
80 using std::cout;
81 using std::ios;
82 using std::ostream;
83
84 #include <iomanip>
85
86 using std::setprecision;
87 using std::setiosflags;
88 using std::resetiosflags;
89
90 #include "p9_10s.h"
91
92 Square::Square( double x, double y, double z, double s ) : Point( x, y, z )
93 { setSide( s ); }
94
95 ostream &operator<<( ostream &output, const Square &s )
96 {
97 output << setiosflags( ios::fixed | ios::showpoint )
98 << "The lower left coordinate of the square is: ["
99 << setprecision( 2 ) << s.getX() << ", " << setprecision( 2 )
100 << s.getY() << ", " << setprecision( 2 ) << s.getZ() << ']'
101 << "\nThe square side is: " << setprecision( 2 ) << s.side
102 << "\nThe area of the square is: " << setprecision( 2 )
103 << s.area() << '\n'
104 << resetiosflags( ios::fixed | ios::showpoint );
105
106 return output;
107 }
108 // P9_10C.H
109 #ifndef P9_10C_H
110 #define P9_10C_H
111 #include "p9_10s.h"
112
113 #include <iostream>
114 using std::ostream;
115
116 class Cube : public Square {
117 friend ostream &operator<<( ostream&, const Cube& );
118 public:
119 Cube( double = 0, double = 0, double = 0, double = 1.0 );
120 double area( void ) const { return 6 * Square::area(); }
121 double volume( void ) const { return Square::area() * getSide(); }
122 };
123
124 #endif
125 //P9_10MC.cpp
126 //member function definitions for class Cube
127 #include <iostream>
128
129 using std::cout;
306 Inheritance Solutions Chapter 9
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
130 using std::ios;
131 using std::ostream;
132
133 #include <iomanip>
134
135 using std::setprecision;
136 using std::setiosflags;
137 using std::resetiosflags;
138
139 #include "p9_10c.h"
140
141 Cube::Cube( double j, double k, double m, double s ) : Square( j, k, m, s ) { }
142
143 ostream &operator<<( ostream &output, const Cube &c )
144 {
145 output << setiosflags( ios::fixed | ios::showpoint )
146 << "The lower left coordinate of the cube is: ["
147 << setprecision( 2 ) << c.getX() << ", " << setprecision( 2 )
148 << c.getY() << ", " << setprecision( 2 ) << c.getZ()
149 << "]\nThe cube side is: " << setprecision( 2 ) << c.side
150 << "\nThe surface area of the cube is: " << setprecision( 2 )
151 << c.area() << "\nThe volume of the cube is: "
152 << setprecision( 2 ) << c.volume()
153 << resetiosflags( ios::showpoint | ios::fixed ) << '\n';
154
155 return output;
156 }
157 // driver for p9_10.cpp
158 #include <iostream>
159
160 using std::cout;
161
162 #include "p9_10.h"
163 #include "p9_10s.h"
164 #include "p9_10c.h"
165
166 int main()
167 {
168 Point p( 7.9, 12.5, 8.8 );
169 Square s( 0.0, 0.0, 0.0, 5.0 );
170 Cube c( 0.5, 8.3, 12.0, 2.0 );
171
172 cout << p << '\n' << s << '\n' << c << '\n';
173
174 return 0;
175 }
The point is: [7.90, 12.50, 8.80]
The lower left coordinate of the square is: [0.00, 0.00, 0.00]
The square side is: 5.00
The area of the square is: 25.00
The lower left coordinate of the cube is: [0.50, 8.30, 12.00]
The cube side is: 2.00
The surface area of the cube is: 24.00
The volume of the cube is: 8.00
Chapter 9 Inheritance Solutions 307
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1// P9_10B.H
2#ifndef P9_10B_H
3#define P9_10B_H
4
5#include <iostream>
6using std::ostream;
7
8class Point {
9 friend ostream &operator<<( ostream&, const Point& );
10 public:
11 Point( double = 0, double = 0, double = 0 );
12 void setPoint( double, double, double );
13 void print( void ) const;
14 double getX( void ) const { return x; }
15 double getY( void ) const { return y; }
16 double getZ( void ) const { return z; }
17 private:
18 double x, y, z;
19 };
20
21 #endif
22 //P9_10BMP.cpp
23 // member function defintions for class Point
24 #include <iostream>
25
26 using std::cout;
27 using std::ios;
28 using std::ostream;
29
30 #include <iomanip>
31
32 using std::setprecision;
33 using std::setiosflags;
34 using std::resetiosflags;
35
36 #include "p9_10b.h"
37
38 Point::Point( double a, double b, double c ) { setPoint( a, b, c ); }
39
40 void Point::setPoint( double a, double b, double c )
41 {
42 x = a;
43 y = b;
44 z = c;
45 }
46
47 ostream &operator<<( ostream &output, const Point &p )
48 {
49 output << "The point is: ";
50 p.print();
51 return output;
52 }
53
54 void Point::print( void ) const
55 {
56 cout << setiosflags( ios::fixed | ios::showpoint )
57 << '[' << setprecision( 2 ) << getX()
58 << ", " << setprecision( 2 ) << getY() << setprecision( 2 )
59 << ", " << getZ() << "]\n"
60 << resetiosflags( ios::fixed | ios::showpoint );
308 Inheritance Solutions Chapter 9
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
61 }
62 //P9_10BS.H
63 #ifndef P9_10BS_H
64 #define P9_10BS_H
65 #include "p9_10B.h"
66
67 #include <iostream>
68 using std::ostream;
69
70 class Square {
71 friend ostream &operator<<( ostream &, const Square & );
72 public:
73 Square( double = 0, double = 0, double = 0, double = 1.0 );
74 void setSide( double s ) { side = s > 0 && s <= 20.0 ? s : 1.0; }
75 void print( void ) const;
76 double getXCoord() const { return pointObject.getX(); }
77 double getYCoord() const { return pointObject.getY(); }
78 double getZCoord() const { return pointObject.getZ(); }
79 double area( void ) const { return side * side; }
80 double getSide( void ) const { return side; }
81 protected:
82 double side;
83 Point pointObject;
84 };
85
86 #endif
87 //P9_10BMS.cpp
88 //member functions for class Square
89 #include <iostream>
90
91 using std::cout;
92 using std::ios;
93 using std::ostream;
94
95 #include <iomanip>
96
97 using std::setprecision;
98 using std::setiosflags;
99
100 #include "p9_10bs.h"
101
102 Square::Square( double x, double y, double z, double s )
103 : pointObject( x, y, z )
104 { setSide( s ); }
105
106 ostream &operator<<( ostream &output, const Square &s )
107 {
108 s.print();
109 return output;
110 }
111
112 void Square::print( void ) const
113 {
114 cout << setiosflags( ios::fixed | ios::showpoint )
115 << "The lower left coordinate of the square is: ";
116 pointObject.print();
117 cout << "The square side is: " << setprecision( 2 ) << getSide()
118 << "\nThe area of the square is: " << setprecision( 2 )
Chapter 9 Inheritance Solutions 309
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
119 << area() << '\n';
120 }
121 // P9_10BC.H
122 #ifndef P9_10BC_H
123 #define P9_10BC_H
124 #include "p9_10bs.h"
125
126 #include <iostream>
127 using std::ostream;
128
129 class Cube {
130 friend ostream &operator<<( ostream&, const Cube& );
131 public:
132 Cube( double = 0, double = 0, double = 0, double = 1.0 );
133 void print( void ) const;
134 double area( void ) const;
135 double volume( void ) const;
136 private:
137 Square squareObject;
138 };
139
140 #endif
141 //P9_10BMC.cpp
142 //member function definitions for class Cube
143 #include <iostream>
144
145 using std::cout;
146 using std::ios;
147 using std::ostream;
148
149 #include <iomanip>
150
151 using std::setprecision;
152 using std::setiosflags;
153
154 #include "p9_10bc.h"
155
156 Cube::Cube( double j, double k, double m, double s )
157 : squareObject( j, k, m, s ) { }
158
159 ostream &operator<<( ostream &output, const Cube &c )
160 {
161 c.print();
162 return output;
163 }
164
165 void Cube::print( void ) const
166 {
167 cout << setiosflags( ios::fixed | ios::showpoint )
168 << "The lower left coordinate of the cube is: [" << setprecision( 2 )
169 << squareObject.getXCoord() << ", " << setprecision( 2 )
170 << squareObject.getYCoord() << ", " << setprecision( 2 )
171 << squareObject.getZCoord() << "]\nThe cube side is: "
172 << setprecision( 2 ) << squareObject.getSide()
173 << "\nThe surface area of the cube is: " << setprecision( 2 ) << area()
174 << "\nThe volume of the cube is: " << setprecision( 2 ) << volume() << '\n';
175 }
176
310 Inheritance Solutions Chapter 9
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
9.11 In the chapter, we stated, “When a base-class member is inappropriate for a derived class, that member can be overridden
in the derived class with an appropriate implementation.” If this is done, does the derived-class-is-a-base-class-object relationship
still hold? Explain your answer.
9.12 Study the inheritance hierarchy of Fig. 9.2. For each class, indicate some common attributes and behaviors consistent with
the hierarchy. Add some other classes (e.g., UndergraduateStudent, GraduateStudent, Freshman, Sophomore,
Junior, Senior, etc.) to enrich the hierarchy.
9.13 Write an inheritance hierarchy for class Quadrilateral, Trapezoid, Parallelogram, Rectangle and
Square. Use Quadrilateral as the base class of the hierarchy. Make the hierarchy as deep (i.e., as many levels) as possible.
The private data of Quadrilateral should be the (x, y) coordinate pairs for the four endpoints of the Quadrilateral.
Write a driver program that instantiates and displays objects of each of these classes.
177 double Cube::area( void ) const { return 6 * squareObject.area(); }
178
179 double Cube::volume( void ) const
180 { return squareObject.area() * squareObject.getSide(); }
181 // driver for p9_10b.cpp
182 #include <iostream>
183
184 using std::cout;
185 using std::endl;
186
187 #include "p9_10b.h"
188 #include "p9_10bs.h"
189 #include "p9_10bc.h"
190
191 int main()
192 {
193 Point p( 7.9, 12.5, 8.8 );
194 Square s( 0.0, 0.0, 0.0, 5.0 );
195 Cube c( 0.5, 8.3, 12.0, 2.0 );
196
197 cout << p << '\n' << s << '\n' << c << endl;
198
199 return 0;
200 }
The point is: [7.90, 12.50, 8.80]
The lower left coordinate of the square is: [0.00, 0.00, 0.00]
The square side is: 5
The area of the square is: 25
The lower left coordinate of the cube is: [0.50, 8.30, 12.00]
The cube side is: 2.00
The surface area of the cube is: 24.00
The volume of the cube is: 8.00
1// P9_13.H
2#ifndef P9_13_H
3#define P9_13_H
4
5#include <iostream>
6using std::ostream;
7
8class Point {
9 friend ostream &operator<<( ostream&, const Point& );
Chapter 9 Inheritance Solutions 311
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
10 public:
11 Point( double = 0, double = 0 );
12 void setPoint( double, double );
13 void print( void ) const;
14 double getX( void ) const { return x; }
15 double getY( void ) const { return y; }
16 private:
17 double x, y;
18 };
19
20 #endif
21 //P9_13PM.cpp
22 // member function defintions for class Point
23 #include <iostream>
24
25 using std::cout;
26 using std::ios;
27 using std::ostream;
28
29 #include <iomanip>
30
31 using std::setprecision;
32 using std::setiosflags;
33 using std::resetiosflags;
34
35 #include "p9_13.h"
36
37 Point::Point( double a, double b ) { setPoint( a, b ); }
38
39 void Point::setPoint( double a, double b )
40 {
41 x = a;
42 y = b;
43 }
44
45 ostream &operator<<( ostream &output, const Point &p )
46 {
47 output << "The point is: ";
48 p.print();
49 return output;
50 }
51
52 void Point::print( void ) const
53 {
54 cout << setiosflags( ios::fixed | ios::showpoint )
55 << '[' << setprecision( 2 ) << getX()
56 << ", " << setprecision( 2 ) << getY() << "]\n"
57 << resetiosflags( ios::fixed | ios::showpoint );
58 }
59 // P9_13Q.H
60 #ifndef P9_13Q_H
61 #define P9_13Q_H
62 #include "p9_13.h"
63
64 #include <iostream>
65 using std::ostream;
66
67 class Quadrilateral {
312 Inheritance Solutions Chapter 9
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
68 friend ostream &operator<<( ostream&, Quadrilateral& );
69 public:
70 Quadrilateral( double = 0, double = 0, double = 0, double = 0, double = 0,
71 double = 0, double = 0, double = 0 );
72 void print( void ) const;
73 protected:
74 Point p1;
75 Point p2;
76 Point p3;
77 Point p4;
78 };
79
80 #endif
81 // P9_13QM.cpp
82 // member functions for class Quadrilateral
83 #include "p9_13q.h"
84
85 #include <iostream>
86 using std::cout;
87 using std::ostream;
88
89 Quadrilateral::Quadrilateral( double x1, double y1, double x2, double y2,
90 double x3, double y3, double x4, double y4 )
91 : p1( x1, y1 ), p2( x2, y2 ), p3( x3, y3 ), p4( x4, y4 ) { }
92
93 ostream &operator<<( ostream& output, Quadrilateral& q )
94 {
95 output << "Coordinates of Quadrilateral are:\n";
96 q.print();
97 output << '\n';
98 return output;
99 }
100
101 void Quadrilateral::print( void ) const
102 {
103 cout << '(' << p1.getX()
104 << ", " << p1.getY() << ") , (" << p2.getX() << ", " << p2.getY()
105 << ") , (" << p3.getX() << ", " << p3.getY() << ") , ("
106 << p4.getX() << ", " << p4.getY() << ")\n";
107 }
108 // P9_13T.H
109 #ifndef P9_13T_H
110 #define P9_13T_H
111 #include "p9_13q.h"
112
113 #include <iostream>
114 using std::ostream;
115
116 class Trapazoid : public Quadrilateral {
117 friend ostream& operator<<( ostream&, Trapazoid& );
118 public:
119 Trapazoid( double = 0, double = 0, double = 0, double = 0, double = 0,
120 double = 0, double = 0, double = 0, double = 0 );
121 void print( void ) const;
122 void setHeight( double h ) { height = h; }
123 double getHeight( void ) const { return height; }
124 private:
125 double height;
Chapter 9 Inheritance Solutions 313
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
126 };
127
128 #endif
129 // P9_13TM.cpp
130 // member function definitions for class Trapazoid
131 #include "p9_13t.h"
132
133 #include <iostream>
134
135 using std::cout;
136 using std::ostream;
137
138
139 Trapazoid::Trapazoid( double h, double x1, double y1, double x2, double y2,
140 double x3, double y3, double x4, double y4 )
141 : Quadrilateral( x1, y1, x2, y2, x3, y3, x4, y4 )
142 { setHeight( h ); }
143
144 ostream& operator<<( ostream& out, Trapazoid& t )
145 {
146 out << "The Coordinates of the Trapazoid are:\n";
147 t.print();
148 return out;
149 }
150
151 void Trapazoid::print( void ) const
152 {
153 Quadrilateral::print();
154 cout << "Height is : " << getHeight() << "\n\n";
155 }
156 // P9_13PA_H
157 #ifndef P9_13PA_H
158 #define P9_13PA_H
159 #include "p9_13q.h"
160
161 #include <iostream>
162 using std::ostream;
163
164 class Parallelogram : public Quadrilateral {
165 friend ostream& operator<<( ostream&, Parallelogram& );
166 public:
167 Parallelogram( double = 0, double = 0, double = 0, double = 0,
168 double = 0, double = 0, double = 0, double = 0 );
169 void print( void ) const;
170 private:
171 // no private data members
172 };
173
174 #endif
175 // P9_13PAM.cpp
176 #include "p9_13q.h"
177 #include "p9_13pa.h"
178
179 #include <iostream>
180 using std::ostream;
314 Inheritance Solutions Chapter 9
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
181
182 Parallelogram::Parallelogram( double x1, double y1, double x2, double y2,
183 double x3, double y3, double x4, double y4 )
184 : Quadrilateral( x1, y1, x2, y2, x3, y3, x4, y4 ) { }
185
186 ostream& operator<<( ostream& out, Parallelogram& pa )
187 {
188 out << "The coordinates of the Parallelogram are:\n";
189 pa.print();
190 return out;
191 }
192
193 void Parallelogram::print( void ) const
194 { Quadrilateral::print(); }
195 // P9_13R.H
196 #ifndef P9_13R_H
197 #define P9_13R_H
198 #include "p9_13pa.h"
199
200 #include <iostream>
201 using std::ostream;
202
203 class Rectangle : public Parallelogram {
204 friend ostream& operator<<( ostream&, Rectangle& );
205 public:
206 Rectangle( double = 0, double = 0, double = 0, double = 0,
207 double = 0, double = 0, double = 0, double = 0 );
208 void print( void ) const;
209 private:
210 // no private data members
211 };
212
213 #endif
214 // P9_13RM.cpp
215 #include "p9_13r.h"
216 #include "p9_13pa.h"
217
218 #include <iostream>
219 using std::ostream;
220
221 Rectangle::Rectangle( double x1, double y1, double x2, double y2,
222 double x3, double y3, double x4, double y4 )
223 : Parallelogram( x1, y1, x2, y2, x3, y3, x4, y4 ) { }
224
225 ostream& operator<<( ostream& out, Rectangle& r )
226 {
227 out << "\nThe coordinates of the Rectangle are:\n";
228 r.print();
229 return out;
230 }
231
232 void Rectangle::print( void ) const
233 { Parallelogram::print(); }
234 / P9_13RH.H
235 #ifndef P9_13RH_H
Chapter 9 Inheritance Solutions 315
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
236 #define P9_13RH_H
237 #include "p9_13pa.h"
238
239 #include <iostream>
240 using std::ostream;
241
242 class Rhombus : public Parallelogram {
243 friend ostream& operator<<(ostream&, Rhombus&);
244 public:
245 Rhombus( double = 0, double = 0, double = 0, double = 0,
246 double = 0, double = 0, double = 0, double = 0 );
247 void print( void ) const { Parallelogram::print(); }
248 private:
249 // no private data members
250 };
251
252 #endif
253 //P9_13HM.cpp
254 #include "p9_13rh.h"
255 #include "p9_13pa.h"
256
257 #include <iostream>
258 using std::ostream;
259
260 Rhombus::Rhombus( double x1, double y1, double x2, double y2,
261 double x3, double y3, double x4, double y4 )
262 : Parallelogram( x1, y1, x2, y2, x3, y3, x4, y4 ) { }
263
264 ostream& operator<<( ostream& out, Rhombus& r )
265 {
266 out << "\nThe coordinates of the Rhombus are:\n";
267 r.print();
268 return out;
269 }
270 // P9_13S.H
271 #ifndef P9_13S_H
272 #define P9_13S_H
273 #include "p9_13pa.h"
274
275 #include <iostream>
276 using std::ostream;
277
278 class Square : public Parallelogram {
279 friend ostream& operator<<( ostream&, Square& );
280 public:
281 Square( double = 0, double = 0, double = 0, double = 0,
282 double = 0, double = 0, double = 0, double = 0 );
283 void print( void ) const { Parallelogram::print(); }
284 private:
285 // no private data members
286 };
287
288 #endif
289 // P9_13SM.cpp
290 #include "p9_13s.h"
316 Inheritance Solutions Chapter 9
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
291 #include "p9_13pa.h"
292
293 #include <iostream>
294 using std::ostream;
295
296 Square::Square( double x1, double y1, double x2, double y2,
297 double x3, double y3, double x4, double y4 )
298 : Parallelogram( x1, y1, x2, y2, x3, y3, x4, y4 ) { }
299
300 ostream& operator<<( ostream& out, Square& s )
301 {
302 out << "\nThe coordinates of the Square are:\n";
303 s.print();
304 return out;
305 }
306 // P9_13.cpp
307 #include "p9_13.h"
308 #include "p9_13q.h"
309 #include "p9_13t.h"
310 #include "p9_13pa.h"
311 #include "p9_13rh.h"
312 #include "p9_13r.h"
313 #include "p9_13s.h"
314
315 #include <iostream>
316 using std::cout;
317 using std::endl;
318
319 int main()
320 {
321 // NOTE: All coordinates are assumed to form the proper shapes
322
323 // A quadrilateral is a four-sided polygon
324 Quadrilateral q( 1.1, 1.2, 6.6, 2.8, 6.2, 9.9, 2.2, 7.4 );
325 // A trapazoid is a quadrilateral having two and only two parallel sides
326 Trapazoid t( 5.0, 0.0, 0.0, 10.0, 0.0, 8.0, 5.0, 3.3, 5.0 );
327 // A parallelogram is a quadrilateral whose opposite sides are parallel
328 Parallelogram p( 5.0, 5.0, 11.0, 5.0, 12.0, 20.0, 6.0, 20.0 );
329 // A rhombus is an equilateral parallelogram
330 Rhombus rh( 0.0, 0.0, 5.0, 0.0, 8.5, 3.5, 3.5, 3.5 );
331 // A rectangle is an equiangular parallelogram
332 Rectangle r( 17.0, 14.0, 30.0, 14.0, 30.0, 28.0, 17.0, 28.0 );
333 // A square is an equiangular and equilateral parallelogram
334 Square s( 4.0, 0.0, 8.0, 0.0, 8.0, 4.0, 4.0, 4.0 );
335
336 cout << q << t << p << rh << r << s << endl;
337
338 return 0;
339 }
Chapter 9 Inheritance Solutions 317
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
9.14 Write down all the shapes you can think of—both two-dimensional and three-dimensional—and form those shapes into a
shape hierarchy. Your hierarchy should have base class Shape from which class TwoDimensionalShape and class ThreeD-
imensionalShape are derived. Once you have developed the hierarchy, define each of the classes in the hierarchy. We will use
this hierarchy in the exercises of Chapter 10 to process all shapes as objects of base-class Shape. This is a technique called poly-
morphism.
ANS: Shape
TwoDimensionalShape
Quadrilateral
Parallelogram
Rectangle
Square
Rhombus
Ellipse
Circle
Triangle
RightTriangle
EquilateralTriangle
IsocelesTriangle
Parabola
Line
Hyperbola
ThreeDimensionalShape
Ellipsoid
Sphere
Prism
Cylinder
Cone
Cube
Tetrahedron
Hyperboloid
OneSheetHyperboloid
TwoSheetHyperboloid
Plane
Coordinates of Quadrilateral are:
(1.1, 1.2) , (6.6, 2.8) , (6.2, 9.9) , (2.2, 7.4)
The Coordinates of the Trapazoid are:
(0, 0) , (10, 0) , (8, 5) , (3.3, 5)
Height is : 5
The coordinates of the Parallelogram are:
(5, 5) , (11, 5) , (12, 20) , (6, 20)
The coordinates of the Rhombus are:
(0, 0) , (5, 0) , (8.5, 3.5) , (3.5, 3.5)
The coordinates of the Rectangle are:
(17, 14) , (30, 14) , (30, 28) , (17, 28)
The coordinates of the Square are:
(4, 0) , (8, 0) , (8, 4) , (4, 4)
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
10
Virtual Functions
and Polymorphism
Solutions
Solutions
10.2 What are virtual functions? Describe a circumstance in which virtual functions would be appropriate.
ANS: Virtual functions are functions with the same function prototype that are defined throughout a class hierarchy. At
least the base class occurrence of the function is preceded by the keyword virtual. Virtual functions are used to enable
generic processing of an entire class hierarchy of objects through a base class pointer. For example, in a shape hierarchy,
all shapes can be drawn. If all shapes are derived from a base class Shape which contains a virtual draw function,
then generic processing of the hierarchy can be performed by calling every shape’s draw generically through a base class
Shape pointer.
10.3 Given that constructors cannot be virtual, describe a scheme for how you might achieve a similar effect.
ANS: Create a virtual function called initialize that the constructor invokes.
10.4 How is it that polymorphism enables you to program “in the general” rather than “in the specific.” Discuss the key advan-
tages of programming “in the general.”
ANS: Polymorphism enables the programmer to concentrate on the processing of common operations that are applied to
all data types in the system without going into the individual details of each data type. The general processing capabilities
are separated from the internal details of each type.
10.5 Discuss the problems of programming with switch logic. Explain why polymorphism is an effective alternative to using
switch logic.
ANS: The main problem with programming using the switch structure is extensibility and maintainability of the pro-
gram. A program containing many switch structures is difficult to modify. Many, but not necessarily all, switch struc-
tures will need to add or remove cases for a specified type. Note: switch logic includes if/else structures which are more
flexible than the switch structure.
10.6 Distinguish between static binding and dynamic binding. Explain the use of virtual functions and the vtable in dynamic
binding.
ANS: Static binding is performed at compile-time when a function is called via a specific object or via a pointer to an
object. Dynamic binding is performed at run-time when a virtual function is called via a base class pointer to a derived
class object (the object can be of any derived class). The virtual functions table (vtable) is used at run-time to enable
the proper function to be called for the object to which the base class pointer "points". Each class containing virtual
functions has its own vtable that specifies where the virtual functions for that class are located. Every object of a class
with virtual functions contains a hidden pointer to the class’s vtable. When a virtual function is called via a base
class pointer, the hidden pointer is dereferenced to locate the vtable, then the vtable is searched for the proper function call.
Chapter 10 Solutions Virtual Functions and Polymorphism Solutions 319
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
10.7 Distinguish between inheriting interface and inheriting implementation. How do inheritance hierarchies designed for inher-
iting interface differ from those designed for inheriting implementation?
ANS: When a class inherits implementation, it inherits previously defined functionality from another class. When a class
inherits interface, it inherits the definition of what the interface to the new class type should be. The implementation is then
provided by the programmer defining the new class type. Inheritance hierarchies designed for inheriting implementation
are used to reduce the amont of new code that is being written. Such hierarchies are used to facilitate software reusability.
Inheritance hierarchies designed for inheriting interface are used to write programs that perform generic processing of many
class types. Such hierarchies are commonly used to facilitate software extensibility (i.e., new types can be added to the hier-
archy without changing the generic processing capabilitiesof the program.)
10.8 Distinguish between virtual functions and pure virtual functions.
ANS: A virtual function must have a definition in the class in which it is declared. A pure virtual function does not
provide a definition. Classes derived directly from the abstract class must provide definitions for the inherited pure vir-
tual functions in order to avoid becoming an abstract base class.
10.9 (True/False) All virtual functions in an abstract base class must be declared as pure virtual functions.
ANS: False.
10.10 Suggest one or more levels of abstract base classes for the Shape hierarchy discussed in this chapter (the first level is
Shape and the second level consists of the classes TwoDimensionalShape and ThreeDimensionalShape).
10.11 How does polymorphism promote extensibility?
ANS: Polymorphism makes programs more extensible by making all function calls generic. When a new class type with
the appropriate virtual functions is added to the hierarchy, no changes need to be made to the generic function calls.
10.12 You have been asked to develop a flight simulator that will have elaborate graphical outputs. Explain why polymorphic
programming would be especially effective for a problem of this nature.
10.13 Develop a basic graphics package. Use the Shape class inheritance hierarchy from Chapter 9. Limit yourself to two-di-
mensional shapes such as squares, rectangles, triangles and circles. Interact with the user. Let the user specify the position, size,
shape and fill characters to be used in drawing each shape. The user can specify many items of the same shape. As you create each
shape, place a Shape * pointer to each new Shape object into an array. Each class has its own draw member function. Write a
polymorphic screen manager that walks through the array (preferably using an iterator) sending draw messages to each object in
the array to form a screen image. Redraw the screen image each time the user specifies an additional shape.
10.14 Modify the payroll system of Fig. 10.1 to add private data members birthDate (a Date object) and departmentCode
(an int) to class Employee. Assume this payroll is processed once per month. Then, as your program calculates the payroll for
each Employee (polymorphically), add a $100.00 bonus to the person’s payroll amount if this is the month in which the Employ-
ee’s birthday occurs.
1// EMPLOY.H
2// Abstract base class Employee
3#ifndef EMPLOY_H
4#define EMPLOY_H
5
6#include "date.h"
7
8class Employee {
9public:
10 Employee( const char * const, const char * const,
11 int, int, int, int);
12 ~Employee();
13 const char *getFirstName() const;
14 const char *getLastName() const;
15 Date getBirthDate() const;
16 int getDepartmentCode() const;
17
18 // Pure virtual functions make Employee abstract base class.
19 virtual double earnings() const = 0; // pure virtual
20 virtual void print() const = 0; // pure virtual
21 private:
22 char *firstName;
23 char *lastName;
320 Virtual Functions and Polymorphism Solutions Chapter 10 Solutions
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
24 Date birthDate;
25 int departmentCode;
26 };
27
28 #endif
29 // EMPLOY.CPP
30 // Member function definitions for
31 // abstract base class Employee.
32 //
33 // Note: No definitions given for pure virtual functions.
34
35 #include <cstring>
36
37 #include <assert.h>
38 #include "employ.h"
39
40 // Constructor dynamically allocates space for the
41 // first and last name and uses strcpy to copy
42 // the first and last names into the object.
43 Employee::Employee( const char * const first, const char * const last,
44 int mn, int dy, int yr, int dept )
45 birthDate( mn, dy, yr ), departmentCode( dept )
46 {
47 firstName = new char[ strlen( first ) + 1 ];
48 assert( firstName != 0 ); // test that new worked
49 strcpy( firstName, first );
50
51 lastName = new char[ strlen( last ) + 1 ];
52 assert( lastName != 0 ); // test that new worked
53 strcpy( lastName, last );
54 }
55
56 // Destructor deallocates dynamically allocated memory
57 Employee::~Employee()
58 {
59 delete [] firstName;
60 delete [] lastName;
61 }
62
63 // Return a pointer to the first name
64 const char *Employee::getFirstName() const
65 {
66 // Const prevents caller from modifying private data.
67 // Caller should copy returned string before destructor
68 // deletes dynamic storage to prevent undefined pointer.
69
70 return firstName; // caller must delete memory
71 }
72
73 // Return a pointer to the last name
74 const char *Employee::getLastName() const
75 {
76 // Const prevents caller from modifying private data.
77 // Caller should copy returned string before destructor
78 // deletes dynamic storage to prevent undefined pointer.
79
80 return lastName; // caller must delete memory
81 }
82
83 // Return the employee's birth date
Chapter 10 Solutions Virtual Functions and Polymorphism Solutions 321
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
84 Date Employee::getBirthDate() const { return birthDate; }
85
86 // Return the employee's department code
87 int Employee::getDepartmentCode() const { return departmentCode; }
88 // BOSS.H
89 // Boss class derived from Employee
90 #ifndef BOSS_H
91 #define BOSS_H
92 #include "employ.h"
93
94 class Boss : public Employee {
95 public:
96 Boss( const char * const, const char * const, int, int, int,
97 double = 0.0, int = 0 );
98 void setWeeklySalary( double );
99 virtual double earnings() const;
100 virtual void print() const;
101 private:
102 double weeklySalary;
103 };
104
105 #endif
106 // BOSS.CPP
107 // Member function definitions for class Boss
108 #include <iostream>
109
110 using std::cout;
111
112 #include "boss.h"
113
114 // Constructor function for class Boss
115 Boss::Boss( const char * const first, const char * const last,
116 int mn, int dy, int yr, double s, int dept )
117 : Employee( first, last, mn, dy, yr, dept )
118 { weeklySalary = s > 0 ? s : 0; }
119
120 // Set the Boss's salary
121 void Boss::setWeeklySalary( double s )
122 { weeklySalary = s > 0 ? s : 0; }
123
124 // Get the Boss's pay
125 double Boss::earnings() const { return weeklySalary; }
126
127 // Print the Boss's name
128 void Boss::print() const
129 {
130 cout << "\nBoss: " << getFirstName()
131 << ' ' << getLastName();
132 }
133 // HOURLY.H
134 // Definition of class HourlyWorker
135 #ifndef HOURLY_H
136 #define HOURLY_H
137 #include "employ.h"
138
322 Virtual Functions and Polymorphism Solutions Chapter 10 Solutions
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
139 class HourlyWorker : public Employee {
140 public:
141 HourlyWorker( const char * const, const char * const, int, int, int,
142 double = 0.0, double = 0.0, int = 0 );
143 void setWage( double );
144 void setHours( double );
145 virtual double earnings() const;
146 virtual void print() const;
147 private:
148 double wage; // wage per hour
149 double hours; // hours worked for week
150 };
151
152 #endif
153 // HOURLY.CPP
154 // Member function definitions for class HourlyWorker
155 #include <iostream>
156
157 using std::cout;
158
159 #include "hourly.h"
160
161 // Constructor for class HourlyWorker
162 HourlyWorker::HourlyWorker( const char * const first, const char * const last,
163 int mn, int dy, int yr, double w, double h, int dept )
164 : Employee( first, last, mn, dy, yr, dept )
165 {
166 wage = w > 0 ? w : 0;
167 hours = h >= 0 && h < 168 ? h : 0;
168 }
169
170 // Set the wage
171 void HourlyWorker::setWage( double w ) { wage = w > 0 ? w : 0; }
172
173 // Set the hours worked
174 void HourlyWorker::setHours( double h )
175 { hours = h >= 0 && h < 168 ? h : 0; }
176
177 // Get the HourlyWorker's pay
178 double HourlyWorker::earnings() const { return wage * hours; }
179
180 // Print the HourlyWorker's name
181 void HourlyWorker::print() const
182 {
183 cout << "\nHourly worker: " << getFirstName()
184 << ' ' << getLastName();
185 }
186 // PIECE.H
187 // PieceWorker class derived from Employee
188 #ifndef PIECE_H
189 #define PIECE_H
190 #include "employ.h"
191
192 class PieceWorker : public Employee {
193 public:
194 PieceWorker( const char * const, const char * const, int, int, int,
195 double = 0.0, unsigned = 0, int = 0 );
Chapter 10 Solutions Virtual Functions and Polymorphism Solutions 323
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
196 void setWage( double );
197 void setQuantity( unsigned );
198 virtual double earnings() const;
199 virtual void print() const;
200 private:
201 double wagePerPiece; // wage for each piece output
202 unsigned quantity; // output for week
203 };
204
205 #endif
206 // PIECE.CPP
207 // Member function definitions for class PieceWorker
208 #include <iostream>
209
210 using std::cout;
211
212 #include "piece.h"
213
214 // Constructor for class PieceWorker
215 PieceWorker::PieceWorker( const char * const first, const char * const last,
216 int mn, int dy, int yr, double w, unsigned q, int dept )
217 : Employee( first, last, mn, dy, yr, dept )
218 {
219 wagePerPiece = w > 0 ? w : 0;
220 quantity = q > 0 ? q : 0;
221 }
222
223 // Set the wage
224 void PieceWorker::setWage( double w )
225 { wagePerPiece = w > 0 ? w : 0; }
226
227 // Set the number of items output
228 void PieceWorker::setQuantity( unsigned q )
229 { quantity = q > 0 ? q : 0; }
230
231 // Determine the PieceWorker's earnings
232 double PieceWorker::earnings() const
233 { return quantity * wagePerPiece; }
234
235 // Print the PieceWorker's name
236 void PieceWorker::print() const
237 {
238 cout << "\nPiece worker: " << getFirstName()
239 << ' ' << getLastName();
240 }
241 // COMMIS.H
242 // CommissionWorker class derived from Employee
243 #ifndef COMMIS_H
244 #define COMMIS_H
245 #include "employ.h"
246
247 class CommissionWorker : public Employee {
248 public:
249 CommissionWorker(const char * const, const char * const, int, int, int,
250 double = 0.0, double = 0.0, unsigned = 0, int = 0 );
251 void setSalary( double );
252 void setCommission( double );
324 Virtual Functions and Polymorphism Solutions Chapter 10 Solutions
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
253 void setQuantity( unsigned );
254 virtual double earnings() const;
255 virtual void print() const;
256 private:
257 double salary; // base salary per week
258 double commission; // amount per item sold
259 unsigned quantity; // total items sold for week
260 };
261
262 #endif
263 // COMMIS.CPP
264 // Member function definitions for class CommissionWorker
265 #include <iostream>
266
267 using std::cout;
268
269 #include "commis.h"
270
271 // Constructor for class CommissionWorker
272 CommissionWorker::CommissionWorker( const char * const first,
273 const char * const last, int mn, int dy, int yr,
274 double s, double c, unsigned q, int dept )
275 : Employee( first, last, mn, dy, yr, dept )
276 {
277 salary = s > 0 ? s : 0;
278 commission = c > 0 ? c : 0;
279 quantity = q > 0 ? q : 0;
280 }
281
282 // Set CommissionWorker's weekly base salary
283 void CommissionWorker::setSalary( double s )
284 { salary = s > 0 ? s : 0; }
285
286 // Set CommissionWorker's commission
287 void CommissionWorker::setCommission( double c )
288 { commission = c > 0 ? c : 0; }
289
290 // Set CommissionWorker's quantity sold
291 void CommissionWorker::setQuantity( unsigned q )
292 { quantity = q > 0 ? q : 0; }
293
294 // Determine CommissionWorker's earnings
295 double CommissionWorker::earnings() const
296 { return salary + commission * quantity; }
297
298 // Print the CommissionWorker's name
299 void CommissionWorker::print() const
300 {
301 cout << "\nCommission worker: " << getFirstName()
302 << ' ' << getLastName();
303 }
304 // DATE.H
305 // Declaration of the Date class.
306 // Member functions defined in DATE1.CPP
307 #ifndef DATE_H
308 #define DATE_H
309
Chapter 10 Solutions Virtual Functions and Polymorphism Solutions 325
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
310 class Date {
311 public:
312 Date( int = 1, int = 1, int = 1900 ); // default constructor
313 int getMonth() const; // return the month
314 int getDay() const; // return the day
315 int getYear()const; // return the year
316 void print() const; // print date in month/day/year format
317 private:
318 int month; // 1-12
319 int day; // 1-31 based on month
320 int year; // any year
321
322 // utility function to test proper day for month and year
323 int checkDay( int ) const;
324 };
325
326 #endif
327 // DATE.CPP
328 // Member function definitions for Date class.
329 #include <iostream>
330
331 using std::cout;
332
333 #include "date.h"
334
335 // Constructor: Confirm proper value for month;
336 // call utility function checkDay to confirm proper
337 // value for day.
338 Date::Date( int mn, int dy, int yr )
339 {
340 if ( mn > 0 && mn <= 12 ) // validate the month
341 month = mn;
342 else {
343 month = 1;
344 cout << "Month " << mn << " invalid. Set to month 1.\n";
345 }
346
347 year = yr >= 1900 && yr <= 2100 ? yr : 1990;
348 day = checkDay( dy ); // validate the day
349 }
350
351 // Utility function to confirm proper day value
352 // based on month and year.
353 int Date::checkDay( int testDay ) const
354 {
355 int daysPerMonth[ 13 ] = { 0, 31, 28, 31, 30, 31, 30,
356 31, 31, 30, 31, 30, 31 };
357
358 if ( testDay > 0 && testDay <= daysPerMonth[ month ] )
359 return testDay;
360
361 if ( month == 2 && // February: Check for possible leap year
362 testDay == 29 &&
363 ( year % 400 == 0 || (year % 4 == 0 && year % 100 != 0 ) ) )
364 return testDay;
365
366 cout << "Day " << testDay << " invalid. Set to day 1.\n";
367
368 return 1; // leave object in consistent state if bad value
369 }
326 Virtual Functions and Polymorphism Solutions Chapter 10 Solutions
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
370
371 // Return the month
372 int Date::getMonth() const { return month; }
373
374 // Return the day
375 int Date::getDay() const { return day; }
376
377 // Return the year
378 int Date::getYear() const { return year; }
379
380 // Print Date object in form month/day/year
381 void Date::print() const
382 { cout << month << '/' << day << '/' << year; }
383 // Exercise 10.14 solution
384 // Driver for Employee hierarchy
385 #include <iostream>
386
387 using std::cout;
388 using std::endl;
389 using std::ios;
390
391 #include <iomanip>
392
393 using std::setprecision;
394 using std::setiosflags;
395
396 #include <ctime>
397 #include <cstdlib>
398 #include "employ.h"
399 #include "boss.h"
400 #include "commis.h"
401 #include "piece.h"
402 #include "hourly.h"
403
404 int determineMonth();
405
406 int main()
407 {
408 // set output formatting
409 cout << setiosflags( ios::fixed | ios::showpoint )
410 << setprecision( 2 );
411
412 Boss b( "John", "Smith", 6, 15, 1944, 800.00, 1 );
413 CommissionWorker c( "Sue", "Jones", 9, 8, 1954, 200.0, 3.0, 150, 1 );
414 PieceWorker p( "Bob", "Lewis", 3, 2, 1965, 2.5, 200, 1 );
415 HourlyWorker h( "Karen", "Price", 12, 29, 1960, 13.75, 40, 1 );
416
417 Employee *ptr[ 4 ] = { &b, &c, &p, &h };
418
419 int month = determineMonth();
420
421 cout << "The month is " << month << "\nThe payroll is:\n";
422
423 for ( int x = 0; x < 4; ++x ) {
424 ptr[ x ]->print();
425 cout << " of department " << ptr[ x ]->getDepartmentCode()
426 << "\n whose birthday is ";
427 ptr[ x ]->getBirthDate().print();
428 cout << " earned ";
429
Chapter 10 Solutions Virtual Functions and Polymorphism Solutions 327
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
10.15 In Exercise 9.14, you developed a Shape class hierarchy and defined the classes in the hierarchy. Modify the hierarchy so
that class Shape is an abstract base class containing the interface to the hierarchy. Derive TwoDimensionalShape and
ThreeDimensionalShape from class Shape—these classes should also be abstract. Use a virtual print function to out-
put the type and dimensions of each class. Also include virtual area and volume functions so these calculations can be per-
formed for objects of each concrete class in the hierarchy. Write a driver program that tests the Shape class hierarchy.
430 if ( ptr[ x ]->getBirthDate().getMonth() == month )
431 cout << ptr[ x ]->earnings() + 100.0
432 << " HAPPY BIRTHDAY!\n";
433 else
434 cout << ptr[x]->earnings() << endl;
435
436
437 return 0;
438 }
439
440 // Determine the current month using standard library functions
441 // of ctime.
442 int determineMonth()
443 {
444 time_t currentTime;
445 char monthString[ 3 ];
446
447 time( &currentTime );
448 strftime( monthString, 3, "%m", localtime( &currentTime ) );
449 return atoi( monthString );
450 }
The month is 5
The payroll is:
Boss: John Smith of department 1
whose birthday is 6/15/1944 earned 800.00
Commission worker: Sue Jones of department 1
whose birthday is 9/8/1954 earned 650.00
Piece worker: Bob Lewis of department 1
whose birthday is 3/2/1965 earned 500.00
Hourly worker: Karen Price of department 1
whose birthday is 12/29/1960 earned 550.00
1// SHAPE.H
2// Definition of base-class Shape
3#ifndef SHAPE_H
4#define SHAPE_H
5
6#include <iostream>
7using std::ostream;
8
9class Shape {
10 friend ostream & operator<<( ostream &, Shape & );
11 public:
12 Shape( double = 0, double = 0 );
13 double getCenterX() const;
14 double getCenterY() const;
15 virtual void print() const = 0;
16 protected:
328 Virtual Functions and Polymorphism Solutions Chapter 10 Solutions
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
17 double xCenter;
18 double yCenter;
19 };
20
21 #endif
22 // SHAPE.CPP
23 // Member and friend definitions for Shape
24 #include "shape.h"
25
26 Shape::Shape( double x, double y )
27 {
28 xCenter = x;
29 yCenter = y;
30 }
31
32 double Shape::getCenterX() const { return xCenter; }
33
34 double Shape::getCenterY() const { return yCenter; }
35
36 ostream & operator<<( ostream &out, Shape &s )
37 {
38 s.print();
39 return out;
40 }
41 // TWODIM.H
42 // Defnition of class TwoDimensionalShape
43 #ifndef TWODIM_H
44 #define TWODIM_H
45
46 #include "shape.h"
47
48 class TwoDimensionalShape : public Shape {
49 public:
50 TwoDimensionalShape( double x, double y ) : Shape( x, y ) { }
51 virtual double area() const = 0;
52 };
53
54 #endif
55 // THREEDIM.H
56 // Defnition of class ThreeDimensionalShape
57 #ifndef THREEDIM_H
58 #define THREEDIM_H
59
60 #include "shape.h"
61
62 class ThreeDimensionalShape : public Shape {
63 public:
64 ThreeDimensionalShape( double x, double y ) : Shape( x, y ) { }
65 virtual double area() const = 0;
66 virtual double volume() const = 0;
67 };
68
69 #endif
Chapter 10 Solutions Virtual Functions and Polymorphism Solutions 329
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
70 // CIRCLE.H
71 // Definition of class Circle
72 #ifndef CIRCLE_H
73 #define CIRCLE_H
74
75 #include "twodim.h"
76
77 class Circle : public TwoDimensionalShape {
78 public:
79 Circle( double = 0, double = 0, double = 0 );
80 double getRadius() const;
81 double area() const;
82 void print() const;
83 private:
84 double radius;
85 };
86
87 #endif
88 // CIRCLE.CPP
89 // Member function definitions for Circle
90 #include "circle.h"
91
92 #include <iostream>
93 using std::cout;
94
95 Circle::Circle( double r, double x, double y )
96 : TwoDimensionalShape( x, y ) { radius = r > 0 ? r : 0; }
97
98 double Circle::getRadius() const { return radius; }
99
100 double Circle::area() const { return 3.14159 * radius * radius; }
101
102 void Circle::print() const
103 {
104 cout << "Circle with radius " << radius << "; center at ("
105 << xCenter << ", " << yCenter << ");\narea of " << area() << '\n';
106 }
107 // SQUARE.H
108 // Definition of class Square
109 #ifndef SQUARE_H
110 #define SQUARE_H
111
112 #include "twodim.h"
113
114 class Square : public TwoDimensionalShape {
115 public:
116 Square( double = 0, double = 0, double = 0 );
117 double getSideLength() const;
118 double area() const;
119 void print() const;
120 private:
121 double sideLength;
122 };
123
124 #endif
330 Virtual Functions and Polymorphism Solutions Chapter 10 Solutions
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
125 // SQUARE.CPP
126 // Member function definitions for Square
127 #include "square.h"
128
129 #include <iostream>
130 using std::cout;
131
132 Square::Square( double s, double x, double y )
133 : TwoDimensionalShape( x, y ) { sideLength = s > 0 ? s : 0; }
134
135 double Square::getSideLength() const { return sideLength; }
136
137 double Square::area() const { return sideLength * sideLength; }
138
139 void Square::print() const
140 {
141 cout << "Square with side length " << sideLength << "; center at ("
142 << xCenter << ", " << yCenter << ");\narea of " << area() << '\n';
143 }
144 // SPHERE.H
145 // Definition of class Shere
146 #ifndef SPHERE_H
147 #define SPHERE_H
148
149 #include "threedim.h"
150
151 class Sphere : public ThreeDimensionalShape {
152 public:
153 Sphere( double = 0, double = 0, double = 0 );
154 double area() const;
155 double volume() const;
156 double getRadius() const;
157 void print() const;
158 private:
159 double radius;
160 };
161
162 #endif
163 // SPHERE.CPP
164 // Member function definitions for Sphere
165 #include "sphere.h"
166
167 #include <iostream>
168 using std::cout;
169
170 Sphere::Sphere( double r, double x, double y )
171 : ThreeDimensionalShape( x, y ) { radius = r > 0 ? r : 0; }
172
173 double Sphere::area() const
174 { return 4.0 * 3.14159 * radius * radius; }
175
176 double Sphere::volume() const
177 { return 4.0/3.0 * 3.14159 * radius * radius * radius; }
178
179 double Sphere::getRadius() const { return radius; }
180
181 void Sphere::print() const
Chapter 10 Solutions Virtual Functions and Polymorphism Solutions 331
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
182 {
183 cout << "Sphere with radius " << radius << "; center at ("
184 << xCenter << ", " << yCenter << ");\narea of "
185 << area() << "; volume of " << volume() << '\n';
186 }
187 // CUBE.H
188 // Definition of class Cube
189 #ifndef CUBE_H
190 #define CUBE_H
191
192 #include "threedim.h"
193
194 class Cube : public ThreeDimensionalShape {
195 public:
196 Cube( double = 0, double = 0, double = 0 );
197 double area() const;
198 double volume() const;
199 double getSideLength() const;
200 void print() const;
201 private:
202 double sideLength;
203 };
204
205 #endif
206 // CUBE.CPP
207 // Member function definitions for Cube
208 #include "cube.h"
209
210 #include <iostream>
211 using std::cout;
212
213 Cube::Cube( double s, double x, double y )
214 : ThreeDimensionalShape( x, y ) { sideLength = s > 0 ? s : 0; }
215
216 double Cube::area() const { return 6 * sideLength * sideLength; }
217
218 double Cube::volume() const
219 { return sideLength * sideLength * sideLength; }
220
221 double Cube::getSideLength() const { return sideLength; }
222
223 void Cube::print() const
224 {
225 cout << "Cube with side length " << sideLength << "; center at ("
226 << xCenter << ", " << yCenter << ");\narea of "
227 << area() << "; volume of " << volume() << '\n';
228 }
229 // Exercise 10.15 solution
230 // Driver to test Shape hierarchy
231 #include <iostream>
232
233 using std::cout;
234
235 #include "circle.h"
332 Virtual Functions and Polymorphism Solutions Chapter 10 Solutions
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
236 #include "square.h"
237 #include "sphere.h"
238 #include "cube.h"
239
240 int main()
241 {
242 Circle cir( 3.5, 6, 9 );
243 Square sqr( 12, 2, 2 );
244 Sphere sph( 5, 1.5, 4.5 );
245 Cube cub( 2.2 );
246 Shape *ptr[ 4 ] = { &cir, &sqr, &sph, &cub };
247
248 for ( int x = 0; x < 4; ++x )
249 cout << *( ptr[ x ] ) << '\n';
250
251 return 0;
252 }
Circle with radius 3.5; center at (6, 9);
area of 38.4845
Square with side length 12; center at (2, 2);
area of 144
Sphere with radius 5; center at (1.5, 4.5);
area of 314.159; volume of 523.598
Cube with side length 2.2; center at (0, 0);
area of 29.04; volume of 10.648
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
11
C++ Stream
Input/Output
Solutions
Solutions
11.6 Write a statement for each of the following:
a) Print integer 40000 left-justified in a 15-digit field.
ANS: cout << setiosflags( ios::left ) << setw( 15 ) << 40000 << ’\n’;
b) Read a string into character array variable state.
ANS: cin >> state;
c) Print 200 with and without a sign.
ANS:
cout << setiosflags( ios::showpos ) << 200 << setw( 4 ) << ‘\n’
<< resetiosflags( ios::showpos ) << 200 << ’\n’;
d) Print the decimal value 100 in hexadecimal form preceded by 0x.
ANS: cout << setiosflags( ios::showbase ) << hex << 100 << ’\n’;
e) Read characters into array s until the character 'p' is encountered up to a limit of 10 characters (including the termi-
nating null character). Extract the delimiter from the input stream and discard it.
ANS: cin.getline( s, 10, ’p’ );
f) Print 1.234 in a 9-digit field with preceding zeros.
ANS:
cout << setiosflags( ios::fixed | ios::showpoint ) << setw( 9 )
<< setfill( ’0’ ) << setiosflags( ios::internal ) << 1.234 << ’\n’;
g) Read a string of the form "characters" from the standard input. Store the string in character array s. Eliminate the
quotation marks from the input stream. Read a maximum of 50 characters (including the terminating null character).
11.7 Write a program to test inputting integer values in decimal, octal and hexadecimal format. Output each integer read by the
program in all three formats. Test the program with the following input data: 10, 010, 0x10.
1// Exercise 11.7 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
334 C++ Stream Input/Output Solutions Chapter 11
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
9#include <iomanip>
10
11 using std::setiosflags;
12 using std::hex;
13 using std::oct;
14 using std::dec;
15
16 int main()
17 {
18 int integer;
19
20 cout << "Enter an integer: ";
21 cin >> integer;
22
23 cout << setiosflags( ios::showbase ) << "As a decimal number " << dec
24 << integer << "\nAs an octal number " << oct << integer
25 << "\nAs a hexadecimal number " << hex << integer << endl;
26
27 cout << "\nEnter an integer in hexadecimal format\n";
28 cin >> hex >> integer;
29
30 cout << setiosflags( ios::showbase ) << "As a decimal number " << dec
31 << integer << "\nAs an octal number " << oct << integer
32 << "\nAs a hexadecimal number " << hex << integer << endl;
33
34 cout << "\nEnter an integer in octal format\n";
35 cin >> oct >> integer;
36
37 cout << setiosflags( ios::showbase ) << "As a decimal number " << dec
38 << integer << "\nAs an octal number " << oct << integer
39 << "\nAs a hexadecimal number " << hex << integer << endl;
40
41
42 return 0;
43 }
Enter an integer: 10
As a decimal number 10
As an octal number 012
As a hexadecimal number 0xa
Enter an integer in hexadecimal format
0x10
As a decimal number 16
As an octal number 020
As a hexadecimal number 0x10
Enter an integer in octal format
010
As a decimal number 8
As an octal number 010
As a hexadecimal number 0x8
Chapter 11 C++ Stream Input/Output Solutions 335
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
11.8 Write a program that prints pointer values using casts to all the integer data types. Which ones print strange values? Which
ones cause errors?
11.9 Write a program to test the results of printing the integer value 12345 and the floating-point value 1.2345 in various-
size fields. What happens when the values are printed in fields containing fewer digits than the values?
1// Exercise 11.8 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7int main()
8{
9 char *string = "test";
10
11 cout << "Value of string is : " << string << '\n'
12 << "Value of static_cast<void *>( string ) is : "
13 << static_cast<void *>( string ) << '\n'
14
15 // The Following generate errors.
16 // reinterpret_cast will allow this
17 // type of casting. See Chap. 21 for
18 // a discussion of reinterpret_cast.
19
20 /* << "Value of static_cast<char>(string) is : "
21 << static_cast<char>( string ) << '\n'
22 << "Value of static_cast<int>(string) is : "
23 << static_cast<int>( string ) << '\n'
24 << "Value of static_cast<long>(string) is : "
25 << static_cast<long>( string ) << '\n'
26 << "Value of static_cast<short>(string) is : "
27 << static_cast<short>( string ) << '\n'
28 << "Value of static_cast<unsigned>(string) is : "
29 << static_cast<unsigned>( string )
30 */
31 << endl;
32
33 return 0;
34 }
Value of string is : test
Value of static_cast<void *>(string) is : 0046C07C
1// Exercise 11.9 Solution
2#include <iostream>
3
4using std::cout;
5
6#include <iomanip>
7
8using std::setw;
9
10 int main()
11 {
12 int x = 12345;
13 double y = 1.2345;
14
15 for ( int loop = 0; loop <= 10; ++loop )
336 C++ Stream Input/Output Solutions Chapter 11
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
11.10 Write a program that prints the value 100.453627 rounded to the nearest digit, tenth, hundredth, thousandth and ten thou-
sandth.
16 cout << x << " printed in a field of size " << loop << " is "
17 << setw( loop ) << x << '\n' << y << " printed in a field "
18 << "of size " << loop << " is " << setw( loop ) << y << '\n';
19
20 return 0;
21 }
12345 printed in a field of size 0 is 12345
1.2345 printed in a field of size 0 is 1.2345
12345 printed in a field of size 1 is 12345
1.2345 printed in a field of size 1 is 1.2345
12345 printed in a field of size 2 is 12345
1.2345 printed in a field of size 2 is 1.2345
12345 printed in a field of size 3 is 12345
1.2345 printed in a field of size 3 is 1.2345
12345 printed in a field of size 4 is 12345
1.2345 printed in a field of size 4 is 1.2345
12345 printed in a field of size 5 is 12345
1.2345 printed in a field of size 5 is 1.2345
12345 printed in a field of size 6 is 12345
1.2345 printed in a field of size 6 is 1.2345
12345 printed in a field of size 7 is 12345
1.2345 printed in a field of size 7 is 1.2345
12345 printed in a field of size 8 is 12345
1.2345 printed in a field of size 8 is 1.2345
12345 printed in a field of size 9 is 12345
1.2345 printed in a field of size 9 is 1.2345
12345 printed in a field of size 10 is 12345
1.2345 printed in a field of size 10 is 1.2345
1// Exercise 11.10 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::ios;
7
8#include <iomanip>
9
10 using std::setprecision;
11 using std::setiosflags;
12
13 int main()
14 {
15 double x = 100.453627;
16
17 cout << setiosflags( ios::fixed );
18 for ( int loop = 0; loop <= 5; ++loop )
19 cout << setprecision( loop ) << "Rounded to " << loop
20 << " digit(s) is " << x << endl;
21
22 return 0;
23 }
Chapter 11 C++ Stream Input/Output Solutions 337
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
11.11 Write a program that inputs a string from the keyboard and determines the length of the string. Print the string using twice
the length as the field width
11.12 Write a program that converts integer Fahrenheit temperatures from 0 to 212 degrees to floating-point Celsius tempera-
tures with 3 digits of precision. Use the formula
celsius = 5.0 / 9.0 * ( fahrenheit - 32 );
to perform the calculation. The output should be printed in two right-justified columns and the Celsius temperatures should be pre-
ceded by a sign for both positive and negative values.
Rounded to 0 digit(s) is 100
Rounded to 1 digit(s) is 100.5
Rounded to 2 digit(s) is 100.45
Rounded to 3 digit(s) is 100.454
Rounded to 4 digit(s) is 100.4536
Rounded to 5 digit(s) is 100.45363
1// Exercise 11.11 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <iomanip>
9
10 using std::setw;
11
12 #include <cstring>
13
14 const int SIZE = 80;
15
16 int main()
17 {
18 char string[ SIZE ];
19 int stringLength;
20
21 cout << "Enter a string: ";
22 cin >> string;
23
24 stringLength = strlen( string );
25
26 cout << "the length of the string is " << strlen( string ) << endl;
27
28 // print string using twice the length as field with
29 cout << setw( 2 * stringLength ) << string << endl;
30
31 return 0;
32 }
Enter a string: castle
the length of the string is 6
castle
338 C++ Stream Input/Output Solutions Chapter 11
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
11.13 In some programming languages, strings are entered surrounded by either single or double quotation marks. Write a pro-
gram that reads the three strings suzy, "suzy" and 'suzy'. Are the single and double quotes ignored or read as part of the string?
1// Exercise 11.12 Solution
2#include <iostream>
3
4using std::cout;
5using std::ios;
6
7#include <iomanip>
8
9using std::setw;
10 using std::setprecision;
11 using std::setiosflags;
12 using std::resetiosflags;
13
14 int main()
15 {
16 double celsius;
17
18 cout << setw( 20 ) << "Fahrenheit " << setw( 20 ) << "Celsius\n"
19 << setiosflags( ios::fixed | ios::showpoint );
20
21 for ( int fahrenheit = 0; fahrenheit <= 212; ++fahrenheit ) {
22 celsius = 5.0 / 9.0 * ( fahrenheit - 32 );
23 cout << setw( 15 ) << resetiosflags( ios::showpos ) << fahrenheit
24 << setw( 23 ) << setprecision( 3 ) << setiosflags( ios::showpos )
25 << celsius << '\n';
26 }
27
28 return 0;
29 }
Fahrenheit Celsius
0 -17.778
1 -17.222
2 -16.667
3 -16.111
4 -15.556
...
206 +96.667
207 +97.222
208 +97.778
209 +98.333
210 +98.889
211 +99.444
212 +100.000
1// Exercise 11.13 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6
7const int SIZE = 80;
8
9int main()
Chapter 11 C++ Stream Input/Output Solutions 339
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
11.14 In Fig. 8.3, the stream-extraction and -insertion operators were overloaded for input and output of objects of the Phone-
Number class. Rewrite the stream-extraction operator to perform the following error checking on input. The operator>> func-
tion will need to be entirely recoded.
a) Input the entire phone number into an array. Test that the proper number of characters has been entered. There should
be a total of 14 characters read for a phone number of the form (800) 555-1212. Use the stream member function
clear to set ios::failbit for improper input.
b) The area code and exchange do not begin with 0 or 1. Test the first digit of the area code and exchange portions of the
phone number to be sure that neither begins with 0 or 1. Use stream member function clear to set ios::failbit
for improper input.
c) The middle digit of an area code used to always be 0 or 1 (although this has changed recently). Test the middle digit
for a value of 0 or 1. Use the stream member function clear to set ios::failbit for improper input. If none of
the above operations results in ios::failbit being set for improper input, copy the three parts of the telephone
number into the areaCode, exchange and line members of the PhoneNumber object. In the main program, if
ios::failbit has been set on the input, have the program print an error message and end rather than print the phone
number.
10 {
11 char string[ SIZE ];
12
13 for ( int k = 0; k < 3; ++k ) {
14 cout << "Enter a string: ";
15 cin >> string;
16 cout << "String is " << string << '\n';
17 }
18
19 return 0;
20 }
Enter a string: "vacuum"
String is "vacuum"
Enter a string: 'grape'
String is 'grape'
Enter a string: water
String is water
1// P11_14.H
2#ifndef P11_14_H
3#define P11_14_H
4#include <iostream>
5using std::cout;
6using std::endl;
7using std::cin;
8using std::ios;
9using std::ostream;
10 using std::istream;
11 using std::cerr;
12
13 #include <cstring>
14 #include <cstdlib>
15
16 class PhoneNumber {
17 friend ostream& operator<<( ostream&, PhoneNumber& );
18 friend istream& operator>>( istream&, PhoneNumber& );
19 public:
20 PhoneNumber();
21 private:
22 char phone[ 15 ];
23 char areaCode[ 4 ];
24 char exchange[ 4 ];
340 C++ Stream Input/Output Solutions Chapter 11
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
25 char line[ 5 ];
26 };
27
28 #endif
29 // P11_14M.cpp
30 // member function definition definition for p11_14.cpp
31 #include "p11_14.h"
32
33 PhoneNumber::PhoneNumber()
34 {
35 phone[ 0 ] = '\0';
36 areaCode[ 0 ] = '\0';
37 exchange[ 0 ] = '\0';
38 line[ 0 ] = '\0';
39 }
40
41 ostream &operator<<( ostream &output, PhoneNumber &number )
42 {
43 output << "(" << number.areaCode << ") " << number.exchange
44 << "-" << number.line << '\n';
45
46 return output;
47 }
48
49 istream &operator>>( istream &input, PhoneNumber &number )
50 {
51 cin.getline( number.phone, 15 );
52
53 if ( strlen( number.phone ) != 14 )
54 cin.clear( ios::failbit );
55
56 if ( number.phone[ 1 ] == '0' || number.phone[ 6 ] == '0' ||
57 number.phone[ 1 ] == '1' || number.phone[ 6 ] == '1')
58 cin.clear( ios::failbit );
59
60 if ( number.phone[ 2 ] != '0' && number.phone[ 2 ] != '1' )
61 cin.clear( ios::failbit );
62
63 if ( !cin.fail() ) {
64 for ( int loop = 0; loop <= 2; ++loop ) {
65 number.areaCode[ loop ] = number.phone[ loop + 1 ];
66 number.exchange[ loop ] = number.phone[ loop + 6 ];
67 }
68
69 number.areaCode[ loop ] = number.exchange[ loop ] = '\0';
70
71 for ( loop = 0; loop <= 3; ++loop )
72 number.line[ loop ] = number.phone[ loop + 10 ];
73
74 number.line[ loop ] = '\0';
75 }
76 else {
77 cerr << "Invalid phone number entered.\n";
78 exit( 1 );
79 }
80
81 return input;
82 }
Chapter 11 C++ Stream Input/Output Solutions 341
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
11.15 Write a program that accomplishes each of the following:
a) Create the user-defined class Point that contains the private integer data members xCoordinate and yCoordi-
nate and declares stream-insertion and stream-extraction overloaded operator functions as friends of the class.
b) Define the stream-insertion and stream-extraction operator functions. The stream-extraction operator function should
determine if the data entered are valid data, and if not, it should set the ios::failbit to indicate improper input.
The stream-insertion operator should not be able to display the point after an input error occurred.
c) Write a main function that tests input and output of user-defined class Point using the overloaded stream-extraction
and stream-insertion operators.
83 // driver for p11_14.cpp
84 #include "p11_14.h"
85
86 int main()
87 {
88 PhoneNumber telephone;
89
90 cout << "Enter a phone number in the form (123) 456-7890:\n";
91 cin >> telephone;
92
93 cout << "The phone number entered was: " << telephone << endl;
94
95 cout << "Now enter an invalid phone number:\n";
96 cin >> telephone;
97
98 return 0;
99 }
Enter a phone number in the form (123) 456-7890:
(800) 987-4567
The phone number entered was: (800) 987-4567
Now enter an invalid phone number:
(000) 000-0000
Invalid phone number entered.
1// P11_15.H
2#ifndef P11_15_H
3#define P11_15_H
4#include <iostream.h>
5
6class Point {
7 friend ostream &operator<<( ostream&, Point& );
8 friend istream &operator>>( istream&, Point& );
9private:
10 int xCoordinate;
11 int yCoordinate;
12 };
13
14 #endif
15 // P11_15M.cpp
16 // member function definitions for p11_15.cpp
17 #include "p11_15.h"
18
19 ostream& operator<<( ostream& out, Point& p )
20 {
21 if ( !cin.fail() )
342 C++ Stream Input/Output Solutions Chapter 11
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
11.16 Write a program that accomplishes each of the following:
a) Create the user-defined class Complex that contains the private integer data members real and imaginary, and
declares stream-insertion and stream-extraction overloaded operator functions as friends of the class.
22 cout << "(" << p.xCoordinate << ", " << p.yCoordinate << ")" << '\n';
23 else
24 cout << "\nInvalid data\n";
25
26 return out;
27 }
28
29 istream& operator>>( istream& i, Point& p )
30 {
31 if ( cin.peek() != '(' )
32 cin.clear( ios::failbit );
33 else
34 i.ignore(); // skip (
35
36 cin >> p.xCoordinate;
37
38 if ( cin.peek() != ',' )
39 cin.clear( ios::failbit );
40 else {
41 i.ignore(); // skip ,
42
43 if ( cin.peek() == ' ' )
44 i.ignore(); // skip space
45 else
46 cin.clear( ios::failbit );
47 }
48
49 cin >> p.yCoordinate;
50
51 if ( cin.peek() == ')' )
52 i.ignore(); // skip )
53 else
54 cin.clear( ios::failbit );
55
56 return i;
57 }
58 // driver for p11_15.cpp
59 #include "p11_15.h"
60
61 int main()
62 {
63 Point pt;
64
65 cout << "Enter a point in the form (x, y):\n";
66 cin >> pt;
67
68 cout << "Point entered was: " << pt << endl;
69 return 0;
70 }
Enter a point in the form (x, y):
(7, 8)
Point entered was: (7, 8)
Chapter 11 C++ Stream Input/Output Solutions 343
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
b) Define the stream-insertion and -extraction operator functions. The stream-extraction operator function should deter-
mine if the data entered are valid, and if not, it should set ios::failbit to indicate improper input. The input should
be of the form
3 + 8i
c) The values can be negative or positive, and it is possible that one of the two values is not provided. If a value is not
provided, the appropriate data member should be set to 0. The stream-insertion operator should not be able to display
the point if an input error occurred. The output format should be identical to the input format shown above. For negative
imaginary values, a minus sign should be printed rather than a plus sign.
d) Write a main function that tests input and output of user-defined class Complex using the overloaded stream-extrac-
tion and stream-insertion operators.
1// P11_16.H
2#ifndef P11_16_H
3#define P11_16_H
4#include <iostream>
5
6using std::ostream;
7using std::istream;
8
9class Complex {
10 friend ostream &operator<<( ostream&, Complex& );
11 friend istream &operator>>( istream&, Complex& );
12 public:
13 Complex( void ); // constructor
14 private:
15 int real;
16 int imaginary;
17 };
18
19 #endif
20 // P11_16M.cpp
21 // member function definitions for p11_16.cpp
22
23 #include <iostream>
24
25 using std::cout;
26 using std::cin;
27 using std::ios;
28 using std::ostream;
29 using std::istream;
30
31 #include <iomanip>
32
33 using std::setiosflags;
34 using std::resetiosflags;
35
36 #include "p11_16.h"
37
38 Complex::Complex( void )
39 {
40 real = 0;
41 imaginary = 0;
42 }
43
44 ostream &operator<<( ostream &output, Complex &c )
45 {
46 if ( !cin.fail() )
47 output << c.real
344 C++ Stream Input/Output Solutions Chapter 11
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
48 << setiosflags( ios::showpos )
49 << c.imaginary << "i\n"
50 << resetiosflags( ios::showpos );
51 else
52 output << "Invalid Data Entered" << '\n';
53
54 return output;
55 }
56
57 istream &operator>>( istream &input, Complex &c )
58 {
59 int number, multiplier;
60 char temp;
61
62 input >> number;
63
64 if ( cin.peek() == ' ' ) { // case a + bi
65 c.real = number;
66 cin >> temp;
67
68 multiplier = ( temp == '+' ) ? 1 : -1;
69
70 if ( cin.peek() != ' ' )
71 cin.clear( ios::failbit ); // set bad bit
72 else {
73
74 if ( cin.peek() == ' ' ) {
75 input >> c.imaginary;
76 c.imaginary *= multiplier;
77
78 cin >> temp;
79 if ( cin.peek() != '\n' )
80 cin.clear( ios::failbit ); // set bad bit
81 }
82 else
83 cin.clear( ios::failbit ); // set bad bit
84 }
85 }
86 else if ( cin.peek() == 'i' ) { // case bi
87 cin >> temp;
88
89 if ( cin.peek() == '\n' ) {
90 c.real = 0;
91 c.imaginary = number;
92 }
93 else
94 cin.clear( ios::failbit ); // set bad bit
95 }
96
97 else if ( cin.peek() == '\n' ) { // case a
98 c.real = number;
99 c.imaginary = 0;
100 }
101 else
102 cin.clear( ios::failbit ); // set bad bit
103
104 return input;
105 }
106 // driver for p11_16.cpp
107 #include "p11_16.h"
Chapter 11 C++ Stream Input/Output Solutions 345
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
11.17 Write a program that uses a for structure to print a table of ASCII values for the characters in the ASCII character set from
33 to 126. The program should print the decimal value, octal value, hexadecimal value and character value for each character. Use
the stream manipulators dec, oct and hex to print the integer values.
108
109 int main()
110 {
111 Complex complex;
112
113 cout << "Input a complex number in the form A + Bi:\n";
114 cin >> complex;
115
116 cout << "Complex number entered was:\n" << complex << endl;
117 return 0;
118 }
Input a complex number in the form A + Bi:
7 - 7777i
Complex number entered was:
7-7777i
1// Exercise 11.17 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::ios;
7
8#include <iomanip>
9
10 using std::setw;
11 using std::setiosflags;
12 using std::dec;
13 using std::oct;
14 using std::hex;
15
16 int main()
17 {
18 cout << setw( 7 ) << "Decimal" << setw( 9 ) << "Octal " << setw( 15 )
19 << "Hexadecimal " << setw( 13 ) << "Character"
20 << setiosflags( ios::showbase ) << '\n';
21
22 for ( int loop = 33; loop <= 126; ++loop )
23 cout << setw( 7 ) << dec << loop << setw( 9 ) << oct << loop
24 << setw( 15 ) << hex << loop << setw(13)
25 << static_cast<char>( loop ) << endl;
26
27 return 0;
28 }
346 C++ Stream Input/Output Solutions Chapter 11
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
11.18 Write a program to show that the getline and three-argument get istream member functions each end the input string
with a string-terminating null character. Also, show that get leaves the delimiter character on the input stream while getline
extracts the delimiter character and discards it. What happens to the unread characters in the stream?
Decimal Octal Hexadecimal Character
33 041 0x21 !
34 042 0x22 "
35 043 0x23 #
36 044 0x24 $
37 045 0x25 %
38 046 0x26 &
39 047 0x27 '
...
120 0170 0x78 x
121 0171 0x79 y
122 0172 0x7a z
123 0173 0x7b {
124 0174 0x7c |
125 0175 0x7d }
126 0176 0x7e ~
1// Exercise 11.18 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <cctype>
10
11 const int SIZE = 80;
12
13 int main()
14 {
15 char array[ SIZE ], array2[ SIZE ], c;
16
17 cout << "Enter a sentence to test getline() and get():\n";
18 cin.getline( array, SIZE, '*' );
19 cout << array << '\n';
20
21 cin >> c; // read next character in input
22 cout << "The next character in the input is: " << c << '\n';
23
24 cin.get( array2, SIZE, '*' );
25 cout << array2 << '\n';
26
27 cin >> c; // read next character in input
28 cout << "The next character in the input is: " << c << '\n';
29
30 return 0;
31 }
Chapter 11 C++ Stream Input/Output Solutions 347
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
11.19 Write a program that creates the user-defined manipulator skipwhite to skip leading whitespace characters in the input
stream. The manipulator should use the isspace function from the <cctype> library to test if the character is a whitespace char-
acter. Each character should be input using the istream member function get. When a nonwhitespace character is encountered,
the skipwhite manipulator finishes its job by placing the character back on the input stream and returning an istream refer-
ence.
Test the manipulator by creating a main function in which the ios::skipws flag is unset so that the stream-extraction
operator does not automatically skip whitespace. Then test the manipulator on the input stream by entering a character preceded by
whitespace as input. Print the character that was input to confirm that a whitespace character was not input.
Enter a sentence to test getline() and get():
wishing*on*a*star
wishing
The next character in the input is: o
n
The next character in the input is: *
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
12
Templates
Solutions
Solutions
12.3 Write a function template bubbleSort based on the sort program of Fig. 5.15. Write a driver program that inputs, sorts
and outputs an int array and a float array.
1// Exercise 12.3 solution
2// This program puts values into an array, sorts the values into
3// ascending order, and prints the resulting array.
4#include <iostream>
5
6using std::cout;
7using std::endl;
8
9#include <iomanip>
10
11 using std::setw;
12
13 template < class T >
14 void swap( T * const, T * const);
15
16 // Function template for bubbleSort
17 template < class T >
18 void bubbleSort( T * const array, int size )
19 {
20
21 for ( int pass = 1; pass < size; ++pass )
22 for ( int j = 0; j < size - pass; ++j )
23 if ( array[ j ] > array[ j + 1 ] )
24 swap( array + j, array + j + 1 );
25
26 }
27
28 template < class T >
29 void swap( T * const element1Ptr, T * const element2Ptr )
30 {
31 T temp = *element1Ptr;
Chapter 12 Templates Solutions 349
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
12.4 Overload function template printArray of Fig.12.2 so that it takes two additional integer arguments, namely int
lowSubscript and int highSubscript. A call to this function will print only the designated portion of the array. Validate
lowSubscript and highSubscript; if either is out-of-range or if highSubscript is less than or equal to low-
32 *element1Ptr = *element2Ptr;
33 *element2Ptr = temp;
34 }
35
36 int main()
37 {
38 const int arraySize = 10;
39 int a[ arraySize ] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }, i;
40
41 // Process an array of integers
42 cout << "Integer data items in original order\n";
43
44 for ( i = 0; i < arraySize; ++i )
45 cout << setw( 6 ) << a[ i ];
46
47 bubbleSort( a, arraySize ); // sort the array
48 cout << "\nInteger data items in ascending order\n";
49
50 for ( i = 0; i < arraySize; ++i )
51 cout << setw( 6 ) << a[ i ];
52
53 cout << "\n\n";
54
55 // Process an array of doubleing point values
56 double b[ arraySize ] = { 10.1, 9.9, 8.8, 7.7, 6.6, 5.5,
57 4.4, 3.3, 2.2, 1.1 };
58
59 cout << "doubleing point data items in original order\n";
60
61 for ( i = 0; i < arraySize; ++i )
62 cout << setw( 6 ) << b[ i ];
63
64 bubbleSort( b, arraySize ); // sort the array
65 cout << "\ndoubleing point data items in ascending order\n";
66
67 for ( i = 0; i < arraySize; ++i )
68 cout << setw( 6 ) << b[ i ];
69
70 cout << endl;
71
72 return 0;
73 }
Integer data items in original order
10 9 8 7 6 5 4 3 2 1
Integer data items in ascending order
1 2 3 4 5 6 7 8 9 10
doubleing point data items in original order
10.1 9.9 8.8 7.7 6.6 5.5 4.4 3.3 2.2 1.1
doubleing point data items in ascending order
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 10.1
350 Templates Solutions Chapter 12
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Subscript, the overloaded printArray function should return 0; otherwise, printArray should return the number of ele-
ments printed. Then modify main to exercise both versions of printArray on arrays a, b and c. Be sure to test all capabilities
of both versions of printArray.
1// Exercise 12.4 solution
2// Using template functions
3#include <iostream>
4
5using std::cout;
6using std::endl;
7
8
9template< class T >
10 int printArray( T const * const array, int size, int lowSubscript,
11 int highSubscript )
12 {
13 if ( size < 0 || lowSubscript < 0 || highSubscript >= size )
14 return 0; // negative size or subscript out of range
15
16 for ( int i = lowSubscript, count = 0; i <= highSubscript; ++i ) {
17 ++count;
18 cout << array[ i ] << ' ';
19 }
20
21 cout << '\n';
22
23 return count; // number or elements output
24 }
25
26 int main()
27 {
28 const int aCount = 5, bCount = 7, cCount = 6;
29 int a[ aCount ] = { 1, 2, 3, 4, 5 };
30 double b[ bCount ] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7 };
31 char c[ cCount ] = "HELLO"; // 6th position for null
32 int elements;
33
34 cout << "\nArray a contains:\n";
35 elements = printArray( a, aCount, 0, aCount - 1 );
36 cout << elements << " elements were output\n";
37
38 cout << "Array a from 1 to 3 is:\n";
39 elements = printArray( a, aCount, 1, 3 );
40 cout << elements << " elements were output\n";
41
42 cout << "Array a output with invalid subscripts:\n";
43 elements = printArray( a, aCount, -1, 10 );
44 cout << elements << " elements were output\n\n";
45
46 cout << "Array b contains:\n";
47 elements = printArray( b, bCount, 0, bCount - 1 );
48 cout << elements << " elements were output\n";
49
50 cout << "Array b from 1 to 3 is:\n";
51 elements = printArray( b, bCount, 1, 3 );
52 cout << elements << " elements were output\n";
53
54 cout << "Array b output with invalid subscripts:\n";
55 elements = printArray( b, bCount, -1, 10 );
56 cout << elements << " elements were output\n\n";
57
58 cout << "Array c contains:\n";
Chapter 12 Templates Solutions 351
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
12.5 Overload function template printArray of Fig.12.2 with a nontemplate version that specifically prints an array of char-
acter strings in neat, tabular, column format.
59 elements = printArray( c, cCount, 0, cCount - 1 );
60 cout << elements << " elements were output\n";
61
62 cout << "Array c from 1 to 3 is:\n";
63 elements = printArray( c, cCount, 1, 3 );
64 cout << elements << " elements were output\n";
65
66 cout << "Array c output with invalid subscripts:\n";
67 elements = printArray( c, cCount, -1, 10 );
68 cout << elements << " elements were output" << endl;
69
70 return 0;
71 }
Array a contains:
1 2 3 4 5
5 elements were output
Array a from 1 to 3 is:
2 3 4
3 elements were output
Array a output with invalid subscripts:
0 elements were output
Array b contains:
1.1 2.2 3.3 4.4 5.5 6.6 7.7
7 elements were output
Array b from 1 to 3 is:
2.2 3.3 4.4
3 elements were output
Array b output with invalid subscripts:
0 elements were output
Array c contains:
H E L L O
6 elements were output
Array c from 1 to 3 is:
E L L
3 elements were output
Array c output with invalid subscripts:
0 elements were output
1// Exercise 12.5 solution
2// Using template functions
3#include <iostream>
4
5using std::cout;
6
7#include <iomanip>
8
9using std::setw;
10
11 template< class T >
12 void printArray( T const * const array, int size )
13 {
14 for ( int i = 0; i < size; ++i )
15 cout << array[ i ] << ' ';
352 Templates Solutions Chapter 12
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
12.6 Write a simple function template for predicate function isEqualTo that compares its two arguments with the equality
operator (==) and returns true if they are equal and false if they are not equal. Use this function template in a program that calls
isEqualTo only with a variety of built-in types. Now write a separate version of the program that calls isEqualTo with a user-
16
17 cout << '\n';
18 }
19
20 void printArray( char const * const stringArray[], int size )
21 {
22 for ( int i = 0; i < size; ++i ) {
23 cout << setw( 10 ) << stringArray[ i ];
24
25 if ( ( i + 1 ) % 4 == 0 )
26 cout << '\n';
27 }
28
29 cout << '\n';
30 }
31
32 int main()
33 {
34 const int aCount = 5, bCount = 7, cCount = 6, sCount = 8;
35 int a[ aCount ] = { 1, 2, 3, 4, 5 };
36 double b[ bCount ] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7 };
37 char c[ cCount ] = "HELLO"; // 6th position for null
38 const char *strings[ sCount ] = { "one", "two", "three", "four",
39 "five", "six", "seven", "eight" };
40
41 cout << "Array a contains:\n";
42 printArray( a, aCount ); // integer template function
43
44 cout << "\nArray b contains:\n";
45 printArray( b, bCount ); // float template function
46
47 cout << "\nArray c contains:\n";
48 printArray( c, cCount ); // character template function
49
50 cout << "\nArray strings contains:\n";
51 printArray( strings, sCount ); // function specific to string arrays
52
53 return 0;
54 }
Array a contains:
1 2 3 4 5
Array b contains:
1.1 2.2 3.3 4.4 5.5 6.6 7.7
Array c contains:
H E L L O
Array strings contains:
one two three four
five six seven eight
Chapter 12 Templates Solutions 353
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
defined class type, but does not overload the equality operator. What happens when you attempt to run this program? Now overload
the equality operator (with operator function operator==). Now what happens when you attempt to run this program?
1// Exercise 12.6 solution
2// Combined solution to entire problem
3#include <iostream>
4
5using std::cout;
6using std::cin;
7using std::ostream;
8
9template < class T >
10 bool isEqualTo( const T &arg1, const T &arg2 ) { return arg1 == arg2; }
11
12 class SomeClass {
13 friend ostream &operator<<(ostream &, SomeClass &);
14 public:
15 SomeClass( int s, double t )
16 {
17 x = s;
18 y = t;
19 }
20
21 // Overloaded equality operator. If this is not provided, the
22 // program will not compile.
23 bool operator==( const SomeClass &right ) const
24 { return x == right.x && y == right.y; }
25 private:
26 int x;
27 double y;
28 };
29
30 ostream &operator<<( ostream &out, SomeClass &obj )
31 {
32 out << '(' << obj.x << ", " << obj.y << ')';
33 return out;
34 }
35
36 int main()
37 {
38 int a, b;
39
40 cout << "Enter two integer values: ";
41 cin >> a >> b;
42 cout << a << " and " << b << " are "
43 << ( isEqualTo( a, b ) ? "equal" : "not equal" ) << '\n';
44
45 char c, d;
46
47 cout << "\nEnter two character values: ";
48 cin >> c >> d;
49 cout << c << " and " << d << " are "
50 << ( isEqualTo( c, d ) ? "equal" : "not equal" ) << '\n';
51
52 double e, f;
53
54 cout << "\nEnter two double values: ";
55 cin >> e >> f;
56 cout << e << " and " << f << " are "
57 << ( isEqualTo( e, f ) ? "equal" : "not equal") << '\n';
58
354 Templates Solutions Chapter 12
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
12.7 Use a nontype parameter numberOfElements and a type parameter elementType to help create a template for the
Array class we developed in Chapter 8, “Operator Overloading.” This template will enable Array objects to be instantiated with
a specified number of elements of a specified element type at compile time.
59 SomeClass g( 1, 1.1 ), h( 1, 1.1 );
60
61 cout << "\nThe class objects " << g << " and " << h << " are "
62 << ( isEqualTo( g, h ) ? "equal" : "not equal" ) << '\n';
63 return 0;
64 }
Enter two integer values: 8 22
8 and 22 are not equal
Enter two character values: Y Y
Y and Y are equal
Enter two double values: 3.3 8.7
3.3 and 8.7 are not equal
The class objects (1, 1.1) and (1, 1.1) are equal
1#ifndef ARRAY1_H
2#define ARRAY1_H
3
4#include <iostream>
5
6using std::cout;
7using std::endl;
8using std::cin;
9
10 #include <cstdlib>
11 #include <cassert>
12
13 template < class elementType, int numberOfElements >
14 class Array {
15 public:
16 Array(); // default constructor
17 ~Array(); // destructor
18 int getSize() const; // return size
19 bool operator==( const Array & ) const; // compare equal
20 bool operator!=( const Array & ) const; // compare !equal
21 elementType &operator[]( int ); // subscript operator
22 static int getArrayCount(); // Return count of
23 // arrays instantiated.
24 void inputArray(); // input the array elements
25 void outputArray() const; // output the array elements
26 private:
27 elementType ptr[ numberOfElements ]; // pointer to first element of array
28 int size; // size of the array
29 static int arrayCount; // # of Arrays instantiated
30 };
31
32 // Initialize static data member at file scope
33 template < class elementType, int numberOfElements >
34 int Array< elementType, numberOfElements >::arrayCount = 0; // no objects yet
35
36 // Default constructor for class Array
37 template < class elementType, int numberOfElements >
Chapter 12 Templates Solutions 355
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
38 Array< elementType, numberOfElements >::Array()
39 {
40 ++arrayCount; // count one more object
41 size = numberOfElements;
42
43 for ( int i = 0; i < size; ++i )
44 ptr[ i ] = 0; // initialize array
45 }
46
47 // Destructor for class Array
48 template < class elementType, int numberOfElements >
49 Array< elementType, numberOfElements >::~Array() { --arrayCount; }
50
51 // Get the size of the array
52 template < class elementType, int numberOfElements >
53 int Array< elementType, numberOfElements >::getSize() const { return size; }
54
55 // Determine if two arrays are equal and
56 // return true or false.
57 template < class elementType, int numberOfElements >
58 bool Array< elementType, numberOfElements >::
59 operator==( const Array &right ) const
60 {
61 if ( size != right.size )
62 return false; // arrays of different sizes
63
64 for ( int i = 0; i < size; ++i )
65 if ( ptr[ i ] != right.ptr[ i ] )
66 return false; // arrays are not equal
67
68 return true; // arrays are equal
69 }
70
71 // Determine if two arrays are not equal and
72 // return true or false.
73 template < class elementType, int numberOfElements >
74 bool Array< elementType, numberOfElements >::
75 operator!=( const Array &right ) const
76 {
77 if ( size != right.size )
78 return true; // arrays of different sizes
79
80 for ( int i = 0; i < size; ++i )
81 if ( ptr[ i ] != right.ptr[ i ] )
82 return true; // arrays are not equal
83
84 return false; // arrays are equal
85 }
86
87 // Overloaded subscript operator
88 template < class elementType, int numberOfElements >
89 elementType &Array< elementType, numberOfElements >::
90 operator[]( int subscript )
91 {
92 // check for subscript out of range error
93 assert( 0 <= subscript && subscript < size );
94
95 return ptr[ subscript ]; // reference return creates lvalue
96 }
97
98 // Return the number of Array objects instantiated
99 template < class elementType, int numberOfElements >
356 Templates Solutions Chapter 12
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
100 int Array< elementType, numberOfElements >::getArrayCount()
101 { return arrayCount; }
102
103 // Input values for entire array.
104 template < class elementType, int numberOfElements >
105 void Array< elementType, numberOfElements >::inputArray()
106 {
107 for ( int i = 0; i < size; ++i )
108 cin >> ptr[ i ];
109 }
110
111 // Output the array values
112 template < class elementType, int numberOfElements >
113 void Array< elementType, numberOfElements >::outputArray() const
114 {
115 for ( int i = 0; i < size; ++i ) {
116 cout << ptr[ i ] << ' ';
117
118 if ( ( i + 1 ) % 10 == 0 )
119 cout << '\n';
120 }
121
122 if ( i % 10 != 0 )
123 cout << '\n';
124 }
125
126 #endif
127 // Exercise 12.7 solution
128 #include <iostream>
129
130 using std::cout;
131
132 #include "arraytmp.h"
133
134 int main()
135 {
136 Array< int, 5 > intArray;
137
138 cout << "Enter " << intArray.getSize() << " integer values:\n";
139 intArray.inputArray();
140
141 cout << "\nThe values in intArray are:\n";
142 intArray.outputArray();
143
144 Array< float, 5 > floatArray;
145
146 cout << "\nEnter " << floatArray.getSize()
147 << " floating point values:\n";
148 floatArray.inputArray();
149
150 cout << "\nThe values in the double array are:\n";
151 floatArray.outputArray();
152
153 return 0;
154 }
Chapter 12 Templates Solutions 357
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
12.8 Write a program with class template Array. The template can instantiate an Array of any element type. Override the
template with a specific definition for an Array of float elements (class Array< float >). The driver should demonstrate
the instantiation of an Array of int through the template and should show that an attempt to instantiate an Array of float uses
the definition provided in class Array< float >.
12.9 Distinguish between the terms "function template" and "template function."
ANS: A function template is used to instantiate template functions.
12.10 Which is more like a stencil—a class template or a template class? Explain your answer.
ANS: A class template can be viewed as a stencil from which a template class can be created. A template class can be
viewed as a stencil from which objects of that class can be created. So, in a way, both can be viewed as stencils.
12.11 What is the relationship between function templates and overloading?
ANS: Function templates create overloaded versions of a function. The main difference is at compile time, where the com-
piler automatically creates the code for the template functions from the function template rather than the programmer cre-
ating the code.
12.12 Why might you choose to use a function template instead of a macro?
ANS: A macro is a text substitution done by the preprocessor. A function template provides real function definitions with
all the type checking to ensure proper function calls.
12.13 What performance problem can result from using function templates and class templates?
ANS: There can be a tremendous proliferation of code in the program due to many copies of code generated by the com-
piler.
12.14 The compiler performs a matching process to determine which template function to call when a function is invoked. Under
what circumstances does an attempt to make a match result in a compile error?
ANS: If the compiler cannot match the function call made to a template or if the matching process results in multiple
matches at compile time, the compiler generates an error.
12.15 Why is it appropriate to call a class template a parameterized type?
ANS: When creating template classes from a class template, it is necessary to provide a type (or possibly several types) to
complete the definition of the new type being declared. For example, when creating an "array of integers" from an Array
class template, the type int is provided to the class template to complete the definition of an array of integers.
12.16 Explain why you might use the statement
Array< Employee > workerList( 100 );
in a C++ program.
ANS: When creating template classes from a class template, it is necessary to provide a type (or possibly several types) to
complete the definition of the new type being declared. For example, when creating an "array of integers" from an Array
class template, the type int is provided to the class template to complete the definition of an array of integers.
12.17 Review your answer to Exercise 12.16. Now, why might you use the statement
Array< Employee > workerList;
in a C++ program?
ANS: Declares an Array object to store an Employee. The default constructor is used.
Enter 5 integer values:
99 98 97 96 95
The values in intArray are:
99 98 97 96 95
Enter 5 floating point values:
1.12 1.13 1.45 1.22 9.11
The values in the doubleArray are:
1.12 1.13 1.45 1.22 9.11
358 Templates Solutions Chapter 12
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
12.18 Explain the use of the following notation in a C++ program:
template< class T > Array< T >::Array( int s )
ANS: This notation is used to begin the definition of the Array( int ) constructor for the class template Array.
12.19 Why might you typically use a nontype parameter with a class template for a container such as an array or stack?
ANS: To specify at compile time the size of the container class object being declared.
12.20 Describe how to provide a class for a specific type to override the class template for that type.
12.21 Describe the relationship between class templates and inheritance.
12.22 Suppose a class template has the header
template< class T1 > class C1
Describe the friendship relationships established by placing each of the following friendship declarations inside this class template
header. Identifiers beginning with “f” are functions, identifiers beginning with “C” are classes and identifiers beginning with “T
can represent any type (i.e., built-in types or class types).
a) friend void f1();
ANS: To specify at compile time the size of the container class object being declared.
b) friend void f2( C1< T1 > &);
ANS: Function f2 for a specific type of T1 is a friend of the template class of type T1. For example, if T1 is of type
int, the function with the prototype
void f2( C1< int > & );
is a friend of the class C1< int >.
c) friend void C2::f4();
ANS: Function f4 of class C2 is a friend of all template classes instantiated from class template C1.
d) friend void C3< T1 >::f5( C1< T1 > & );
ANS: Function f5 of class C3 for a specific type of T1 is a friend of the template class of type T1. For example, if T1
is int, the function with the prototype
void c3< int >::f5( C1< int > & );
e) friend class C5;
ANS: Makes every member function of class C5 a friend of all template classes instantiated from the class template C1.
f) friend class C6< T1 >;
ANS: For a specific type T1, makes every member function of C6< T1 > a friend of class C1< T1 >. For example,
if T1 is int, every member function of class C6< int > is a friend of C1< int >.
12.23 Suppose class template Employee has a static data member count. Suppose three template classes are instantiated
from the class template. How many copies of the static data member will exist? How will the use of each be constrained (if at
all)?
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
13
Exception
Handling
Solutions
Solutions
13.20 List the various exceptional conditions that have occurred in programs throughout this text. List as many additional excep-
tional conditions as you can. For each of these, describe briefly how a program would typically handle the exception using the ex-
ception-handling techniques discussed in this chapter. Some typical exceptions are division by zero, arithmetic overflow, array
subscript out of bounds, exhaustion of the free store, etc.
13.21 Under what circumstances would the programmer not provide a parameter name when defining the type of the object that
will be caught by a handler?
ANS: If there is no information in the object that is required in the handler, a parameter name is not required in the handler.
13.22 A program contains the statement
throw;
Where would you normally expect to find such a statement? What if that statement appeared in a different part of the program?
ANS: The statement would be found in an exception handler to rethrow an exception. If any throw expression occurs
outside a try block, the function unexpected is called.
13.23 Under what circumstances would you use the following statement?
catch(...) { throw; }
ANS: The preceding statement is used to catch any exception and rethrow it for handling by an exception handler in a
function within the call stack.
13.24 Compare and contrast exception handling with the various other error-processing schemes discussed in the text.
ANS: Exception handling enables the programmer to build more robust classes with built-in error processing capabilities.
Once created, such classes allow clients of classes to concentrate on using the classes rather than defining what should
happen if an error occurs while using the class. Exception handling offers the possibility that an error can be processed and
that the program can continue execution. Other forms of error checking such as assert exit the program immediately
without any further processing.
13.25 List the advantages of exception handling over conventional means of error processing.
13.26 Provide reasons why exceptions should not be used as an alternate form of program control.
ANS: Exceptions were designed for "exceptional cases." Exceptions do not follow conventional forms of program control.
Therefore, using exceptions for anything other than error processing will not be easily recognized by others reading the
code. This may make the program more difficult to modify and maintain.
360 Exception Handling Solutions Chapter 13
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
13.27 Describe a technique for handling related exceptions.
ANS: Create a base class for all related exceptions. In the base class, derive all the related exception classes. Once the
exception class hierarchy is created, exceptions from the hierarchy can be caught as the base class exception type or as one
of the derived class exception types.
13.28 Until this chapter, we have found that dealing with errors detected by constructors is a bit awkward. Exception handling
gives us a much better means of dealing with such errors. Consider a constructor for a String class. The constructor uses new to
obtain space from the free store. Suppose new fails. Show how you would deal with this without exception handling. Discuss the
key issues. Show how you would deal with such memory exhaustion with exception handling. Explain why the exception handling
method is superior.
13.29 Suppose a program throws an exception and the appropriate exception handler begins executing. Now suppose that the
exception handler itself throws the same exception. Does this create an infinite recursion? Write a program to check your obser-
vation.
1// Exercise 13.28 Solution
2#include <iostream>
3
4using std::cout;
5using std::cerr;
6
7#include <new>
8#include <cstdlib>
9
10 void message( void );
11
12 int main()
13 {
14 long double *d[ 50 ];
15 set_new_handler( message );
16
17 for ( int q = 0; q < 50; ++q ){
18 d[ q ] = new long double[ 10000000 ];
19 cout << "allocated 10000000 long doubles to d[" << q << "]\n";
20 }
21
22 cout << "Memory Allocated\n";
23
24 return 0;
25 }
26
27 void message( void )
28 {
29 cerr << "Memory Allocation Failed\n";
30 exit( EXIT_FAILURE );
31 }
Assertion failed: new_p == 0, file setnewh.cpp, line 52
abnormal program termination
1// Exercise 13.29 solution
2#include <iostream>
3
4using std::cout;
5
6class TestException {
7public:
8 TestException( char *mPtr ) : message( mPtr ) {}
Chapter 13 Exception Handling Solutions 361
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
13.30 Use inheritance to create a base exception class and various derived exception classes. Then show that a catch handler
specifying the base class can catch derived-class exceptions.
9 void print() const { cout << message << '\n'; }
10 private:
11 char *message;
12 };
13
14 int main()
15 {
16 try {
17 throw TestException( "This is a test" );
18 }
19 catch ( TestException &t ) {
20 t.print();
21 throw TestException( "This is another test" );
22 }
23
24 return 0;
25 }
This is a test
abnormal program termination
1// Exercise 13.30 Solution
2#include <iostream>
3
4using std::cout;
5
6#include <cstdlib>
7#include <ctime>
8
9class BaseException {
10 public:
11 BaseException( char *mPtr ) : message( mPtr ) {}
12 void print() const { cout << message << '\n'; }
13 private:
14 char *message;
15 };
16
17 class DerivedException : public BaseException {
18 public:
19 DerivedException( char *mPtr ) : BaseException( mPtr ) {}
20 };
21
22 class DerivedException2 : public DerivedException {
23 public:
24 DerivedException2( char *mPtr ) : DerivedException( mPtr ) {}
25 };
26
27 int main()
28 {
29 srand( time( 0 ) );
30
31 try {
32 throw ( rand() % 2 ? DerivedException( "DerivedException" ) :
33 DerivedException2( "DerivedException2" ) );
34 }
362 Exception Handling Solutions Chapter 13
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
13.31 Show a conditional expression that returns either a double or an int. Provide an int catch handler and a double
catch handler. Show that only the double catch handler executes regardless of whether the int or the double is returned.
13.32 Write a program designed to generate and handle a memory exhaustion error. Your program should loop on a request to
create dynamic storage through operator new.
35 catch ( BaseException &b ) {
36 b.print();
37 }
38
39 return 0;
40 }
DerivedException2
1// Exercise 13.31 Solution
2#include <iostream>
3using std::cerr;
4
5int main()
6{
7 try {
8 int a = 7;
9 double b = 9.9;
10
11 throw a < b ? a : b;
12 }
13 catch ( int x ) {
14 cerr << "The int value " << x << " was thrown\n";
15 }
16 catch ( double y ) {
17 cerr << "The double value " << y << " was thrown\n";
18 }
19
20 return 0;
21 }
The double value 7 was thrown
1// Exercise 13.32 solution
2#include <iostream>
3
4using std::cout;
5using std::cerr;
6
7#include <new>
8using std::bad_alloc;
9
10 #include <cstdlib>
11
12 int main()
13 {
14 long double *ptr[ 10 ];
15
16 try {
Chapter 13 Exception Handling Solutions 363
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
13.33 Write a program which shows that all destructors for objects constructed in a block are called before an exception is thrown
from that block.
17 for ( int i = 0; i < 10; ++i ) {
18 ptr[ i ] = new long double[ 50000000 ];
19 cout << "Allocated 50000000 long doubles in ptr[ "
20 << i << " ]\n";
21 }
22 }
23 catch ( bad_alloc ex ) {
24 cerr << "Memory Allocation Failed.\n";
25 exit( EXIT_FAILURE );
26 }
27
28 return 0;
29 }
Allocated 5000000 long doubles in ptr[ 0 ]
Allocated 5000000 long doubles in ptr[ 1 ]
Allocated 5000000 long doubles in ptr[ 2 ]
Allocated 5000000 long doubles in ptr[ 3 ]
Allocated 5000000 long doubles in ptr[ 4 ]
Allocated 5000000 long doubles in ptr[ 5 ]
Allocated 5000000 long doubles in ptr[ 6 ]
Allocated 5000000 long doubles in ptr[ 7 ]
Allocated 5000000 long doubles in ptr[ 8 ]
Allocated 5000000 long doubles in ptr[ 9 ]
1// Exercise 13.33 Solution
2#include <iostream>
3
4using std::cout;
5using std::cerr;
6
7
8class Object {
9public:
10 Object( int val ) : value( val )
11 { cout << "Object " << value << " constructor\n"; }
12 ~Object()
13 { cout << "Object " << value << " destructor\n"; }
14 private:
15 int value;
16 };
17
18 class Error {
19 public:
20 Error( char *s ) : string( s ) {}
21 void print() const { cerr << '\n' << string << '\n'; }
22 private:
23 char *string;
24 };
25
26 int main()
27 {
28 try {
29 Object a( 1 ), b( 2 ), c( 3 );
30 cout << '\n';
31 throw Error( "This is a test exception" );
364 Exception Handling Solutions Chapter 13
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
13.34 Write a program which shows that member object destructors are called for only those member objects that were construct-
ed before an exception occurred.
32 }
33 catch ( Error &e ) {
34 e.print();
35 }
36
37 return 0;
38 }
Object 1 constructor
Object 2 constructor
Object 3 constructor
Object 3 destructor
Object 2 destructor
Object 1 destructor
This is a test exception
1// Exercise 13_34 Solution
2#include <iostream>
3
4using std::cout;
5using std::cerr;
6
7// A sample exception class
8class ExceptionClass {
9public:
10 ExceptionClass() : message( "An exception was thrown" ) {}
11 void print() const { cerr << '\n' << message << '\n'; }
12 private:
13 char *message;
14 };
15
16 // A class from which to build member objects
17 class Member {
18 public:
19 Member( int val ) : value( val )
20 {
21 cout << "Member object " << value << " constructor called\n";
22
23 // If value is 3, throw an exception for demonstration purposes.
24 if ( value == 3 )
25 throw ExceptionClass();
26 }
27
28 ~Member()
29 { cout << "Member object " << value << " destructor called\n"; }
30 private:
31 int value;
32 };
33
34 // A class to encapsulate objects of class Member
35 class Encapsulate {
36 public:
37 Encapsulate() : m1( 1 ), m2( 2 ), m3( 3 ), m4( 4 ), m5( 5 ) {}
38 private:
Chapter 13 Exception Handling Solutions 365
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
13.35 Write a program that demonstrates how any exception is caught with catch(...).
39 Member m1, m2, m3, m4, m5;
40 };
41
42 int main()
43 {
44 cout << "Constructing an object of class Encapsulate\n";
45
46 try {
47 Encapsulate e;
48 }
49 catch( ExceptionClass &except ) {
50 except.print();
51 }
52
53 return 0;
54 }
Constructing an object of class Encapsulate
Member object 1 constructor called
Member object 2 constructor called
Member object 3 constructor called
Member object 2 destructor called
Member object 1 destructor called
An exception was thrown
1// Exercise 13.35 Solution
2#include <iostream>
3
4using std::cout;
5using std::cerr;
6
7
8// A sample exception class
9class ExceptionClass {
10 public:
11 ExceptionClass() : message( "An exception was thrown" ) {}
12 void print() const { cerr << '\n' << message << '\n'; }
13 private:
14 char *message;
15 };
16
17 void generateException();
18
19 int main()
20 {
21 try {
22 generateException();
23 }
24 catch( ... ) {
25 cerr << "The \"catch all\" exception handler was invoked\n";
26 }
27
28 return 0;
29 }
30
31 void generateException()
366 Exception Handling Solutions Chapter 13
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
13.36 Write a program which shows that the order of exception handlers is important. The first matching handler is the one that
executes. Compile and run your program two different ways to show that two different handlers execute with two different effects.
13.37 Write a program that shows a constructor passing information about constructor failure to an exception handler after a try
block.
13.38 Write a program that uses a multiple inheritance hierarchy of exception classes to create a situation in which the order of
exception handlers matters.
32 {
33 throw ExceptionClass();
34 }
The "catch all" exception handler was invoked
1// Exercise 13.37 Solution
2#include <iostream>
3
4using std::cout;
5using std::cerr;
6
7class InvalidIDNumberError {
8public:
9 InvalidIDNumberError( char *s ) : errorMessage( s ) {}
10 void print() const { cerr << errorMessage; }
11 private:
12 char *errorMessage;
13 };
14
15 class TestInvalidIDNumberError {
16 public:
17 TestInvalidIDNumberError( int id ) : idNumber( id )
18 {
19 cout << "Constructor for object " << idNumber << '\n';
20
21 if ( idNumber < 0 )
22 throw InvalidIDNumberError( "ERROR: Negative ID number" );
23 }
24 private:
25 int idNumber;
26 };
27
28 int main()
29 {
30 try {
31 TestInvalidIDNumberError valid( 10 ), invalid( -1 );
32 }
33 catch ( InvalidIDNumberError &error ) {
34 error.print();
35 cerr << '\n';
36 }
37
38 return 0;
39 }
Constructor for object 10
Constructor for object -1
ERROR: Negative ID number
Chapter 13 Exception Handling Solutions 367
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
13.39 Using setjmp/longjmp, a program can transfer control immediately to an error routine from a deeply nested function
invocation. Unfortunately, as the stack is unwound, destructors are not called for the automatic objects that were created during the
sequence of nested function calls. Write a program which demonstrates that these destructors are, in fact, not called.
13.40 Write a program that illustrates rethrowing an exception.
13.41 Write a program that uses set_unexpected to set a user-defined function for unexpected, uses set_unexpected
again, and then resets unexpected back to its previous function. Write a similar program to test set_terminate and ter-
minate.
13.42 Write a program which shows that a function with its own try block does not have to catch every possible error generated
within the try. Some exceptions can slip through to, and be handled in, outer scopes.
1// Exercise 13.40 Solution
2#include <iostream>
3
4using std::cout;
5using std::cerr;
6
7class TestException {
8public:
9 TestException( char *m ) : message( m ) {}
10 void print() const { cout << message << '\n'; }
11 private:
12 char *message;
13 };
14
15 void f() { throw TestException( "Test exception thrown" ); }
16
17 void g()
18 {
19 try {
20 f();
21 }
22 catch ( ... ) {
23 cerr << "Exception caught in function g(). Rethrowing...\n";
24 throw;
25 }
26 }
27
28 int main()
29 {
30 try {
31 g(); // start function call chain
32 }
33 catch ( ... ) {
34 cerr << "Exception caught in function main()\n";
35 }
36
37 return 0;
38 }
Exception caught in function g(). Rethrowing...
Exception caught in function main()
1// Exercise 13.42 Solution
2#include <iostream>
368 Exception Handling Solutions Chapter 13
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
13.43 Write a program that throws an error from a deeply nested function call and still has the catch handler following the
try block enclosing the call chain catch the exception.
3
4using std::cout;
5using std::cerr;
6
7class TestException1 {
8public:
9 TestException1( char *m ) : message( m ) {}
10 void print() const { cerr << message << '\n'; }
11 private:
12 char *message;
13 };
14
15 class TestException2 {
16 public:
17 TestException2( char *m ) : message( m ) {}
18 void print() const { cout << message << '\n'; }
19 private:
20 char *message;
21 };
22
23 void f()
24 {
25 throw TestException1( "TestException1" );
26 }
27
28 void g()
29 {
30 try {
31 f();
32 }
33 catch ( TestException2 &t2 ) {
34 cerr << "In g: Caught ";
35 t2.print();
36 }
37 }
38
39 int main()
40 {
41 try {
42 g();
43 }
44 catch ( TestException1 &t1 ) {
45 cerr << "In main: Caught ";
46 t1.print();
47 }
48
49 return 0;
50 }
In main: Caught TestException1
1// Exercise 13.43 Solution
2#include <iostream>
3
4using std::cout;
5using std::cerr;
6
Chapter 13 Exception Handling Solutions 369
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
7class TestException {
8public:
9 TestException( char *m ) : message( m ) {}
10 void print() const { cout << message << '\n'; }
11 private:
12 char *message;
13 };
14
15 void f() { throw TestException( "TestException" ); }
16
17 void g() { f(); }
18
19 void h() { g(); }
20
21 int main()
22 {
23 try {
24 h();
25 }
26 catch ( TestException &t ) {
27 cerr << "In main: Caught ";
28 t.print();
29 }
30
31 return 0;
32 }
In main: Caught TestException
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
14
File Processing
Solutions
Solutions
14.5 Fill in the blanks in each of the following:
a) Computers store large amounts of data on secondary storage devices as .
ANS: files.
b) A is composed of several fields.
ANS: record.
c) A field that may contain only digits, letters and blanks is called an field.
ANS: alphanumeric.
d) To facilitate the retrieval of specific records from a file, one field in each record is chosen as a .
ANS: key.
e) The vast majority of information stored in computer systems is stored in files.
ANS: sequential.
f) A group of related characters that conveys meaning is called a .
ANS: field.
g) The standard stream objects declared by header file <iostream> are , , and
.
ANS: cin, cout, cerr, clog.
h) ostream member function outputs a character to the specified stream.
ANS: put.
i) ostream member function is generally used to write data to a randomly accessed file.
ANS: write.
j) istream member function repositions the file position pointer in a file.
ANS: seekg.
14.6 State which of the following are true and which are false. If false, explain why.
a) The impressive functions performed by computers essentially involve the manipulation of zeros and ones.
ANS: True.
b) People prefer to manipulate bits instead of characters and fields because bits are more compact.
ANS: False. People prefer to manipulate characters and fields because they are less cumbersome and
more understandable.
c) People specify programs and data items as characters; computers then manipulate and process these characters as
groups of zeros and ones.
ANS: True.
d) A person's 5-digit zip code is an example of a numeric field.
Chapter 14 File Processing Solutions 371
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
ANS: True.
e) A person's street address is generally considered to be an alphabetic field in computer applications.
ANS: False. A street address is generally considered to be alphanumeric.
f) Data items represented in computers form a data hierarchy in which data items become larger and more complex as we
progress from fields to characters to bits, etc.
ANS: False. Data items processed by a computer form a data hierarchy in which data items become larger and more com-
plex as we progress from bits to characters to fields, etc.
g) A record key identifies a record as belonging to a particular field.
ANS: False. A record key identifies a record as belonging to a particular person or entity.
h) Most organizations store all information in a single file to facilitate computer processing.
ANS: False. Most organizations have many files in which they store their information.
i) Each statement that processes a file in a C++ program explicitly refers to that file by name.
ANS: False. A pointer to each file is used to refer to the file.
j) When a program creates a file, the file is automatically retained by the computer for future reference.
ANS: True.
14.7 Exercise 14.3 asked the reader to write a series of single statements. Actually, these statements form the core of an important
type of file processing program, namely, a file-matching program. In commercial data processing, it is common to have several files
in each application system. In an accounts receivable system, for example, there is generally a master file containing detailed infor-
mation about each customer such as the customer's name, address, telephone number, outstanding balance, credit limit, discount
terms, contract arrangements, and possibly a condensed history of recent purchases and cash payments.
As transactions occur (e.g., sales are made and cash payments arrive), they are entered into a file. At the end of each business
period (a month for some companies, a week for others, and a day in some cases) the file of transactions (called "trans.dat" in
Exercise 14.3) is applied to the master file (called "oldmast.dat" in Exercise 14.3), thus updating each account's record of pur-
chases and payments. During an updating run, the master file is rewritten as a new file ("newmast.dat"), which is then used at the
end of the next business period to begin the updating process again.
File-matching programs must deal with certain problems that do not exist in single-file programs. For example, a match does
not always occur. A customer on the master file may not have made any purchases or cash payments in the current business period,
and therefore no record for this customer will appear on the transaction file. Similarly, a customer who did make some purchases or
cash payments may have just moved to this community, and the company may not have had a chance to create a master record for
this customer.
Use the statements from Exercise 14.3 as a basis for writing a complete file-matching accounts receivable program. Use the
account number on each file as the record key for matching purposes. Assume that each file is a sequential file with records stored
in increasing order by account number.
When a match occurs (i.e., records with the same account number appear on both the master and transaction files), add the
dollar amount on the transaction file to the current balance on the master file, and write the "newmast.dat" record. (Assume
purchases are indicated by positive amounts on the transaction file and payments are indicated by negative amounts.) When there is
a master record for a particular account but no corresponding transaction record, merely write the master record to "new-
mast.dat". When there is a transaction record but no corresponding master record, print the message "Unmatched trans-
action record for account number …" (fill in the account number from the transaction record).
1// Exercise 14.7 Solution
2#include <iostream>
3
4using std::cout;
5using std::ios;
6using std::cerr;
7
8
9#include <iomanip>
10
11 using std::setprecision;
12
13 #include <fstream>
14
15 using std::ofstream;
16 using std::ifstream;
17
18 #include <cstdlib>
372 File Processing Solutions Chapter 14
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
19
20 void printOutput( ofstream&, int, const char *, const char *, double );
21
22 int main()
23 {
24 int masterAccount, transactionAccount;
25 double masterBalance, transactionBalance;
26 char masterFirstName[ 20 ], masterLastName[ 20 ];
27
28 ifstream inOldMaster( "oldmast.dat" ),
29 inTransaction( "trans.dat" );
30 ofstream outNewMaster( "newmast.dat" );
31
32 if ( !inOldMaster ) {
33 cerr << "Unable to open oldmast.dat\n";
34 exit( EXIT_FAILURE );
35 }
36
37 if ( !inTransaction ) {
38 cerr << "Unable to open trans.dat\n";
39 exit( EXIT_FAILURE );
40 }
41
42 if ( !outNewMaster ) {
43 cerr << "Unable to open newmast.dat\n";
44 exit( EXIT_FAILURE );
45 }
46
47 cout << "Processing...\n";
48 inTransaction >> transactionAccount >> transactionBalance;
49
50 while ( !inTransaction.eof() ) {
51 inOldMaster >> masterAccount >> masterFirstName
52 >> masterLastName >> masterBalance;
53
54 while ( masterAccount < transactionAccount && !inOldMaster.eof() ) {
55 printOutput( outNewMaster, masterAccount, masterFirstName,
56 masterLastName, masterBalance );
57 inOldMaster >> masterAccount >> masterFirstName
58 >> masterLastName >> masterBalance;
59 }
60
61 if ( masterAccount > transactionAccount ) {
62 cout << "Unmatched transaction record for account "
63 << transactionAccount << '\n';
64
65 inTransaction >> transactionAccount >> transactionBalance;
66 }
67
68 if ( masterAccount == transactionAccount ) {
69 masterBalance += transactionBalance;
70 printOutput( outNewMaster, masterAccount, masterFirstName,
71 masterLastName, masterBalance );
72 }
73
74 inTransaction >> transactionAccount >> transactionBalance;
75 }
76
77 inTransaction.close();
78 outNewMaster.close();
79 inOldMaster.close();
80
Chapter 14 File Processing Solutions 373
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Contents of “oldmast.dat”
Contents of “trans.dat”
Contents of “newmast.dat”
81 return 0;
82 }
83
84 void printOutput( ofstream &oRef, int mAccount, const char *mfName,
85 const char *mlName, double mBalance )
86 {
87 cout.setf( ios::fixed | ios::showpoint );
88 oRef.setf( ios::fixed | ios::showpoint );
89
90 oRef << mAccount << ' ' << mfName << ' ' << mlName << ' '
91 << setprecision( 2 ) << mBalance << '\n';
92 cout << mAccount << ' ' << mfName << ' ' << mlName << ' '
93 << setprecision( 2 ) << mBalance << '\n';
94 }
Processing...
100 Ajax Guppie 678.06
300 Sue Pirhana 650.07
400 Clint Bass 994.22
Unmatched transaction record for account 445
500 Aias Shark 895.80
700 Tom Mahi-Mahi -23.57
900 Marisal Carp 200.55
100 Ajax Guppie 543.89
300 Sue Pirhana 22.88
400 Clint Bass -6.32
500 Aias Shark 888.71
700 Tom Mahi-Mahi 76.09
900 Marisal Carp 100.55
100 134.17
300 627.19
400 1000.54
445 55.55
500 7.09
700 -99.66
900 100.00
100 Ajax Guppie 678.06
300 Sue Pirhana 650.07
400 Clint Bass 994.22
500 Aias Shark 895.80
700 Tom Mahi-Mahi -23.57
900 Marisal Carp 200.55
374 File Processing Solutions Chapter 14
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
14.8 After writing the program of Exercise 14.7, write a simple program to create some test data for checking out the program.
Use the following sample account data:
Master file
Account number Name Balance
100 Alan Jones 348.17
300 Mary Smith 27.19
500 Sam Sharp 0.00
700 Suzy Green -14.22
Transaction file
Account number Transaction amount
100 27.14
300 62.11
400 100.56
900 82.17
1// Exercise 14.8 Solution
2#include <iostream>
3
4using std::cout;
5using std::ios;
6using std::cerr;
7
8#include <iomanip>
9
10 using std::setprecision;
11 using std::setiosflags;
12
13 #include <fstream>
14
15 using std::ofstream;
16 using std::ifstream;
17
18 #include <cstdlib>
19 #include <ctime>
20
21 int main()
22 {
23 const char *firstNames[] = { "Walter", "Alice", "Alan", "Mary", "Steve",
24 "Gina", "Tom", "Cindy", "Ilana", "Pam" },
25 *lastNames[] = { "Red", "Blue", "Yellow", "Orange", "Purple",
26 "Green", "Violet", "White", "Black", "Brown" };
27 ofstream outOldMaster( "oldMast.dat" ),
28 outTransaction( "trans.dat" );
29
30 int z;
31
32 srand( time( 0 ) );
33
34 if ( !outOldMaster ) {
35 cerr << "Unable to open oldmast.dat\n";
36 exit( EXIT_SUCCESS );
37 }
38
39 if ( !outTransaction ) {
Chapter 14 File Processing Solutions 375
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
40 cerr << "Unable to open trans.dat\n";
41 exit( EXIT_SUCCESS );
42 }
43
44 // write data to "oldmast.dat"
45 cout << setiosflags( ios::fixed | ios::showpoint )
46 << "Contents of \"oldmast.dat\":\n";
47
48 outOldMaster.setf( ios::fixed | ios::showpoint );
49 for ( z = 1; z < 11; ++z ) {
50 int value = rand() % 10, value2 = rand() % 50;
51 outOldMaster << z * 100 << ' ' << firstNames[ z - 1 ] << ' '
52 << lastNames[ value ] << ' ' << setprecision( 2 )
53 << ( value * 100 ) / ( value2 / 3 + 4.32 ) << '\n';
54 cout << z * 100 << ' ' << firstNames[ z - 1 ] << ' '
55 << lastNames[ value ] << ' ' << setprecision( 2 )
56 << ( value * 100 ) / ( value2 / 3 + 4.32 ) << '\n';
57 }
58
59 // write data to "trans.dat"
60 cout << "\nContents of \"trans.dat\":\n";
61 outTransaction.setf( ios::fixed | ios::showpoint );
62
63 for ( z = 1; z < 11; ++z ) {
64 int value = 25 - rand() % 50;
65 outTransaction << z * 100 << ' ' << setprecision( 2 )
66 << ( value * 100 ) / ( 2.667 * ( 1 + rand() % 10 ) )
67 << '\n';
68 cout << z * 100 << ' ' << setprecision( 2 )
69 << ( value * 100 ) / ( 2.667 * ( 1 + rand() % 10 ) ) << '\n';
70 }
71
72 outTransaction.close();
73 outOldMaster.close();
74
75 ifstream inMaster( "oldmast.dat" ), inTrans( "trans.dat" );
76 ofstream newMaster( "newMast.dat" );
77
78 if ( !inMaster ) {
79 cerr << "Unable to open oldmast.dat\n";
80 exit( EXIT_SUCCESS );
81 }
82
83 if ( !inTrans ) {
84 cerr << "Unable to open trans.dat\n";
85 exit( EXIT_SUCCESS );
86 }
87
88 if ( !newMaster ) {
89 cerr << "Unable to open newmast.dat\n";
90 exit( EXIT_SUCCESS );
91 }
92
93 int account, mAccount;
94 double balance, mBalance;
95 char mFirst[ 20 ], mLast[ 20 ];
96
97 cout << "Processing...\n";
98 inTrans >> account >> balance;
99
100 while ( !inTrans.eof() ) {
101 inMaster >> mAccount >> mFirst >> mLast >> mBalance;
376 File Processing Solutions Chapter 14
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Contents of “oldmast.dat”
102
103 while ( mAccount < account && !inMaster.eof() )
104 inMaster >> mAccount >> mFirst >> mLast >> mBalance;
105
106 if ( mAccount > account ) {
107 cout << "Unmatched transaction record: account " << account << '\n';
108
109 inTrans >> account >> balance;
110 }
111
112 if ( mAccount == account ) {
113 mBalance += balance;
114 newMaster << mAccount << ' ' << mFirst << ' ' << mLast
115 << ' ' << mBalance << '\n';
116 }
117
118 inTrans >> account >> balance;
119 }
120
121 newMaster.close();
122 inTrans.close();
123 inMaster.close();
124
125 return 0;
126 }
Contents of "oldmast.dat":
100 Walter Brown 46.58
200 Alice Orange 47.47
300 Alan Green 28.87
400 Mary Black 49.02
500 Steve White 67.83
600 Gina Orange 56.39
700 Tom White 38.21
800 Cindy Red 0.00
900 Ilana Brown 87.21
1000 Pam Red 0.00
Contents of "trans.dat":
100 -149.98
200 262.47
300 -41.24
400 -412.45
500 23.43
600 318.71
700 -224.97
800 -33.33
900 -249.97
1000 -71.24
Chapter 14 File Processing Solutions 377
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Contents of “trans.dat”
14.9 Run the program of Exercise 14.7 using the files of test data created in Exercise 14.8. Print the new master file. Check that
the accounts have been updated correctly.
ANS: Contents of newmast.dat
14.10 It is possible (actually common) to have several transaction records with the same record key. This occurs because a par-
ticular customer might make several purchases and cash payments during a business period. Rewrite your accounts receivable file-
matching program of Exercise 14.7 to provide for the possibility of handling several transaction records with the same record key.
Modify the test data of Exercise 14.8 to include the following additional transaction records:
100 Walter Brown 46.58
200 Alice Orange 47.47
300 Alan Green 28.87
400 Mary Black 49.02
500 Steve White 67.83
600 Gina Orange 56.39
700 Tom White 38.21
800 Cindy Red 0.00
900 Ilana Brown 87.21
1000 Pam Red 0.00
100 -149.98
200 262.47
300 -41.24
400 -412.45
500 23.43
600 318.71
700 -224.97
800 -33.33
900 -249.97
1000 -71.24
100 Walter Brown -103.40
200 Alice Orange 309.94
300 Alan Green -12.37
400 Mary Black -363.43
500 Steve White 91.26
600 Gina Orange 375.10
700 Tom White -186.76
800 Cindy Red -33.33
900 Ilana Brown -162.76
1000 Pam Red -71.24
Account number Dollar amount
300 83.89
700 80.78
700 1.53
1// Exercise 14.10 Solution
2#include <iostream>
378 File Processing Solutions Chapter 14
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3
4using std::cout;
5using std::ios;
6using std::cerr;
7
8#include <fstream>
9using std::ofstream;
10 using std::ifstream;
11
12 #include <iomanip>
13
14 using std::setprecision;
15 using std::setiosflags;
16
17 #include <cstdlib>
18
19 void printOutput( ofstream &, int, const char *, const char *, double );
20
21 int main()
22 {
23 int masterAccount, transactionAccount;
24 double masterBalance, transactionBalance;
25 char masterFirstName[ 20 ], masterLastName[ 20 ];
26
27 ifstream inOldmaster( "oldmast.dat" ),
28 inTransaction( "trans.dat" );
29 ofstream outNewmaster( "newmast.dat" );
30
31 if ( !inOldmaster ) {
32 cerr << "Unable to open oldmast.dat\n";
33 exit( EXIT_FAILURE );
34 }
35
36 if ( !inTransaction ) {
37 cerr << "Unable to open trans.dat\n";
38 exit( EXIT_FAILURE );
39 }
40
41 if ( !outNewmaster ) {
42 cerr << "Unable to open newmast.dat\n";
43 exit( EXIT_FAILURE );
44 }
45
46 cout << "Processing....\n";
47 inTransaction >> transactionAccount >> transactionBalance;
48
49 while ( !inTransaction.eof() ) {
50 inOldmaster >> masterAccount >> masterFirstName >> masterLastName
51 >> masterBalance;
52
53 while ( masterAccount < transactionAccount && !inOldmaster.eof() ) {
54 printOutput( outNewmaster, masterAccount, masterFirstName,
55 masterLastName, masterBalance );
56 inOldmaster >> masterAccount >> masterFirstName >> masterLastName
57 >> masterBalance;
58 }
59
60 if ( masterAccount > transactionAccount ) {
61 cout << "Unmatched transaction record for account "
62 << transactionAccount << '\n';
63 inTransaction >> transactionAccount >> transactionBalance;
64 }
65 else if ( masterAccount < transactionAccount ) {
Chapter 14 File Processing Solutions 379
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Contents of “oldmast.dat”
66 cout << "Unmatched transaction record for account "
67 << transactionAccount << '\n';
68 inTransaction >> transactionAccount >> transactionBalance;
69 }
70
71 while ( masterAccount == transactionAccount &&
72 !inTransaction.eof() ) {
73 masterBalance += transactionBalance;
74 inTransaction >> transactionAccount >> transactionBalance;
75 }
76
77 printOutput( outNewmaster, masterAccount, masterFirstName,
78 masterLastName, masterBalance );
79 }
80
81 inTransaction.close();
82 outNewmaster.close();
83 inOldmaster.close();
84
85 return 0;
86 }
87
88 void printOutput( ofstream &oRef, int mAccount, const char *mfName,
89 const char *mlName, double mBalance )
90 {
91 cout.setf( ios::showpoint | ios::fixed );
92 oRef.setf( ios::showpoint | ios::fixed );
93 oRef << mAccount << ' ' << mfName << ' ' << mlName << ' '
94 << setprecision( 2 ) << mBalance << '\n';
95 cout << mAccount << ' ' << mfName << ' ' << mlName << ' '
96 << setprecision( 2 ) << mBalance << '\n';
97 cout.unsetf( ios::showpoint | ios::fixed );
98 }
Processing....
100 Walter Brown -103.40
200 Alice Orange 309.94
300 Alan Green 71.52
400 Mary Black -363.43
500 Steve White 91.26
600 Gina Orange 375.10
700 Tom White -104.45
800 Cindy Red -33.33
900 Ilana Brown -162.76
1000 Pam Red -71.24
100 Walter Brown 46.58
200 Alice Orange 47.47
300 Alan Green 28.87
400 Mary Black 49.02
500 Steve White 67.83
600 Gina Orange 56.39
700 Tom White 38.21
800 Cindy Red 0.00
900 Ilana Brown 87.21
1000 Pam Red 0.00
380 File Processing Solutions Chapter 14
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Contents of “trans.dat”
Contents of “newmast.dat”
14.11 Write a series of statements that accomplish each of the following. Assume the structure
struct Person {
char lastName[ 15 ];
char firstName[ 15 ];
char age[ 4 ];
};
has been defined, and that the random-access file has been opened properly.
a) Initialize the file "nameage.dat" with 100 records containing lastName = "unassigned", firstName = ""
and age = "0".
ANS:
// fstream object "fileObject" corresponds to file "nameage.dat"
Person personInfo = { "unassigned", "", 0 };
for ( int r = 0; r < 100; ++r )
fileObject.write( reinterpret_cast< char * >( &personInfo,
sizeof( personInfo ) );
b) Input 10 last names, first names and ages, and write them to the file.
ANS:
fileObject.seekp( 0 );
for ( int x = 1; x <= 10; ++x ) {
cout << "Enter last name, first name, and age: ";
cin >> personInfo.lastName >> personInfo.firstName >> personInfo.age;
fileObject.write( reinterpret_cast< char * > &personInfo,
sizeof( personInfo ) );
}
100 -149.98
200 262.47
300 -41.24
300 83.89
400 -412.45
500 23.43
600 318.71
700 -224.97
700 80.78
700 1.53
800 -33.33
900 -249.97
1000 -71.24
100 Walter Brown -103.40
200 Alice Orange 309.94
300 Alan Green 71.52
400 Mary Black -363.43
500 Steve White 91.26
600 Gina Orange 375.10
700 Tom White -104.45
800 Cindy Red -33.33
900 Ilana Brown -162.76
1000 Pam Red -71.24
Chapter 14 File Processing Solutions 381
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
c) Update a record that has information in it, and if there is none, tell the user “No info.”
d) Delete a record that has information by reinitializing that particular record.
14.12 You are the owner of a hardware store and need to keep an inventory that can tell you what different tools you have, how
many of each you have on hand and the cost of each one. Write a program that initializes the random-access file "hard-
ware.dat" to one hundred empty records, lets you input the data concerning each tool, enables you to list all your tools, lets you
delete a record for a tool that you no longer have and lets you update any information in the file. The tool identification number
should be the record number. Use the following information to start your file:
Record # Tool name Quantity Cost
3Electric sander 7 57.98
17 Hammer 76 11.99
24 Jig saw 21 11.00
39 Lawn mower 3 79.50
56 Power saw 18 99.99
68 Screwdriver 106 6.99
77 Sledge hammer 11 21.50
83 Wrench 34 7.50
1// Exercise 14.12 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8using std::cerr;
9
10 #include <iomanip>
11
12 using std::setw;
13 using std::setprecision;
14 using std::setiosflags;
15
16 #include <fstream>
17 using std::ofstream;
18 using std::ifstream;
19
20 #include <cstring>
21 #include <cctype>
22 #include <cstdlib>
23
24 void initializeFile( fstream & );
25 void inputData( fstream & );
26 void listTools( fstream & );
27 void updateRecord( fstream & );
28 void insertRecord( fstream & );
29 void deleteRecord( fstream & );
30 int instructions( void );
31
32 const int LENGTH = 30;
33
34 struct Data {
35 int partNumber;
36 char toolName[ LENGTH ];
37 int inStock;
38 double unitPrice;
39 };
382 File Processing Solutions Chapter 14
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
40
41 int main()
42 {
43 int choice;
44 char response;
45 fstream file( "hardware.dat", ios::in | ios::out );
46 void ( *f[] )( fstream & ) = { listTools, updateRecord, insertRecord,
47 deleteRecord };
48
49 if ( !file ) {
50 cerr << "File could not be opened.\n";
51 exit( EXIT_FAILURE );
52 }
53
54 cout << "Should the file be initialized (Y or N): ";
55 cin >> response;
56
57 while ( toupper( response ) != 'Y' && toupper( response ) != 'N' ) {
58 cout << "Invalid response. Enter Y or N: ";
59 cin >> response;
60 }
61
62 if ( toupper( response ) == 'Y' ) {
63 initializeFile( file );
64 inputData( file );
65 }
66
67 while ( ( choice = instructions() ) != 5 ) {
68 ( *f[ choice - 1 ] )( file );
69 file.clear(); // reset eof indicator
70 }
71
72 file.close();
73
74 return 0;
75 }
76
77 void initializeFile( fstream &fRef )
78 {
79 Data blankItem = { -1, "", 0, 0.0 };
80
81 // See Chapter 21 for a discussion of reinterpret_cast
82 for ( int i = 0; i < 100; ++i )
83 fRef.write( reinterpret_cast< char * >( &blankItem ), sizeof( Data ) );
84 }
85
86 void inputData( fstream &fRef )
87 {
88 Data temp;
89
90 cout << "Enter the partnumber (0 - 99, -1 to end input): ";
91 cin >> temp.partNumber;
92
93 while ( temp.partNumber != -1 ) {
94 cout << "Enter the tool name: ";
95 cin.ignore(); // ignore the newline on the input stream
96 cin.get( temp.toolName, LENGTH );
97 cout << "Enter quantity and price: ";
98 cin >> temp.inStock >> temp.unitPrice;
99 fRef.seekp( ( temp.partNumber ) * sizeof( Data ) );
100 fRef.write( reinterpret_cast< char * >( &temp ), sizeof( Data ) );
101
Chapter 14 File Processing Solutions 383
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
102 cout << "Enter the partnumber (0 - 99, -1 to end input): ";
103 cin >> temp.partNumber;
104 }
105 }
106
107 int instructions( void )
108 {
109 int choice;
110
111 cout << "\nEnter a choice:\n1 List all tools."
112 << "\n2 Update record.\n3 Insert record."
113 << "\n4 Delete record.\n5 End program.\n";
114
115 do {
116 cout << "? ";
117 cin >> choice;
118 } while ( choice < 1 || choice > 5 );
119
120 return choice;
121 }
122
123 void listTools( fstream &fRef )
124 {
125 Data temp;
126
127 cout << setw( 7 ) << "Record#" << " " << setiosflags( ios::left )
128 << setw( 30 ) << "Tool name" << resetiosflags( ios::left )
129 << setw( 13 ) << "Quantity" << setw( 10 ) << "Cost\n";
130
131 for ( int count = 0; count < 100 && !fRef.eof(); ++count ) {
132 fRef.seekg( count * sizeof( Data ) );
133 fRef.read( reinterpret_cast< char * >( &temp ), sizeof( Data ) );
134
135 if ( temp.partNumber >= 0 && temp.partNumber < 100 ) {
136 cout.setf( ios::fixed | ios::showpoint );
137 cout << setw( 7 ) << temp.partNumber << " "
138 << setiosflags( ios::left ) << setw( 30 ) << temp.toolName
139 << resetiosflags( ios::left ) << setw( 13 ) << temp.inStock
140 << setprecision( 2 ) << setw( 10 ) << temp.unitPrice << '\n';
141 }
142 }
143 }
144
145 void updateRecord( fstream &fRef )
146 {
147 Data temp;
148 int part;
149
150 cout << "Enter the part number for update: ";
151 cin >> part;
152 fRef.seekg( part * sizeof( Data ) );
153 fRef.read( reinterpret_cast< char * >( &temp ), sizeof( Data ) );
154
155 if ( temp.partNumber != -1 ) {
156 cout << setw( 7 ) << "Record#" << " " << setiosflags( ios::left )
157 << setw( 30 ) << "Tool name" << resetiosflags( ios::left )
158 << setw( 13 ) << "Quantity" << setw( 10 ) << "Cost\n";
159
160 cout.setf( ios::fixed | ios::showpoint );
161 cout << setw( 7 ) << temp.partNumber << " "
162 << setiosflags( ios::left ) << setw( 30 ) << temp.toolName
163 << resetiosflags( ios::left ) << setw( 13 ) << temp.inStock
384 File Processing Solutions Chapter 14
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
164 << setprecision( 2 ) << setw( 10 ) << temp.unitPrice << '\n'
165 << "Enter the tool name: ";
166
167 cin.ignore(); // ignore the newline on the input stream
168 cin.get( temp.toolName, LENGTH );
169 cout << "Enter quantity and price: ";
170 cin >> temp.inStock >> temp.unitPrice;
171
172 fRef.seekp( ( temp.partNumber ) * sizeof( Data ) );
173 fRef.write( reinterpret_cast< char * > ( &temp ), sizeof( Data ) );
174 }
175 else
176 cerr << "Cannot update. The record is empty.\n";
177 }
178
179 void insertRecord( fstream &fRef )
180 {
181 Data temp;
182 int part;
183
184 cout << "Enter the partnumber for insertion: ";
185 cin >> part;
186 fRef.seekg( ( part ) * sizeof( Data ) );
187 fRef.read( reinterpret_cast< char * > ( &temp ), sizeof( Data ) );
188
189 if ( temp.partNumber == -1 ) {
190 temp.partNumber = part;
191 cout << "Enter the tool name: ";
192 cin.ignore(); // ignore the newline on the input stream
193 cin.get( temp.toolName, LENGTH );
194 cout << "Enter quantity and price: ";
195 cin >> temp.inStock >> temp.unitPrice;
196
197 fRef.seekp( ( temp.partNumber ) * sizeof( Data ) );
198 fRef.write( reinterpret_cast< char * >( &temp ), sizeof( Data ) );
199 }
200 else
201 cerr << "Cannot insert. The record contains information.\n";
202 }
203
204 void deleteRecord( fstream &fRef )
205 {
206 Data blankItem = { -1, "", 0, 0.0 }, temp;
207 int part;
208
209 cout << "Enter the partnumber for deletion: ";
210 cin >> part;
211
212 fRef.seekg( part * sizeof( Data ) );
213 fRef.read( reinterpret_cast< char * >( &temp ), sizeof( Data ) );
214
215 if ( temp.partNumber != -1 ) {
216 fRef.seekp( part * sizeof( Data ) );
217 fRef.write( reinterpret_cast< char * >( &blankItem ), sizeof( Data ) );
218 cout << "Record deleted.\n";
219 }
220 else
221 cerr << "Cannot delete. The record is empty.\n";
222 }
Chapter 14 File Processing Solutions 385
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Should the file be initialized (Y or N): Y
Enter the partnumber (0 - 99, -1 to end input): 77
Enter the tool name: Sledge hammer
Enter quantity and price: 11 21.50
Enter the partnumber (0 - 99, -1 to end input): -1
Enter a choice:
1 List all tools.
2 Update record.
3 Insert record.
4 Delete record.
5 End program.
? 1
Record# Tool name Quantity Cost
77 Sledge hammer 11 21.50
Enter a choice:
1 List all tools.
2 Update record.
3 Insert record.
4 Delete record.
5 End program.
? 3
Enter the partnumber for insertion: 44
Enter the tool name: Pipe wrench
Enter quantity and price: 1 19.99
Enter a choice:
1 List all tools.
2 Update record.
3 Insert record.
4 Delete record.
5 End program.
? 2
Enter the part number for update: 44
Record# Tool name Quantity Cost
44 Pipe wrench 1 19.99
Enter the tool name: Pipe wrench
Enter quantity and price: 1 14.99
Enter a choice:
1 List all tools.
2 Update record.
3 Insert record.
4 Delete record.
5 End program.
? 1
Record# Tool name Quantity Cost
44 Pipe wrench 1 14.99
77 Sledge hammer 11 21.50
Enter a choice:
1 List all tools.
2 Update record.
3 Insert record.
4 Delete record.
5 End program.
? 4
Enter the partnumber for deletion: 44
Record deleted.
...
386 File Processing Solutions Chapter 14
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
14.13 Modify the telephone number word-generating program you wrote in Chapter 4 so that it writes its output to a file. This
allows you to read the file at your convenience. If you have a computerized dictionary available, modify your program to look up
the thousands of seven-letter words in the dictionary. Some of the interesting seven-letter combinations created by this program may
consist of two or more words. For example, the phone number 8432677 produces “THEBOSS.” Modify your program to use the
computerized dictionary to check each possible seven-letter word to see if it is a valid one-letter word followed by a valid six-letter
word, a valid two-letter word followed by a valid five-letter word, etc.
1// Exercise 14.13 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6using std::ios;
7using std::cerr;
8
9#include <fstream>
10 using std::ofstream;
11 using std::ifstream;
12
13 #include <cstdlib>
14 #include <cctype>
15
16 void wordGenerator( const int * const );
17
18 int main()
19 {
20 int phoneNumber[ 7 ] = { 0 };
21
22 cout << "Enter a phone number (digits 2 through 9) "
23 << "in the form: xxx-xxxx\n";
24
25 // loop 8 times: 7 digits plus hyphen
26 // hyphen is is not placed in phoneNumber
27 for ( int u = 0, v = 0; u < 8; ++u ) {
28 int i = cin.get();
29
30 // See chapter 16 for a discussion of isdigit
31 if ( isdigit( i ) ) // ctype library
32 phoneNumber[ v++ ] = i - '0';
33 }
34
35 wordGenerator( phoneNumber );
36
37 return 0;
38 }
39
40 void wordGenerator( const int * const n )
41 {
42 ofstream outFile( "phone.dat" );
43 const char *phoneLetters[ 10 ] = { "", "", "ABC", "DEF", "GHI", "JKL",
44 "MNO", "PRS", "TUV", "WXY" };
45
46 if ( !outFile ) {
47 cerr << "\"phone.dat\" could not be opened.\n";
48 exit( EXIT_FAILURE );
49 }
50
51 int count = 0;
52
53 // output all possible combinations
54 for ( int i1 = 0; i1 <= 2; ++i1 )
Chapter 14 File Processing Solutions 387
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Contents of phone.dat
14.14 Write a program that uses the sizeof operator to determine the sizes in bytes of the various data types on your computer
system. Write the results to the file "datasize.dat" so you may print the results later. The format for the results in the file
should be
55 for ( int i2 = 0; i2 <= 2; ++i2 )
56 for ( int i3 = 0; i3 <= 2; ++i3 )
57 for ( int i4 = 0; i4 <= 2; ++i4 )
58 for ( int i5 = 0; i5 <= 2; ++i5 )
59 for ( int i6 = 0; i6 <= 2; ++i6 )
60 for ( int i7 = 0; i7 <= 2; ++i7 ) {
61 outFile << phoneLetters[ n[ 0 ] ][ i1 ]
62 << phoneLetters[ n[ 1 ] ][ i2 ]
63 << phoneLetters[ n[ 2 ] ][ i3 ]
64 << phoneLetters[ n[ 3 ] ][ i4 ]
65 << phoneLetters[ n[ 4 ] ][ i5 ]
66 << phoneLetters[ n[ 5 ] ][ i6 ]
67 << phoneLetters[ n[ 6 ] ][ i7 ] << ' ';
68
69 if ( ++count % 9 == 0 )
70 outFile << '\n';
71 }
72
73 outFile << "\nPhone number is ";
74
75 for ( int i = 0; i < 7; ++i ) {
76 if ( i == 3 )
77 outFile << '-';
78
79 outFile << n[ i ];
80 }
81
82 outFile.close();
83 }
TMPJDPW TMPJDPX TMPJDPY TMPJDRW TMPJDRX TMPJDRY TMPJDSW TMPJDSX TMPJDSY
TMPJEPW TMPJEPX TMPJEPY TMPJERW TMPJERX TMPJERY TMPJESW TMPJESX TMPJESY
TMPJFPW TMPJFPX TMPJFPY TMPJFRW TMPJFRX TMPJFRY TMPJFSW TMPJFSX TMPJFSY
TMPKDPW TMPKDPX TMPKDPY TMPKDRW TMPKDRX TMPKDRY TMPKDSW TMPKDSX TMPKDSY
TMPKEPW TMPKEPX TMPKEPY TMPKERW TMPKERX TMPKERY TMPKESW TMPKESX TMPKESY
...
VOSLDPW VOSLDPX VOSLDPY VOSLDRW VOSLDRX VOSLDRY VOSLDSW VOSLDSX VOSLDSY
VOSLEPW VOSLEPX VOSLEPY VOSLERW VOSLERX VOSLERY VOSLESW VOSLESX VOSLESY
VOSLFPW VOSLFPX VOSLFPY VOSLFRW VOSLFRX VOSLFRY VOSLFSW VOSLFSX VOSLFSY
Phone number is 867-5379
Data type Size
char 1
unsigned char 1
short int 2
unsigned short int 2
int 4
unsigned int 4
388 File Processing Solutions Chapter 14
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Note: The sizes of the built-in data types on your computer may differ from those listed above.
long int 4
unsigned long int 4
float 4
double 8
long double 16
1// Exercise 14.14 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cerr;
7
8#include <iomanip>
9
10 using std::setw;
11
12 #include <fstream>
13
14 using std::ofstream;
15 using std::ifstream;
16
17 #include <cstdlib>
18
19 int main()
20 {
21 ofstream outFile( "datasize.dat" );
22
23 if ( !outFile ) {
24 cerr << "Unable to open \"datasize.dat\".\n";
25 exit( EXIT_FAILURE );
26 }
27
28 outFile << "Data type" << setw( 16 ) << "Size\nchar"
29 << setw( 21 ) << sizeof( char )
30 << "\nunsigned char" << setw( 12 ) << sizeof( unsigned char )
31 << "\nshort int" << setw(16) << sizeof( short int )
32 << "\nunsigned short int" << setw( 7 ) << sizeof( unsigned short )
33 << "\nint" << setw( 22 ) << sizeof( int ) << '\n';
34
35 outFile << "unsigned int" << setw( 13 ) << sizeof( unsigned )
36 << "\nlong int" << setw( 17 ) << sizeof( long )
37 << "\nunsigned long int" << setw( 8 ) << sizeof( unsigned long )
38 << "\ndouble" << setw( 20 ) << sizeof( double )
39 << "\ndouble" << setw( 19 ) << sizeof( double )
40 << "\nlong double" << setw( 14 ) << sizeof( long double ) << endl;
41
42 outFile.close();
43
44 return 0;
45 }
Data type Size
Chapter 14 File Processing Solutions 389
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Contents of datasize.dat
Data type Size
char 1
unsigned char 1
short int 2
unsigned short int 2
int 4
unsigned int 4
long int 4
unsigned long int 4
float 4
double 8
long double 8
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15
Data Structures
Solutions
Solutions
15.6 Write a program that concatenates two linked list objects of characters. The program should include function concate-
nate, which takes references to both list objects as arguments and concatenates the second list to the first list.
1// LIST.H
2// Template List class definition
3// Added copy constructor to member functions (not included in chapter).
4#ifndef LIST_H
5#define LIST_H
6
7#include <iostream>
8
9using std::cout;
10
11 #include <cassert>
12 #include "listnd.h"
13
14 template< class NODETYPE >
15 class List {
16 public:
17 List(); // default constructor
18 List( const List< NODETYPE > & ); // copy constructor
19 ~List(); // destructor
20 void insertAtFront( const NODETYPE & );
21 void insertAtBack( const NODETYPE & );
22 bool removeFromFront( NODETYPE & );
23 bool removeFromBack( NODETYPE & );
24 bool isEmpty() const;
25 void print() const;
26 protected:
27 ListNode< NODETYPE > *firstPtr; // pointer to first node
28 ListNode< NODETYPE > *lastPtr; // pointer to last node
29
30 // Utility function to allocate a new node
31 ListNode< NODETYPE > *getNewNode( const NODETYPE & );
Chapter 15 Data Structures Solutions 391
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
32 };
33
34 // Default constructor
35 template< class NODETYPE >
36 List< NODETYPE >::List() { firstPtr = lastPtr = 0; }
37
38 // Copy constructor
39 template< class NODETYPE >
40 List< NODETYPE >::List( const List<NODETYPE> &copy )
41 {
42 firstPtr = lastPtr = 0; // initialize pointers
43
44 ListNode< NODETYPE > *currentPtr = copy.firstPtr;
45
46 while ( currentPtr != 0 ) {
47 insertAtBack( currentPtr -> data );
48 currentPtr = currentPtr -> nextPtr;
49 }
50 }
51
52 // Destructor
53 template< class NODETYPE >
54 List< NODETYPE >::~List()
55 {
56 if ( !isEmpty() ) { // List is not empty
57 cout << "Destroying nodes ...\n";
58
59 ListNode< NODETYPE > *currentPtr = firstPtr, *tempPtr;
60
61 while ( currentPtr != 0 ) { // delete remaining nodes
62 tempPtr = currentPtr;
63 cout << tempPtr -> data << ' ';
64 currentPtr = currentPtr -> nextPtr;
65 delete tempPtr;
66 }
67 }
68
69 cout << "\nAll nodes destroyed\n\n";
70 }
71
72 // Insert a node at the front of the list
73 template< class NODETYPE >
74 void List< NODETYPE >::insertAtFront( const NODETYPE &value )
75 {
76 ListNode<NODETYPE> *newPtr = getNewNode( value );
77
78 if ( isEmpty() ) // List is empty
79 firstPtr = lastPtr = newPtr;
80 else { // List is not empty
81 newPtr -> nextPtr = firstPtr;
82 firstPtr = newPtr;
83 }
84 }
85
86 // Insert a node at the back of the list
87 template< class NODETYPE >
88 void List< NODETYPE >::insertAtBack( const NODETYPE &value )
89 {
90 ListNode< NODETYPE > *newPtr = getNewNode( value );
91
92 if ( isEmpty() ) // List is empty
93 firstPtr = lastPtr = newPtr;
392 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
94 else { // List is not empty
95 lastPtr -> nextPtr = newPtr;
96 lastPtr = newPtr;
97 }
98 }
99
100 // Delete a node from the front of the list
101 template< class NODETYPE >
102 bool List< NODETYPE >::removeFromFront( NODETYPE &value )
103 {
104 if ( isEmpty() ) // List is empty
105 return false; // delete unsuccessful
106 else {
107 ListNode< NODETYPE > *tempPtr = firstPtr;
108
109 if ( firstPtr == lastPtr )
110 firstPtr = lastPtr = 0;
111 else
112 firstPtr = firstPtr -> nextPtr;
113
114 value = tempPtr -> data; // data being removed
115 delete tempPtr;
116 return true; // delete successful
117 }
118 }
119
120 // Delete a node from the back of the list
121 template< class NODETYPE >
122 bool List< NODETYPE >::removeFromBack( NODETYPE &value )
123 {
124 if ( isEmpty() )
125 return false; // delete unsuccessful
126 else {
127 ListNode< NODETYPE > *tempPtr = lastPtr;
128
129 if ( firstPtr == lastPtr )
130 firstPtr = lastPtr = 0;
131 else {
132 ListNode< NODETYPE > *currentPtr = firstPtr;
133
134 while ( currentPtr -> nextPtr != lastPtr )
135 currentPtr = currentPtr -> nextPtr;
136
137 lastPtr = currentPtr;
138 currentPtr -> nextPtr = 0;
139 }
140
141 value = tempPtr -> data;
142 delete tempPtr;
143 return true; // delete successful
144 }
145 }
146
147 // Is the List empty?
148 template< class NODETYPE >
149 bool List< NODETYPE >::isEmpty() const { return firstPtr == 0; }
150
151 // Return a pointer to a newly allocated node
152 template< class NODETYPE >
153 ListNode< NODETYPE > *List< NODETYPE >::getNewNode( const NODETYPE &value )
154 {
155 ListNode< NODETYPE > *ptr = new ListNode< NODETYPE >( value );
Chapter 15 Data Structures Solutions 393
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
156 assert( ptr != 0 );
157 return ptr;
158 }
159
160 // Display the contents of the List
161 template< class NODETYPE >
162 void List< NODETYPE >::print() const
163 {
164 if ( isEmpty() ) {
165 cout << "The list is empty\n\n";
166 return;
167 }
168
169 ListNode< NODETYPE > *currentPtr = firstPtr;
170
171 cout << "The list is: ";
172
173 while ( currentPtr != 0 ) {
174 cout << currentPtr -> data << ' ';
175 currentPtr = currentPtr -> nextPtr;
176 }
177
178 cout << "\n\n";
179 }
180
181 #endif
182 // LISTND.H
183 // ListNode template definition
184 #ifndef LISTND_H
185 #define LISTND_H
186
187 template< class T > class List; // forward declaration
188
189 template< class NODETYPE >
190 class ListNode {
191 friend class List< NODETYPE >; // make List a friend
192 public:
193 ListNode( const NODETYPE & ); // constructor
194 NODETYPE getData() const; // return the data in the node
195 void setNextPtr( ListNode *nPtr ) { nextPtr = nPtr; }
196 ListNode *getNextPtr() const { return nextPtr; }
197 private:
198 NODETYPE data; // data
199 ListNode *nextPtr; // next node in the list
200 };
201
202 // Constructor
203 template< class NODETYPE >
204 ListNode< NODETYPE >::ListNode( const NODETYPE &info )
205 {
206 data = info;
207 nextPtr = 0;
208 }
209
210 // Return a copy of the data in the node
211 template< class NODETYPE >
212 NODETYPE ListNode< NODETYPE >::getData() const { return data; }
213
214 #endif
394 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
215 // Exercise 15.6 solution
216 #include <iostream>
217
218 using std::cout;
219
220 #include "list.h"
221
222 template< class T >
223 void concatenate( List< T > &first, List< T > &second )
224 {
225 List< T > temp( second ); // create a copy of second
226 T value; // variable to store removed item from temp
227
228 while ( !temp.isEmpty() ) {
229 temp.removeFromFront( value ); // remove value from temp list
230 first.insertAtBack( value ); // insert at end of first list
231 }
232 }
233
234 int main()
235 {
236 List< char > list1, list2;
237 char c;
238
239 for ( c = 'a'; c <= 'e'; ++c )
240 list1.insertAtBack( c );
241
242 list1.print();
243
244 for ( c = 'f'; c <= 'j'; ++c )
245 list2.insertAtBack( c );
246
247 list2.print();
248
249 concatenate( list1, list2 );
250 cout << "The new list1 after concatenation is:\n";
251 list1.print();
252
253 return 0;
254 }
The list is: a b c d e
The list is: f g h i j
All nodes destroyed
The new list1 after concatenation is:
The list is: a b c d e f g h i j
Destroying nodes ...
f g h i j
All nodes destroyed
Destroying nodes ...
a b c d e f g h i j
All nodes destroyed
Chapter 15 Data Structures Solutions 395
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.7 Write a program that merges two ordered list objects of integers into a single ordered list object of integers. Function
merge should receive references to each of the list objects to be merged, and should return an object containing the merged list.
1// LIST.H
2// Template List class definition
3#ifndef LIST_H
4#define LIST_H
5
6#include <iostream>
7
8using std::cout;
9
10 #include <cassert>
11 #include "listnd.h"
12
13 template< class NODETYPE >
14 class List {
15 public:
16 List(); // default constructor
17 List( const List< NODETYPE > & ); // copy constructor
18 ~List(); // destructor
19 void insertAtFront( const NODETYPE & );
20 void insertAtBack( const NODETYPE & );
21 bool removeFromFront( NODETYPE & );
22 bool removeFromBack( NODETYPE & );
23 bool isEmpty() const;
24 void print() const;
25 protected:
26 ListNode< NODETYPE > *firstPtr; // pointer to first node
27 ListNode< NODETYPE > *lastPtr; // pointer to last node
28
29 // Utility function to allocate a new node
30 ListNode< NODETYPE > *getNewNode( const NODETYPE & );
31 };
32
33 // Default constructor
34 template< class NODETYPE >
35 List< NODETYPE >::List() { firstPtr = lastPtr = 0; }
36
37 // Copy constructor
38 template< class NODETYPE >
39 List< NODETYPE >::List( const List<NODETYPE> &copy )
40 {
41 firstPtr = lastPtr = 0; // initialize pointers
42
43 ListNode< NODETYPE > *currentPtr = copy.firstPtr;
44
45 while ( currentPtr != 0 ) {
46 insertAtBack( currentPtr -> data );
47 currentPtr = currentPtr -> nextPtr;
48 }
49 }
50
51 // Destructor
52 template< class NODETYPE >
53 List< NODETYPE >::~List()
54 {
55 if ( !isEmpty() ) { // List is not empty
56 cout << "Destroying nodes ...\n";
57
58 ListNode< NODETYPE > *currentPtr = firstPtr, *tempPtr;
396 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
59
60 while ( currentPtr != 0 ) { // delete remaining nodes
61 tempPtr = currentPtr;
62 cout << tempPtr -> data << ' ';
63 currentPtr = currentPtr -> nextPtr;
64 delete tempPtr;
65 }
66 }
67
68 cout << "\nAll nodes destroyed\n\n";
69 }
70
71 // Insert a node at the front of the list
72 template< class NODETYPE >
73 void List< NODETYPE >::insertAtFront( const NODETYPE &value )
74 {
75 ListNode<NODETYPE> *newPtr = getNewNode( value );
76
77 if ( isEmpty() ) // List is empty
78 firstPtr = lastPtr = newPtr;
79 else { // List is not empty
80 newPtr -> nextPtr = firstPtr;
81 firstPtr = newPtr;
82 }
83 }
84
85 // Insert a node at the back of the list
86 template< class NODETYPE >
87 void List< NODETYPE >::insertAtBack( const NODETYPE &value )
88 {
89 ListNode< NODETYPE > *newPtr = getNewNode( value );
90
91 if ( isEmpty() ) // List is empty
92 firstPtr = lastPtr = newPtr;
93 else { // List is not empty
94 lastPtr -> nextPtr = newPtr;
95 lastPtr = newPtr;
96 }
97 }
98
99 // Delete a node from the front of the list
100 template< class NODETYPE >
101 bool List< NODETYPE >::removeFromFront( NODETYPE &value )
102 {
103 if ( isEmpty() ) // List is empty
104 return false; // delete unsuccessful
105 else {
106 ListNode< NODETYPE > *tempPtr = firstPtr;
107
108 if ( firstPtr == lastPtr )
109 firstPtr = lastPtr = 0;
110 else
111 firstPtr = firstPtr -> nextPtr;
112
113 value = tempPtr -> data; // data being removed
114 delete tempPtr;
115 return true; // delete successful
116 }
117 }
118
119 // Delete a node from the back of the list
120 template< class NODETYPE >
Chapter 15 Data Structures Solutions 397
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
121 bool List< NODETYPE >::removeFromBack( NODETYPE &value )
122 {
123 if ( isEmpty() )
124 return false; // delete unsuccessful
125 else {
126 ListNode< NODETYPE > *tempPtr = lastPtr;
127
128 if ( firstPtr == lastPtr )
129 firstPtr = lastPtr = 0;
130 else {
131 ListNode< NODETYPE > *currentPtr = firstPtr;
132
133 while ( currentPtr -> nextPtr != lastPtr )
134 currentPtr = currentPtr -> nextPtr;
135
136 lastPtr = currentPtr;
137 currentPtr -> nextPtr = 0;
138 }
139
140 value = tempPtr -> data;
141 delete tempPtr;
142 return true; // delete successful
143 }
144 }
145
146 // Is the List empty?
147 template< class NODETYPE >
148 bool List< NODETYPE >::isEmpty() const { return firstPtr == 0; }
149
150 // Return a pointer to a newly allocated node
151 template< class NODETYPE >
152 ListNode< NODETYPE > *List< NODETYPE >::getNewNode( const NODETYPE &value )
153 {
154 ListNode< NODETYPE > *ptr = new ListNode< NODETYPE >( value );
155 assert( ptr != 0 );
156 return ptr;
157 }
158
159 // Display the contents of the List
160 template< class NODETYPE >
161 void List< NODETYPE >::print() const
162 {
163 if ( isEmpty() ) {
164 cout << "The list is empty\n\n";
165 return;
166 }
167
168 ListNode< NODETYPE > *currentPtr = firstPtr;
169
170 cout << "The list is: ";
171
172 while ( currentPtr != 0 ) {
173 cout << currentPtr -> data << ' ';
174 currentPtr = currentPtr -> nextPtr;
175 }
176
177 cout << "\n\n";
178 }
179
180 #endif
398 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
181 // LISTND.H
182 // ListNode template definition
183 #ifndef LISTND_H
184 #define LISTND_H
185
186 template< class T > class List; // forward declaration
187
188 template< class NODETYPE >
189 class ListNode {
190 friend class List< NODETYPE >; // make List a friend
191 public:
192 ListNode( const NODETYPE & ); // constructor
193 NODETYPE getData() const; // return the data in the node
194 void setNextPtr( ListNode *nPtr ) { nextPtr = nPtr; }
195 ListNode *getNextPtr() const { return nextPtr; }
196 private:
197 NODETYPE data; // data
198 ListNode *nextPtr; // next node in the list
199 };
200
201 // Constructor
202 template< class NODETYPE >
203 ListNode< NODETYPE >::ListNode( const NODETYPE &info )
204 {
205 data = info;
206 nextPtr = 0;
207 }
208
209 // Return a copy of the data in the node
210 template< class NODETYPE >
211 NODETYPE ListNode< NODETYPE >::getData() const { return data; }
212
213 #endif
214 // Exercise 15.7 solution
215 #include <iostream>
216
217 using std::cout;
218
219 #include "list.h"
220
221 template< class T >
222 List< T > &merge( List< T > &first, List< T > &second )
223 {
224 // If both lists are empty, return an empty result
225 if ( first.isEmpty() && second.isEmpty() ) {
226 List< T > *ptr = new List< T >; // dynamically allocated
227 return *ptr;
228 }
229
230 // If first list is empty, return result containing second list
231 if ( first.isEmpty() ) {
232 List< T > *ptr = new List< T >( second ); // dynamically allocated
233 return *ptr;
234 }
235
236 // If second list is empty, return result containing first list
237 if ( second.isEmpty() ) {
238 List< T > *ptr = new List< T >( first ); // dynamically allocated
239 return *ptr;
240 }
Chapter 15 Data Structures Solutions 399
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
241
242 List< T > tempFirst( first ), // create a copy of first
243 tempSecond( second ); // create a copy of second
244 List< T > *ptr = new List< T >; // dynamically allocated result object
245 T value1, value2;
246
247 tempFirst.removeFromFront( value1 );
248 tempSecond.removeFromFront( value2 );
249
250 while ( !tempFirst.isEmpty() && !tempSecond.isEmpty() ) {
251 if ( value1 <= value2 ) {
252 ptr -> insertAtBack( value1 );
253 tempFirst.removeFromFront( value1 );
254 }
255 else {
256 ptr -> insertAtBack( value2 );
257 tempSecond.removeFromFront( value2 );
258 }
259 }
260
261 // Insert the values currently in value1 and value2
262 if ( value1 < value2 ) {
263 ptr -> insertAtBack( value1 );
264 ptr -> insertAtBack( value2 );
265 }
266 else {
267 ptr -> insertAtBack( value2 );
268 ptr -> insertAtBack( value1 );
269 }
270
271 // Complete the insertion of the list that is not empty.
272 // NOTE: Only one of the following 2 while structures will execute
273 // because one of the lists must be empty to exit the preceding while.
274 if ( !tempFirst.isEmpty() ) // Items left in tempFirst? Insert in result.
275 do {
276 tempFirst.removeFromFront( value1 );
277 ptr -> insertAtBack( value2 );
278 } while ( !tempFirst.isEmpty() );
279 else // Items left in tempSecond? Insert in result.
280 do {
281 tempSecond.removeFromFront( value2 );
282 ptr -> insertAtBack( value2 );
283 } while ( !tempSecond.isEmpty() );
284
285 return *ptr;
286 }
287
288 int main()
289 {
290 List< int > list1, list2;
291 int i;
292
293 for ( i = 1; i <= 9; i += 2 )
294 list1.insertAtBack( i );
295
296 list1.print();
297
298 for ( i = 2; i <= 10; i += 2 )
299 list2.insertAtBack( i );
300
301 list2.print();
302
400 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.8 Write a program that inserts 25 random integers from 0 to 100 in order in a linked list object. The program should calculate
the sum of the elements and the floating-point average of the elements.
303 List< int > &listRef = merge( list1, list2 );
304
305 cout << "The merged list is:\n";
306 listRef.print();
307
308 delete &listRef; // delete the dynamically allocated list
309
310 return 0;
311 }
The list is: 1 3 5 7 9
The list is: 2 4 6 8 10
All nodes destroyed
All nodes destroyed
The merged list is:
The list is: 1 2 3 4 5 6 7 8 9 10
Destroying nodes ...
1 2 3 4 5 6 7 8 9 10
All nodes destroyed
Destroying nodes ...
2 4 6 8 10
All nodes destroyed
Destroying nodes ...
1 3 5 7 9
All nodes destroyed
1// LIST
2// Template List class definition
3// Added copy constructor to member functions (not included in chapter).
4#ifndef LIST_H
5#define LIST_H
6
7#include <iostream>
8
9using std::cout;
10
11 #include <cassert>
12 #include "Listnd.h"
13
14 template< class NODETYPE >
15 class List {
16 public:
17 List(); // default constructor
18 List( const List< NODETYPE > & ); // copy constructor
19 ~List(); // destructor
20 void insertAtFront( const NODETYPE & );
21 void insertAtBack( const NODETYPE & );
Chapter 15 Data Structures Solutions 401
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
22 bool removeFromFront( NODETYPE & );
23 bool removeFromBack( NODETYPE & );
24 bool isEmpty() const;
25 void print() const;
26 protected:
27 ListNode< NODETYPE > *firstPtr; // pointer to first node
28 ListNode< NODETYPE > *lastPtr; // pointer to last node
29
30 // Utility function to allocate a new node
31 ListNode< NODETYPE > *getNewNode( const NODETYPE & );
32 };
33
34 // Default constructor
35 template< class NODETYPE >
36 List< NODETYPE >::List() { firstPtr = lastPtr = 0; }
37
38 // Copy constructor
39 template< class NODETYPE >
40 List< NODETYPE >::List( const List<NODETYPE> &copy )
41 {
42 firstPtr = lastPtr = 0; // initialize pointers
43
44 ListNode< NODETYPE > *currentPtr = copy.firstPtr;
45
46 while ( currentPtr != 0 ) {
47 insertAtBack( currentPtr -> data );
48 currentPtr = currentPtr -> nextPtr;
49 }
50 }
51
52 // Destructor
53 template< class NODETYPE >
54 List< NODETYPE >::~List()
55 {
56 if ( !isEmpty() ) { // List is not empty
57 cout << "Destroying nodes ...\n";
58
59 ListNode< NODETYPE > *currentPtr = firstPtr, *tempPtr;
60
61 while ( currentPtr != 0 ) { // delete remaining nodes
62 tempPtr = currentPtr;
63 cout << tempPtr -> data << ' ';
64 currentPtr = currentPtr -> nextPtr;
65 delete tempPtr;
66 }
67 }
68
69 cout << "\nAll nodes destroyed\n\n";
70 }
71
72 // Insert a node at the front of the list
73 template< class NODETYPE >
74 void List< NODETYPE >::insertAtFront( const NODETYPE &value )
75 {
76 ListNode<NODETYPE> *newPtr = getNewNode( value );
77
78 if ( isEmpty() ) // List is empty
79 firstPtr = lastPtr = newPtr;
80 else { // List is not empty
81 newPtr -> nextPtr = firstPtr;
82 firstPtr = newPtr;
83 }
402 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
84 }
85
86 // Insert a node at the back of the list
87 template< class NODETYPE >
88 void List< NODETYPE >::insertAtBack( const NODETYPE &value )
89 {
90 ListNode< NODETYPE > *newPtr = getNewNode( value );
91
92 if ( isEmpty() ) // List is empty
93 firstPtr = lastPtr = newPtr;
94 else { // List is not empty
95 lastPtr -> nextPtr = newPtr;
96 lastPtr = newPtr;
97 }
98 }
99
100 // Delete a node from the front of the list
101 template< class NODETYPE >
102 bool List< NODETYPE >::removeFromFront( NODETYPE &value )
103 {
104 if ( isEmpty() ) // List is empty
105 return false; // delete unsuccessful
106 else {
107 ListNode< NODETYPE > *tempPtr = firstPtr;
108
109 if ( firstPtr == lastPtr )
110 firstPtr = lastPtr = 0;
111 else
112 firstPtr = firstPtr -> nextPtr;
113
114 value = tempPtr -> data; // data being removed
115 delete tempPtr;
116 return true; // delete successful
117 }
118 }
119
120 // Delete a node from the back of the list
121 template< class NODETYPE >
122 bool List< NODETYPE >::removeFromBack( NODETYPE &value )
123 {
124 if ( isEmpty() )
125 return false; // delete unsuccessful
126 else {
127 ListNode< NODETYPE > *tempPtr = lastPtr;
128
129 if ( firstPtr == lastPtr )
130 firstPtr = lastPtr = 0;
131 else {
132 ListNode< NODETYPE > *currentPtr = firstPtr;
133
134 while ( currentPtr -> nextPtr != lastPtr )
135 currentPtr = currentPtr -> nextPtr;
136
137 lastPtr = currentPtr;
138 currentPtr -> nextPtr = 0;
139 }
140
141 value = tempPtr -> data;
142 delete tempPtr;
143 return true; // delete successful
144 }
145 }
Chapter 15 Data Structures Solutions 403
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
146
147 // Is the List empty?
148 template< class NODETYPE >
149 bool List< NODETYPE >::isEmpty() const { return firstPtr == 0; }
150
151 // Return a pointer to a newly allocated node
152 template< class NODETYPE >
153 ListNode< NODETYPE > *List< NODETYPE >::getNewNode( const NODETYPE &value )
154 {
155 ListNode< NODETYPE > *ptr = new ListNode< NODETYPE >( value );
156 assert( ptr != 0 );
157 return ptr;
158 }
159
160 // Display the contents of the List
161 template< class NODETYPE >
162 void List< NODETYPE >::print() const
163 {
164 if ( isEmpty() ) {
165 cout << "The list is empty\n\n";
166 return;
167 }
168
169 ListNode< NODETYPE > *currentPtr = firstPtr;
170
171 cout << "The list is: ";
172
173 while ( currentPtr != 0 ) {
174 cout << currentPtr -> data << ' ';
175 currentPtr = currentPtr -> nextPtr;
176 }
177
178 cout << "\n\n";
179 }
180
181 #endif
182 // LIST2
183 // Template List2 class definition
184 // Enhances List by adding insertInOrder
185 #ifndef LIST2_H
186 #define LIST2_H
187
188 #include <cassert>
189 #include "Listnd.h"
190 #include "List.h"
191
192 template< class NODETYPE >
193 class List2 : public List< NODETYPE > {
194 public:
195 void insertInOrder( const NODETYPE & );
196 };
197
198 // Insert a node in order
199 template< class NODETYPE >
200 void List2< NODETYPE >::insertInOrder( const NODETYPE &value )
201 {
202 if ( isEmpty() ) { // List is empty
203 ListNode< NODETYPE > *newPtr = getNewNode( value );
204 firstPtr = lastPtr = newPtr;
205 }
404 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
206 else { // List is not empty
207 if ( firstPtr -> getData() > value )
208 insertAtFront( value );
209 else if ( lastPtr -> getData() < value )
210 insertAtBack( value );
211 else {
212 ListNode< NODETYPE > *currentPtr = firstPtr -> getNextPtr(),
213 *previousPtr = firstPtr,
214 *newPtr = getNewNode( value );
215
216 while ( currentPtr != lastPtr && currentPtr -> getData() < value ) {
217 previousPtr = currentPtr;
218 currentPtr = currentPtr -> getNextPtr();
219 }
220
221 previousPtr -> setNextPtr( newPtr );
222 newPtr -> setNextPtr( currentPtr );
223 }
224 }
225 }
226
227 #endif
228 // LISTND.H
229 // ListNode template definition
230 #ifndef LISTND_H
231 #define LISTND_H
232
233 template< class T > class List; // forward declaration
234
235 template< class NODETYPE >
236 class ListNode {
237 friend class List< NODETYPE >; // make List a friend
238 public:
239 ListNode( const NODETYPE & ); // constructor
240 NODETYPE getData() const; // return the data in the node
241 void setNextPtr( ListNode *nPtr ) { nextPtr = nPtr; }
242 ListNode *getNextPtr() const { return nextPtr; }
243 private:
244 NODETYPE data; // data
245 ListNode *nextPtr; // next node in the list
246 };
247
248 // Constructor
249 template< class NODETYPE >
250 ListNode< NODETYPE >::ListNode( const NODETYPE &info )
251 {
252 data = info;
253 nextPtr = 0;
254 }
255
256 // Return a copy of the data in the node
257 template< class NODETYPE >
258 NODETYPE ListNode< NODETYPE >::getData() const { return data; }
259
260 #endif
261 // Exercise 15.8 solution
262 #include <iostream>
Chapter 15 Data Structures Solutions 405
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
263
264 using std::cout;
265
266 #include <cstdlib>
267 #include <ctime>
268 #include "List2.h"
269
270 // Integer specific list sum
271 int sumList( List2< int > &listRef )
272 {
273 List2< int > temp( listRef );
274 int sum = 0, value;
275
276 while ( !temp.isEmpty() ) {
277 temp.removeFromFront( value );
278 sum += value;
279 }
280
281 return sum;
282 }
283
284 // Integer specific list average
285 double aveList( List2< int > &listRef )
286 {
287 List2< int > temp( listRef );
288 int sum = 0, value, count = 0;
289
290 while ( !temp.isEmpty() ) {
291 temp.removeFromFront( value );
292 ++count;
293 sum += value;
294 }
295
296 return static_cast< double >( sum ) / count;
297 }
298
299 int main()
300 {
301 srand( time( 0 ) ); // randomize the random number generator
302
303 List2< int > intList;
304
305 for ( int i = 1; i <= 25; ++i )
306 intList.insertInOrder( rand() % 101 );
307
308 intList.print();
309
310 cout << "The sum of the elements is: " << sumList( intList ) << '\n';
311 cout << "The average of the elements is: " << aveList( intList ) << '\n';
312
313 return 0;
314 }
406 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.9 Write a program that creates a linked list object of 10 characters and then creates a second list object containing a copy of
the first list, but in reverse order.
The list is: 6 11 14 22 23 25 31 34 41 42 43 43 46 47 48 51 54 61 66 72 72 82 89
94 95
All nodes destroyed
The sum of the elements is: 1212
All nodes destroyed
The average of the elements is: 48.48
Destroying nodes ...
6 11 14 22 23 25 31 34 41 42 43 43 46 47 48 51 54 61 66 72 72 82 89 94 95
All nodes destroyed
1// LIST.H
2// Template List class definition
3// Added copy constructor to member functions (not included in chapter).
4#ifndef LIST_H
5#define LIST_H
6
7#include <iostream>
8
9using std::cout;
10
11 #include <cassert>
12 #include "listnd.h"
13
14 template< class NODETYPE >
15 class List {
16 public:
17 List(); // default constructor
18 List( const List< NODETYPE > & ); // copy constructor
19 ~List(); // destructor
20 void insertAtFront( const NODETYPE & );
21 void insertAtBack( const NODETYPE & );
22 bool removeFromFront( NODETYPE & );
23 bool removeFromBack( NODETYPE & );
24 bool isEmpty() const;
25 void print() const;
26 protected:
27 ListNode< NODETYPE > *firstPtr; // pointer to first node
28 ListNode< NODETYPE > *lastPtr; // pointer to last node
29
30 // Utility function to allocate a new node
31 ListNode< NODETYPE > *getNewNode( const NODETYPE & );
32 };
33
34 // Default constructor
35 template< class NODETYPE >
36 List< NODETYPE >::List() { firstPtr = lastPtr = 0; }
37
38 // Copy constructor
39 template< class NODETYPE >
40 List< NODETYPE >::List( const List<NODETYPE> &copy )
41 {
42 firstPtr = lastPtr = 0; // initialize pointers
Chapter 15 Data Structures Solutions 407
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
43
44 ListNode< NODETYPE > *currentPtr = copy.firstPtr;
45
46 while ( currentPtr != 0 ) {
47 insertAtBack( currentPtr -> data );
48 currentPtr = currentPtr -> nextPtr;
49 }
50 }
51
52 // Destructor
53 template< class NODETYPE >
54 List< NODETYPE >::~List()
55 {
56 if ( !isEmpty() ) { // List is not empty
57 cout << "Destroying nodes ...\n";
58
59 ListNode< NODETYPE > *currentPtr = firstPtr, *tempPtr;
60
61 while ( currentPtr != 0 ) { // delete remaining nodes
62 tempPtr = currentPtr;
63 cout << tempPtr -> data << ' ';
64 currentPtr = currentPtr -> nextPtr;
65 delete tempPtr;
66 }
67 }
68
69 cout << "\nAll nodes destroyed\n\n";
70 }
71
72 // Insert a node at the front of the list
73 template< class NODETYPE >
74 void List< NODETYPE >::insertAtFront( const NODETYPE &value )
75 {
76 ListNode<NODETYPE> *newPtr = getNewNode( value );
77
78 if ( isEmpty() ) // List is empty
79 firstPtr = lastPtr = newPtr;
80 else { // List is not empty
81 newPtr -> nextPtr = firstPtr;
82 firstPtr = newPtr;
83 }
84 }
85
86 // Insert a node at the back of the list
87 template< class NODETYPE >
88 void List< NODETYPE >::insertAtBack( const NODETYPE &value )
89 {
90 ListNode< NODETYPE > *newPtr = getNewNode( value );
91
92 if ( isEmpty() ) // List is empty
93 firstPtr = lastPtr = newPtr;
94 else { // List is not empty
95 lastPtr -> nextPtr = newPtr;
96 lastPtr = newPtr;
97 }
98 }
99
100 // Delete a node from the front of the list
101 template< class NODETYPE >
102 bool List< NODETYPE >::removeFromFront( NODETYPE &value )
103 {
104 if ( isEmpty() ) // List is empty
105 return false; // delete unsuccessful
408 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
106 else {
107 ListNode< NODETYPE > *tempPtr = firstPtr;
108
109 if ( firstPtr == lastPtr )
110 firstPtr = lastPtr = 0;
111 else
112 firstPtr = firstPtr -> nextPtr;
113
114 value = tempPtr -> data; // data being removed
115 delete tempPtr;
116 return true; // delete successful
117 }
118 }
119
120 // Delete a node from the back of the list
121 template< class NODETYPE >
122 bool List< NODETYPE >::removeFromBack( NODETYPE &value )
123 {
124 if ( isEmpty() )
125 return false; // delete unsuccessful
126 else {
127 ListNode< NODETYPE > *tempPtr = lastPtr;
128
129 if ( firstPtr == lastPtr )
130 firstPtr = lastPtr = 0;
131 else {
132 ListNode< NODETYPE > *currentPtr = firstPtr;
133
134 while ( currentPtr -> nextPtr != lastPtr )
135 currentPtr = currentPtr -> nextPtr;
136
137 lastPtr = currentPtr;
138 currentPtr -> nextPtr = 0;
139 }
140
141 value = tempPtr -> data;
142 delete tempPtr;
143 return true; // delete successful
144 }
145 }
146
147 // Is the List empty?
148 template< class NODETYPE >
149 bool List< NODETYPE >::isEmpty() const { return firstPtr == 0; }
150
151 // Return a pointer to a newly allocated node
152 template< class NODETYPE >
153 ListNode< NODETYPE > *List< NODETYPE >::getNewNode( const NODETYPE &value )
154 {
155 ListNode< NODETYPE > *ptr = new ListNode< NODETYPE >( value );
156 assert( ptr != 0 );
157 return ptr;
158 }
159
160 // Display the contents of the List
161 template< class NODETYPE >
162 void List< NODETYPE >::print() const
163 {
164 if ( isEmpty() ) {
165 cout << "The list is empty\n\n";
166 return;
167 }
Chapter 15 Data Structures Solutions 409
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
168
169 ListNode< NODETYPE > *currentPtr = firstPtr;
170
171 cout << "The list is: ";
172
173 while ( currentPtr != 0 ) {
174 cout << currentPtr -> data << ' ';
175 currentPtr = currentPtr -> nextPtr;
176 }
177
178 cout << "\n\n";
179 }
180
181 #endif
182 // LISTND.H
183 // ListNode template definition
184 #ifndef LISTND_H
185 #define LISTND_H
186
187 template< class T > class List; // forward declaration
188
189 template< class NODETYPE >
190 class ListNode {
191 friend class List< NODETYPE >; // make List a friend
192 public:
193 ListNode( const NODETYPE & ); // constructor
194 NODETYPE getData() const; // return the data in the node
195 void setNextPtr( ListNode *nPtr ) { nextPtr = nPtr; }
196 ListNode *getNextPtr() const { return nextPtr; }
197 private:
198 NODETYPE data; // data
199 ListNode *nextPtr; // next node in the list
200 };
201
202 // Constructor
203 template< class NODETYPE >
204 ListNode< NODETYPE >::ListNode( const NODETYPE &info )
205 {
206 data = info;
207 nextPtr = 0;
208 }
209
210 // Return a copy of the data in the node
211 template< class NODETYPE >
212 NODETYPE ListNode< NODETYPE >::getData() const { return data; }
213
214 #endif
215 // Exercise 15.9 solution
216 #include <iostream>
217
218 using std::cout;
219
220 #include "list.h"
221
222 // Function template that takes two List objects as arguments
223 // and makes a copy of the second argument reversed in the first argument.
224 template< class T >
225 void reverseList( List< T > &first, List< T > &second )
410 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.10 Write a program that inputs a line of text and uses a stack object to print the line reversed.
226 {
227 List< T > temp( second ); // create a copy of second
228 T value; // variable to store removed item from temp
229
230 while ( !temp.isEmpty() ) {
231 temp.removeFromFront( value ); // remove value from temp list
232 first.insertAtFront( value ); // insert at beginning of first list
233 }
234 }
235
236 int main()
237 {
238 List< char > list1, list2;
239
240 for ( char c = 'a'; c <= 'g'; ++c )
241 list1.insertAtBack( c );
242
243 list1.print();
244
245 reverseList( list2, list1 );
246 cout << "After reversing:\n";
247 list2.print();
248
249 return 0;
250 }
The list is: a b c d e f g
All nodes destroyed
After reversing:
The list is: g f e d c b a
Destroying nodes ...
g f e d c b a
All nodes destroyed
Destroying nodes ...
a b c d e f g
All nodes destroyed
1// STACK.H
2// Definition of class Stack
3// NOTE: This Stack class is a standalone Stack class template.
4#ifndef STACK_H
5#define STACK_H
6
7#include <iostream>
8
9using std::cout;
10
11 #include <cassert>
12 #include "stacknd.h"
13
14 template < class T >
15 class Stack {
Chapter 15 Data Structures Solutions 411
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16 public:
17 Stack(); // default constructor
18 ~Stack(); // destructor
19 void push( T & ); // insert item in stack
20 T pop(); // remove item from stack
21 bool isEmpty() const; // is the stack empty?
22 void print() const; // output the stack
23 StackNode< T > *getTopPtr() const { return topPtr; }
24 private:
25 StackNode< T > *topPtr; // pointer to fist StackNode
26 };
27
28 // Member function definitions for class Stack
29 template < class T >
30 Stack< T >::Stack() { topPtr = 0; }
31
32 template < class T >
33 Stack< T >::~Stack()
34 {
35 StackNode< T > *tempPtr, *currentPtr = topPtr;
36
37 while ( currentPtr != 0 ) {
38 tempPtr = currentPtr;
39 currentPtr = currentPtr -> getNextPtr();
40 delete tempPtr;
41 }
42 }
43
44 template < class T >
45 void Stack< T >::push( T &d )
46 {
47 StackNode< T > *newPtr = new StackNode< T >( d, topPtr );
48
49 assert( newPtr != 0 ); // was memory allocated?
50 topPtr = newPtr;
51 }
52
53 template < class T >
54 T Stack< T >::pop()
55 {
56 assert( !isEmpty() );
57
58 StackNode< T > *tempPtr = topPtr;
59
60 topPtr = topPtr -> nextPtr;
61 T poppedValue = tempPtr -> data;
62 delete tempPtr;
63 return poppedValue;
64 }
65
66 template < class T >
67 bool Stack< T >::isEmpty() const { return topPtr == 0; }
68
69 template < class T >
70 void Stack< T >::print() const
71 {
72 StackNode< T > *currentPtr = topPtr;
73
74 if ( isEmpty() ) // Stack is empty
75 cout << "Stack is empty\n";
76 else { // Stack is not empty
77 cout << "The stack is:\n";
412 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
78
79 while ( currentPtr != 0 ) {
80 cout << currentPtr -> data << ' ';
81 currentPtr = currentPtr -> nextPtr;
82 }
83
84 cout << '\n';
85 }
86 }
87
88 #endif
89 // STACKND.H
90 // Definition of template class StackNode
91 #ifndef STACKND_H
92 #define STACKND_H
93
94 template< class T > class Stack; // forward declaration
95
96 template < class T >
97 class StackNode {
98 friend class Stack< T >;
99 public:
100 StackNode( const T & = 0, StackNode * = 0 );
101 T getData() const;
102 void setNextPtr( StackNode *nPtr ) { nextPtr = nPtr; }
103 StackNode *getNextPtr() const { return nextPtr; }
104 private:
105 T data;
106 StackNode *nextPtr;
107 };
108
109 // Member function definitions for class StackNode
110 template < class T >
111 StackNode< T >::StackNode( const T &d, StackNode< T > *ptr )
112 {
113 data = d;
114 nextPtr = ptr;
115 }
116
117 template < class T >
118 T StackNode< T >::getData() const { return data; }
119
120 #endif
121 // Exercise 15.10 solution
122 #include <iostream>
123
124 using std::cout;
125 using std::cin;
126
127 #include "stack.h"
128
129 int main()
130 {
131 Stack< char > charStack;
132 char c;
133
134 cout << "Enter a sentence:\n";
Chapter 15 Data Structures Solutions 413
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.11 Write a program that uses a stack object to determine if a string is a palindrome (i.e., the string is spelled identically backwards
and forwards). The program should ignore spaces and punctuation.
135
136 while ( ( c = static_cast< char >( cin.get() ) ) != '\n' )
137 charStack.push( c );
138
139 cout << "\nThe sentence in reverse is:\n";
140
141 while ( !charStack.isEmpty() )
142 cout << charStack.pop();
143
144 cout << '\n';
145
146 return 0;
147 }
Enter a sentence:
Hello World!
The sentence in reverse is:
!dlroW olleH
1// STACK.H
2// Definition of class Stack
3// NOTE: This Stack class is a standalone Stack class template.
4#ifndef STACK_H
5#define STACK_H
6
7#include <iostream>
8
9using std::cout;
10
11 #include <cassert>
12 #include "stacknd.h"
13
14 template < class T >
15 class Stack {
16 public:
17 Stack(); // default constructor
18 ~Stack(); // destructor
19 void push( T & ); // insert item in stack
20 T pop(); // remove item from stack
21 bool isEmpty() const; // is the stack empty?
22 void print() const; // output the stack
23 StackNode< T > *getTopPtr() const { return topPtr; }
24 private:
25 StackNode< T > *topPtr; // pointer to fist StackNode
26 };
27
28 // Member function definitions for class Stack
29 template < class T >
30 Stack< T >::Stack() { topPtr = 0; }
31
32 template < class T >
33 Stack< T >::~Stack()
34 {
35 StackNode< T > *tempPtr, *currentPtr = topPtr;
36
414 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
37 while ( currentPtr != 0 ) {
38 tempPtr = currentPtr;
39 currentPtr = currentPtr -> getNextPtr();
40 delete tempPtr;
41 }
42 }
43
44 template < class T >
45 void Stack< T >::push( T &d )
46 {
47 StackNode< T > *newPtr = new StackNode< T >( d, topPtr );
48
49 assert( newPtr != 0 ); // was memory allocated?
50 topPtr = newPtr;
51 }
52
53 template < class T >
54 T Stack< T >::pop()
55 {
56 assert( !isEmpty() );
57
58 StackNode< T > *tempPtr = topPtr;
59
60 topPtr = topPtr -> nextPtr;
61 T poppedValue = tempPtr -> data;
62 delete tempPtr;
63 return poppedValue;
64 }
65
66 template < class T >
67 bool Stack< T >::isEmpty() const { return topPtr == 0; }
68
69 template < class T >
70 void Stack< T >::print() const
71 {
72 StackNode< T > *currentPtr = topPtr;
73
74 if ( isEmpty() ) // Stack is empty
75 cout << "Stack is empty\n";
76 else { // Stack is not empty
77 cout << "The stack is:\n";
78
79 while ( currentPtr != 0 ) {
80 cout << currentPtr -> data << ' ';
81 currentPtr = currentPtr -> nextPtr;
82 }
83
84 cout << '\n';
85 }
86 }
87
88 #endif
89 // STACKND.H
90 // Definition of template class StackNode
91 #ifndef STACKND_H
92 #define STACKND_H
93
94 template< class T > class Stack; // forward declaration
95
96 template < class T >
Chapter 15 Data Structures Solutions 415
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
97 class StackNode {
98 friend class Stack< T >;
99 public:
100 StackNode( const T & = 0, StackNode * = 0 );
101 T getData() const;
102 void setNextPtr( StackNode *nPtr ) { nextPtr = nPtr; }
103 StackNode *getNextPtr() const { return nextPtr; }
104 private:
105 T data;
106 StackNode *nextPtr;
107 };
108
109 // Member function definitions for class StackNode
110 template < class T >
111 StackNode< T >::StackNode( const T &d, StackNode< T > *ptr )
112 {
113 data = d;
114 nextPtr = ptr;
115 }
116
117 template < class T >
118 T StackNode< T >::getData() const { return data; }
119
120 #endif
121 // Exercise 15.11 solution
122 #include <iostream>
123
124 using std::cout;
125 using std::cin;
126
127 #include <cctype>
128
129 #include <cstring>
130 #include "stack.h"
131
132 int main()
133 {
134 Stack< char > charStack;
135 char c, string1[ 80 ], string2[ 80 ];
136 int i = 0;
137
138 cout << "Enter a sentence:\n";
139
140 while ( ( c = static_cast< char >( cin.get() ) ) != '\n' )
141 if ( isalpha( c ) ) {
142 string1[ i++ ] = c;
143 charStack.push( c );
144 }
145
146 string1[ i ] = '\0';
147
148 i = 0;
149
150 while ( !charStack.isEmpty() )
151 string2[ i++ ] = charStack.pop();
152
153 string2[ i ] = '\0';
154
155 if ( strcmp( string1, string2 ) == 0 )
156 cout << "\nThe sentence is a palindrome\n";
416 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.12 Stacks are used by compilers to help in the process of evaluating expressions and generating machine language code. In
this and the next exercise, we investigate how compilers evaluate arithmetic expressions consisting only of constants, operators and
parentheses.
Humans generally write expressions like 3 + 4 and 7 / 9 in which the operator (+ or / here) is written between its oper-
ands—this is called infix notation. Computers “prefer” postfix notation in which the operator is written to the right of its two oper-
ands. The preceding infix expressions would appear in postfix notation as 3 4 + and 7 9 /, respectively.
To evaluate a complex infix expression, a compiler would first convert the expression to postfix notation and then evaluate the
postfix version of the expression. Each of these algorithms requires only a single left-to-right pass of the expression. Each algo-
rithm uses a stack object in support of its operation, and in each algorithm the stack is used for a different purpose.
In this exercise, you will write a C++ version of the infix-to-postfix conversion algorithm. In the next exercise, you will write
a C++ version of the postfix expression evaluation algorithm. Later in the chapter, you will discover that code you write in this
exercise can help you implement a complete working compiler.
Write a program that converts an ordinary infix arithmetic expression (assume a valid expression is entered) with single-digit
integers such as
(6 + 2) * 5 - 8 / 4
to a postfix expression. The postfix version of the preceding infix expression is
6 2 + 5 * 8 4 / -
The program should read the expression into character array infix, and use modified versions of the stack functions imple-
mented in this chapter to help create the postfix expression in character array postfix. The algorithm for creating a postfix
expression is as follows:
1) Push a left parenthesis '(' onto the stack.
2) Append a right parenthesis ')' to the end of infix.
3) While the stack is not empty, read infix from left to right and do the following:
If the current character in infix is a digit, copy it to the next element of postfix.
If the current character in infix is a left parenthesis, push it onto the stack.
If the current character in infix is an operator,
Pop operators (if there are any) at the top of the stack while they have equal or
higher precedence than the current operator, and insert the popped
operators in postfix.
Push the current character in infix onto the stack.
If the current character in infix is a right parenthesis
Pop operators from the top of the stack and insert them in postfix until a left
parenthesis is at the top of the stack.
Pop (and discard) the left parenthesis from the stack.
The following arithmetic operations are allowed in an expression:
+addition
-subtraction
*multiplication
/division
^exponentiation
157 else
158 cout << "\nThe sentence is not a palindrome\n";
159
160 return 0;
161 }
Enter a sentence:
oat y tao
The sentence is a palindrome
Chapter 15 Data Structures Solutions 417
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
%modulus
The stack should be maintained with stack nodes that each contain a data member and a pointer to the next stack node.
Some of the functional capabilities you may want to provide are:
a) Function convertToPostfix that converts the infix expression to postfix notation.
b) Function isOperator that determines if c is an operator.
c) Function precedence that determines if the precedence of operator1 is less than, equal to or greater than the pre-
cedence of operator2. The function returns -1, 0 and 1, respectively.
d) Function push that pushes a value onto the stack.
e) Function pop that pops a value off the stack.
f) Function stackTop that returns the top value of the stack without popping the stack.
g) Function isEmpty that determines if the stack is empty.
h) Function printStack that prints the stack.
1// STACK.H
2// Definition of class Stack
3// NOTE: This Stack class is a standalone Stack class template.
4#ifndef STACK_H
5#define STACK_H
6
7#include <iostream>
8
9using std::cout;
10
11 #include <cassert>
12 #include "stacknd.h"
13
14 template < class T >
15 class Stack {
16 public:
17 Stack(); // default constructor
18 ~Stack(); // destructor
19 void push( T & ); // insert item in stack
20 T pop(); // remove item from stack
21 bool isEmpty() const; // is the stack empty?
22 void print() const; // output the stack
23 StackNode< T > *getTopPtr() const { return topPtr; }
24 private:
25 StackNode< T > *topPtr; // pointer to fist StackNode
26 };
27
28 // Member function definitions for class Stack
29 template < class T >
30 Stack< T >::Stack() { topPtr = 0; }
31
32 template < class T >
33 Stack< T >::~Stack()
34 {
35 StackNode< T > *tempPtr, *currentPtr = topPtr;
36
37 while ( currentPtr != 0 ) {
38 tempPtr = currentPtr;
39 currentPtr = currentPtr -> getNextPtr();
40 delete tempPtr;
41 }
42 }
43
44 template < class T >
45 void Stack< T >::push( T &d )
46 {
47 StackNode< T > *newPtr = new StackNode< T >( d, topPtr );
418 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
48
49 assert( newPtr != 0 ); // was memory allocated?
50 topPtr = newPtr;
51 }
52
53 template < class T >
54 T Stack< T >::pop()
55 {
56 assert( !isEmpty() );
57
58 StackNode< T > *tempPtr = topPtr;
59
60 topPtr = topPtr -> nextPtr;
61 T poppedValue = tempPtr -> data;
62 delete tempPtr;
63 return poppedValue;
64 }
65
66 template < class T >
67 bool Stack< T >::isEmpty() const { return topPtr == 0; }
68
69 template < class T >
70 void Stack< T >::print() const
71 {
72 StackNode< T > *currentPtr = topPtr;
73
74 if ( isEmpty() ) // Stack is empty
75 cout << "Stack is empty\n";
76 else { // Stack is not empty
77 cout << "The stack is:\n";
78
79 while ( currentPtr != 0 ) {
80 cout << currentPtr -> data << ' ';
81 currentPtr = currentPtr -> nextPtr;
82 }
83
84 cout << '\n';
85 }
86 }
87
88 #endif
89 // STACKND.H
90 // Definition of template class StackNode
91 #ifndef STACKND_H
92 #define STACKND_H
93
94 template< class T > class Stack; // forward declaration
95
96 template < class T >
97 class StackNode {
98 friend class Stack< T >;
99 public:
100 StackNode( const T & = 0, StackNode * = 0 );
101 T getData() const;
102 void setNextPtr( StackNode *nPtr ) { nextPtr = nPtr; }
103 StackNode *getNextPtr() const { return nextPtr; }
104 private:
105 T data;
106 StackNode *nextPtr;
107 };
Chapter 15 Data Structures Solutions 419
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
108
109 // Member function definitions for class StackNode
110 template < class T >
111 StackNode< T >::StackNode( const T &d, StackNode< T > *ptr )
112 {
113 data = d;
114 nextPtr = ptr;
115 }
116
117 template < class T >
118 T StackNode< T >::getData() const { return data; }
119
120 #endif
121 // STACK2
122 // Definition of class Stack2
123 #ifndef STACK2_H
124 #define STACK2_H
125
126 #include <iostream>
127
128 using std::cout;
129
130 #include <cassert>
131 #include "stacknd.h"
132 #include "stack.h"
133
134 template < class T >
135 class Stack2 : public Stack< T > {
136 public:
137 T stackTop() const; // check the top value
138 };
139
140 template < class T >
141 T Stack2< T >::stackTop() const
142 { return !isEmpty() ? getTopPtr() -> getData() : static_cast< T >( 0 ); }
143
144 #endif
145 // Exercise 15.12 Solution
146 // Infix to postfix conversion
147 #include <iostream>
148
149 using std::cout;
150 using std::endl;
151 using std::cin;
152
153 #include <cctype>
154 #include <cstring>
155 #include "stack2.h"
156
157 void convertToPostfix( char * const, char * const );
158 bool isOperator( char );
159 bool precedence( char, char );
160
161 int main()
162 {
163 const int MAXSIZE = 100;
164 char c, inFix[ MAXSIZE ], postFix[ MAXSIZE ];
420 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
165 int pos = 0;
166
167 cout << "Enter the infix expression.\n";
168
169 while ( ( c = static_cast< char >( cin.get() ) ) != '\n' )
170 if ( c != ' ' )
171 inFix[ pos++ ] = c;
172
173 inFix[ pos ] = '\0';
174
175 cout << "The original infix expression is:\n" << inFix << '\n';
176 convertToPostfix( inFix, postFix );
177 cout << "The expression in postfix notation is:\n" << postFix << endl;
178
179 return 0;
180 }
181
182 void convertToPostfix( char * const infix, char * const postfix )
183 {
184 Stack2< char > charStack;
185 int infixCount, postfixCount;
186 bool higher;
187 char popValue, leftParen = '(';
188
189 // push a left paren onto the stack and add a right paren to infix
190 charStack.push( leftParen );
191 charStack.print();
192 strcat( infix, ")" );
193
194 // convert the infix expression to postfix
195 for ( infixCount = 0, postfixCount = 0; charStack.stackTop();
196 ++infixCount ) {
197
198 if ( isdigit( infix[ infixCount ] ) )
199 postfix[ postfixCount++ ] = infix[ infixCount ];
200 else if ( infix[ infixCount ] == '(' ) {
201 charStack.push( leftParen );
202 charStack.print();
203 }
204 else if ( isOperator( infix[ infixCount ] ) ) {
205 higher = true; // used to store value of precedence test
206
207 while ( higher ) {
208 if ( isOperator( charStack.stackTop() ) )
209 if ( precedence( charStack.stackTop(), infix[ infixCount ] ) ) {
210 postfix[ postfixCount++ ] = charStack.pop();
211 charStack.print();
212 }
213 else
214 higher = false;
215 else
216 higher = false;
217 }
218
219 charStack.push( infix[ infixCount ] );
220 charStack.print();
221 }
222 else if ( infix[ infixCount ] == ')' ) {
223 while ( ( popValue = charStack.pop() ) != '(' ) {
224 charStack.print();
225 postfix[ postfixCount++ ] = popValue;
226 }
Chapter 15 Data Structures Solutions 421
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
227
228 charStack.print();
229 }
230 }
231
232 postfix[ postfixCount ] = '\0';
233 }
234
235 // check if c is an operator
236 bool isOperator( char c )
237 {
238 if ( c == '+' || c == '-' || c == '*' || c == '/' || c == '^' )
239 return true;
240 else
241 return false;
242 }
243
244 bool precedence( char operator1, char operator2 )
245 {
246 if ( operator1 == '^' )
247 return true;
248 else if ( operator2 == '^' )
249 return false;
250 else if ( operator1 == '*' || operator1 == '/' )
251 return true;
252 else if ( operator1 == '+' || operator1 == '-' )
253 if ( operator2 == '*' || operator2 == '/' )
254 return false;
255 else
256 return true;
257
258 return false;
259 }
422 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.13 Write a program that evaluates a postfix expression (assume it is valid) such as
6 2 + 5 * 8 4 / -
The program should read a postfix expression consisting of digits and operators into a character array. Using modified versions of
the stack functions implemented earlier in this chapter, the program should scan the expression and evaluate it. The algorithm is as
follows:
1) Append the null character ('\0') to the end of the postfix expression. When the null character is encountered, no fur-
ther processing is necessary.
2) While '\0' has not been encountered, read the expression from left to right.
If the current character is a digit,
Push its integer value onto the stack (the integer value of a digit character is its
value in the computer’s character set minus the value of '0' in the
computer’s character set).
Otherwise, if the current character is an operator,
Pop the two top elements of the stack into variables x and y.
Calculate y operator x.
Push the result of the calculation onto the stack.
3) When the null character is encountered in the expression, pop the top value of the stack. This is the result of the postfix
expression.
Note: In step 2) above, if the operator is '/', the top of the stack is 2 and the next element in the stack is 8, then pop 2 into x, pop
8 into y, evaluate 8 / 2 and push the result, 4, back onto the stack. This note also applies to operator '-'. The arithmetic opera-
tions allowed in an expression are:
+addition
-subtraction
*multiplication
/division
^exponentiation
Enter the infix expression.
(6 + 2) * 5 - 8 / 4
The original infix expression is:
(6+2)*5-8/4
The stack is:
(
The stack is:
( (
The stack is:
+ ( (
The stack is:
( (
The stack is:
(
The stack is:
* (
The stack is:
(
The stack is:
- (
The stack is:
/ - (
The stack is:
- (
The stack is:
(
Stack is empty
The expression in postfix notation is:
62+5*84/-
Chapter 15 Data Structures Solutions 423
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
%modulus
The stack should be maintained with stack nodes that contain an int data member and a pointer to the next stack node. You may
want to provide the following functional capabilities:
a) Function evaluatePostfixExpression that evaluates the postfix expression.
b) Function calculate that evaluates the expression op1 operator op2.
c) Function push that pushes a value onto the stack.
d) Function pop that pops a value off the stack.
e) Function isEmpty that determines if the stack is empty.
f) Function printStack that prints the stack.
1// STACK.H
2// Definition of class Stack
3// NOTE: This Stack class is a standalone Stack class template.
4#ifndef STACK_H
5#define STACK_H
6
7#include <iostream>
8
9using std::cout;
10
11 #include <cassert>
12 #include "stacknd.h"
13
14 template < class T >
15 class Stack {
16 public:
17 Stack(); // default constructor
18 ~Stack(); // destructor
19 void push( T & ); // insert item in stack
20 T pop(); // remove item from stack
21 bool isEmpty() const; // is the stack empty?
22 void print() const; // output the stack
23 StackNode< T > *getTopPtr() const { return topPtr; }
24 private:
25 StackNode< T > *topPtr; // pointer to fist StackNode
26 };
27
28 // Member function definitions for class Stack
29 template < class T >
30 Stack< T >::Stack() { topPtr = 0; }
31
32 template < class T >
33 Stack< T >::~Stack()
34 {
35 StackNode< T > *tempPtr, *currentPtr = topPtr;
36
37 while ( currentPtr != 0 ) {
38 tempPtr = currentPtr;
39 currentPtr = currentPtr -> getNextPtr();
40 delete tempPtr;
41 }
42 }
43
44 template < class T >
45 void Stack< T >::push( T &d )
46 {
47 StackNode< T > *newPtr = new StackNode< T >( d, topPtr );
48
49 assert( newPtr != 0 ); // was memory allocated?
50 topPtr = newPtr;
51 }
424 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
52
53 template < class T >
54 T Stack< T >::pop()
55 {
56 assert( !isEmpty() );
57
58 StackNode< T > *tempPtr = topPtr;
59
60 topPtr = topPtr -> nextPtr;
61 T poppedValue = tempPtr -> data;
62 delete tempPtr;
63 return poppedValue;
64 }
65
66 template < class T >
67 bool Stack< T >::isEmpty() const { return topPtr == 0; }
68
69 template < class T >
70 void Stack< T >::print() const
71 {
72 StackNode< T > *currentPtr = topPtr;
73
74 if ( isEmpty() ) // Stack is empty
75 cout << "Stack is empty\n";
76 else { // Stack is not empty
77 cout << "The stack is:\n";
78
79 while ( currentPtr != 0 ) {
80 cout << currentPtr -> data << ' ';
81 currentPtr = currentPtr -> nextPtr;
82 }
83
84 cout << '\n';
85 }
86 }
87
88 #endif
89 // STACKND.H
90 // Definition of template class StackNode
91 #ifndef STACKND_H
92 #define STACKND_H
93
94 template< class T > class Stack; // forward declaration
95
96 template < class T >
97 class StackNode {
98 friend class Stack< T >;
99 public:
100 StackNode( const T & = 0, StackNode * = 0 );
101 T getData() const;
102 void setNextPtr( StackNode *nPtr ) { nextPtr = nPtr; }
103 StackNode *getNextPtr() const { return nextPtr; }
104 private:
105 T data;
106 StackNode *nextPtr;
107 };
108
109 // Member function definitions for class StackNode
110 template < class T >
111 StackNode< T >::StackNode( const T &d, StackNode< T > *ptr )
Chapter 15 Data Structures Solutions 425
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
112 {
113 data = d;
114 nextPtr = ptr;
115 }
116
117 template < class T >
118 T StackNode< T >::getData() const { return data; }
119
120 #endif
121 // Exercise 15.13 Solution
122 // Using a stack to evaluate an expression in postfix notation
123 #include <iostream>
124
125 using std::cout;
126 using std::endl;
127 using std::cin;
128
129 #include <cstring>
130 using std::string;
131
132 #include <cctype>
133 #include <cmath>
134 #include "stack.h"
135
136 int evaluatePostfixExpression( char * const );
137 int calculate( int, int, char );
138
139 int main()
140 {
141 char expression[ 100 ], c;
142 int answer, i = 0;
143
144 cout << "Enter a postfix expression:\n";
145
146 while ( ( c = static_cast< char >( cin.get() ) ) != '\n')
147 if ( c != ' ' )
148 expression[ i++ ] = c;
149
150 expression[ i ] = '\0';
151
152 answer = evaluatePostfixExpression( expression );
153 cout << "The value of the expression is: " << answer << endl;
154
155 return 0;
156 }
157
158 int evaluatePostfixExpression( char * const expr )
159 {
160 int i, popVal1, popVal2, pushVal;
161 Stack< int > intStack;
162 char c;
163
164 strcat( expr, ")" );
165
166 for ( i = 0; ( c = expr[ i ] ) != ')'; ++i )
167 if ( isdigit( expr[ i ] ) ) {
168 pushVal = c - '0';
169 intStack.push( pushVal );
170 intStack.print();
171 }
426 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
172 else {
173 popVal2 = intStack.pop();
174 intStack.print();
175 popVal1 = intStack.pop();
176 intStack.print();
177 pushVal = calculate( popVal1, popVal2, expr[ i ] );
178 intStack.push( pushVal );
179 intStack.print();
180 }
181
182 return intStack.pop();
183 }
184
185 int calculate( int op1, int op2, char oper )
186 {
187 switch( oper ) {
188 case '+':
189 return op1 + op2;
190 case '-':
191 return op1 - op2;
192 case '*':
193 return op1 * op2;
194 case '/':
195 return op1 / op2;
196 case '^': // exponentiation
197 return static_cast< int >( pow( op1, op2 ) );
198 }
199
200 return 0;
201 }
Chapter 15 Data Structures Solutions 427
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.14 Modify the postfix evaluator program of Exercise 15.13 so that it can process integer operands larger than 9.
15.15 (Supermarket simulation) Write a program that simulates a checkout line at a supermarket. The line is a queue object. Cus-
tomers (i.e., customer objects) arrive in random integer intervals of 1 to 4 minutes. Also, each customer is served in random integer
intervals of 1 to 4 minutes. Obviously, the rates need to be balanced. If the average arrival rate is larger than the average service
rate, the queue will grow infinitely. Even with “balanced” rates, randomness can still cause long lines. Run the supermarket simu-
lation for a 12-hour day (720 minutes) using the following algorithm:
1) Choose a random integer between 1 and 4 to determine the minute at which the first customer arrives.
2) At the first customer’s arrival time:
Determine customer’s service time (random integer from 1 to 4);
Begin servicing the customer;
Schedule arrival time of next customer (random integer 1 to 4 added to the current time).
3) For each minute of the day:
If the next customer arrives,
Say so,
Enqueue the customer;
Schedule the arrival time of the next customer;
If service was completed for the last customer;
Say so
Dequeue next customer to be serviced
Determine customer’s service completion time
(random integer from 1 to 4 added to the current time).
Now run your simulation for 720 minutes and answer each of the following:
a) What is the maximum number of customers in the queue at any time?
Enter a postfix expression:
6 2 + 5 * 8 4 / -
The stack is:
6
The stack is:
2 6
The stack is:
6
Stack is empty
The stack is:
8
The stack is:
5 8
The stack is:
8
Stack is empty
The stack is:
40
The stack is:
8 40
The stack is:
4 8 40
The stack is:
8 40
The stack is:
40
The stack is:
2 40
The stack is:
40
Stack is empty
The stack is:
38
The value of the expression is: 38
428 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
b) What is the longest wait any one customer experiences?
c) What happens if the arrival interval is changed from 1-to-4 minutes to 1-to-3 minutes?
15.16 Modify the program of Fig. 15.16 to allow the binary tree object to contain duplicates.
1// TREE
2// Definition of template class Tree
3#ifndef TREE_H
4#define TREE_H
5
6#include <iostream>
7
8using std::cout;
9
10 #include <cassert>
11 #include "treenode.h"
12
13 template< class NODETYPE >
14 class Tree {
15 public:
16 Tree();
17 void insertNode( const NODETYPE & );
18 void preOrderTraversal() const;
19 void inOrderTraversal() const;
20 void postOrderTraversal() const;
21 protected:
22 TreeNode<NODETYPE> *rootPtr;
23
24 // utility functions
25 void insertNodeHelper( TreeNode< NODETYPE > **, const NODETYPE & );
26 void preOrderHelper( TreeNode< NODETYPE > * ) const;
27 void inOrderHelper( TreeNode< NODETYPE > * ) const;
28 void postOrderHelper( TreeNode< NODETYPE > * ) const;
29 };
30
31 template< class NODETYPE >
32 Tree< NODETYPE >::Tree() { rootPtr = 0; }
33
34 template< class NODETYPE >
35 void Tree< NODETYPE >::insertNode( const NODETYPE &value )
36 { insertNodeHelper( &rootPtr, value ); }
37
38 // This function receives a pointer to a pointer so the
39 // pointer can be modified.
40 // NOTE: THIS FUNCTION WAS MODIFIED TO ALLOW DUPLICATES.
41 template< class NODETYPE >
42 void Tree< NODETYPE >::insertNodeHelper( TreeNode< NODETYPE > **ptr,
43 const NODETYPE &value )
44 {
45 if ( *ptr == 0 ) { // tree is empty
46 *ptr = new TreeNode< NODETYPE >( value );
47 assert( *ptr != 0 );
48 }
49 else // tree is not empty
50 if ( value <= ( *ptr ) -> data )
51 insertNodeHelper( &( ( *ptr ) -> leftPtr ), value );
52 else
53 insertNodeHelper( &( ( *ptr ) -> rightPtr ), value );
54 }
55
56 template< class NODETYPE >
57 void Tree< NODETYPE >::preOrderTraversal() const { preOrderHelper( rootPtr ); }
Chapter 15 Data Structures Solutions 429
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
58
59 template< class NODETYPE >
60 void Tree< NODETYPE >::preOrderHelper( TreeNode< NODETYPE > *ptr ) const
61 {
62 if ( ptr != 0 ) {
63 cout << ptr -> data << ' ';
64 preOrderHelper( ptr -> leftPtr );
65 preOrderHelper( ptr -> rightPtr );
66 }
67 }
68
69 template< class NODETYPE >
70 void Tree< NODETYPE >::inOrderTraversal() const { inOrderHelper( rootPtr ); }
71
72 template< class NODETYPE >
73 void Tree< NODETYPE >::inOrderHelper( TreeNode< NODETYPE > *ptr ) const
74 {
75 if ( ptr != 0 ) {
76 inOrderHelper( ptr -> leftPtr );
77 cout << ptr -> data << ' ';
78 inOrderHelper( ptr -> rightPtr );
79 }
80 }
81
82 template< class NODETYPE >
83 void Tree< NODETYPE >::postOrderTraversal() const { postOrderHelper( rootPtr );
}
84
85 template< class NODETYPE >
86 void Tree< NODETYPE >::postOrderHelper( TreeNode< NODETYPE > *ptr ) const
87 {
88 if ( ptr != 0 ) {
89 postOrderHelper( ptr -> leftPtr );
90 postOrderHelper( ptr -> rightPtr );
91 cout << ptr -> data << ' ';
92 }
93 }
94
95 #endif
96 // TREENODE.H
97 // Definition of class TreeNode
98 #ifndef TREENODE_H
99 #define TREENODE_H
100
101 template< class T > class Tree; // forward declaration
102
103 template< class NODETYPE >
104 class TreeNode {
105 friend class Tree< NODETYPE >;
106 public:
107 TreeNode( const NODETYPE & ); // constructor
108 NODETYPE getData() const; // return data
109 TreeNode *getLeftPtr() const { return leftPtr; }
110 TreeNode *getRightPtr() const { return rightPtr; }
111 void setLeftPtr( TreeNode *ptr ) { leftPtr = ptr; }
112 void setRightPtr( TreeNode *ptr ) { rightPtr = ptr; }
113 private:
114 TreeNode *leftPtr; // pointer to left subtree
115 NODETYPE data;
116 TreeNode *rightPtr; // pointer to right subtree
430 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
117 };
118
119 // Constructor
120 template< class NODETYPE >
121 TreeNode< NODETYPE >::TreeNode( const NODETYPE &d )
122 {
123 data = d;
124 leftPtr = rightPtr = 0;
125 }
126
127 //Return a copy of the data value
128 template< class NODETYPE >
129 NODETYPE TreeNode< NODETYPE >::getData() const { return data; }
130
131 #endif
132 // Exercise 15.16 solution
133 // Driver to test class Tree
134 #include <iostream>
135
136 using std::cout;
137 using std::cin;
138 using std::ios;
139
140 #include <iomanip>
141
142 using std::setprecision;
143 using std::setiosflags;
144
145 #include "tree.h"
146
147 int main()
148 {
149 Tree< int > intTree;
150 int intVal, i;
151
152 cout << "Enter 10 integer values:\n";
153 for ( i = 0; i < 10; ++i ) {
154 cin >> intVal;
155 intTree.insertNode( intVal );
156 }
157
158 cout << "\nPreorder traversal\n";
159 intTree.preOrderTraversal();
160
161 cout << "\nInorder traversal\n";
162 intTree.inOrderTraversal();
163
164 cout << "\nPostorder traversal\n";
165 intTree.postOrderTraversal();
166
167 Tree< double > doubleTree;
168 double doubleVal;
169
170 cout << "\n\n\nEnter 10 double values:\n"
171 << setiosflags( ios::fixed | ios::showpoint )
172 << setprecision( 1 );
173 for ( i = 0; i < 10; ++i ) {
174 cin >> doubleVal;
175 doubleTree.insertNode( doubleVal );
176 }
Chapter 15 Data Structures Solutions 431
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.17 Write a program based on Fig. 15.16 that inputs a line of text, tokenizes the sentence into separate words (you may want to
use the strtok library function), inserts the words in a binary search tree and prints the inorder, preorder and postorder traversals
of the tree. Use an OOP approach.
177
178 cout << "\nPreorder traversal\n";
179 doubleTree.preOrderTraversal();
180
181 cout << "\nInorder traversal\n";
182 doubleTree.inOrderTraversal();
183
184 cout << "\nPostorder traversal\n";
185 doubleTree.postOrderTraversal();
186
187 return 0;
188 }
Enter 10 integer values:
22 8 88 22 73 88 83 68 99 92
Preorder traversal
22 8 22 88 73 68 88 83 99 92
Inorder traversal
8 22 22 68 73 83 88 88 92 99
Postorder traversal
22 8 68 83 88 73 92 99 88 22
Enter 10 double values:
9.9 2.2 8.8 2.2 0.0 6.0 3.4 9.8 5.2 6.3
Preorder traversal
9.9 2.2 2.2 0.0 8.8 6.0 3.4 5.2 6.3 9.8
Inorder traversal
0.0 2.2 2.2 3.4 5.2 6.0 6.3 8.8 9.8 9.9
Postorder traversal
0.0 2.2 5.2 3.4 6.3 6.0 9.8 8.8 2.2 9.9
1// TREE
2// Definition of template class Tree
3#ifndef TREE_H
4#define TREE_H
5
6#include <iostream>
7
8using std::cout;
9
10 #include <cassert>
11 #include "treenode.h"
12
13 template< class NODETYPE >
14 class Tree {
15 public:
16 Tree();
17 void insertNode( const NODETYPE & );
18 void preOrderTraversal() const;
19 void inOrderTraversal() const;
20 void postOrderTraversal() const;
21 protected:
432 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
22 TreeNode<NODETYPE> *rootPtr;
23
24 // utility functions
25 void insertNodeHelper( TreeNode< NODETYPE > **, const NODETYPE & );
26 void preOrderHelper( TreeNode< NODETYPE > * ) const;
27 void inOrderHelper( TreeNode< NODETYPE > * ) const;
28 void postOrderHelper( TreeNode< NODETYPE > * ) const;
29 };
30
31 template< class NODETYPE >
32 Tree< NODETYPE >::Tree() { rootPtr = 0; }
33
34 template< class NODETYPE >
35 void Tree< NODETYPE >::insertNode( const NODETYPE &value )
36 { insertNodeHelper( &rootPtr, value ); }
37
38 // This function receives a pointer to a pointer so the
39 // pointer can be modified.
40 // NOTE: THIS FUNCTION WAS MODIFIED TO ALLOW DUPLICATES.
41 template< class NODETYPE >
42 void Tree< NODETYPE >::insertNodeHelper( TreeNode< NODETYPE > **ptr,
43 const NODETYPE &value )
44 {
45 if ( *ptr == 0 ) { // tree is empty
46 *ptr = new TreeNode< NODETYPE >( value );
47 assert( *ptr != 0 );
48 }
49 else // tree is not empty
50 if ( value <= ( *ptr ) -> data )
51 insertNodeHelper( &( ( *ptr ) -> leftPtr ), value );
52 else
53 insertNodeHelper( &( ( *ptr ) -> rightPtr ), value );
54 }
55
56 template< class NODETYPE >
57 void Tree< NODETYPE >::preOrderTraversal() const { preOrderHelper( rootPtr ); }
58
59 template< class NODETYPE >
60 void Tree< NODETYPE >::preOrderHelper( TreeNode< NODETYPE > *ptr ) const
61 {
62 if ( ptr != 0 ) {
63 cout << ptr -> data << ' ';
64 preOrderHelper( ptr -> leftPtr );
65 preOrderHelper( ptr -> rightPtr );
66 }
67 }
68
69 template< class NODETYPE >
70 void Tree< NODETYPE >::inOrderTraversal() const { inOrderHelper( rootPtr ); }
71
72 template< class NODETYPE >
73 void Tree< NODETYPE >::inOrderHelper( TreeNode< NODETYPE > *ptr ) const
74 {
75 if ( ptr != 0 ) {
76 inOrderHelper( ptr -> leftPtr );
77 cout << ptr -> data << ' ';
78 inOrderHelper( ptr -> rightPtr );
79 }
80 }
81
82 template< class NODETYPE >
Chapter 15 Data Structures Solutions 433
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
83 void Tree< NODETYPE >::postOrderTraversal() const { postOrderHelper( rootPtr );}
84
85 template< class NODETYPE >
86 void Tree< NODETYPE >::postOrderHelper( TreeNode< NODETYPE > *ptr ) const
87 {
88 if ( ptr != 0 ) {
89 postOrderHelper( ptr -> leftPtr );
90 postOrderHelper( ptr -> rightPtr );
91 cout << ptr -> data << ' ';
92 }
93 }
94
95 #endif
96 // TREENODE.H
97 // Definition of class TreeNode
98 #ifndef TREENODE_H
99 #define TREENODE_H
100
101 template< class T > class Tree; // forward declaration
102
103 template< class NODETYPE >
104 class TreeNode {
105 friend class Tree< NODETYPE >;
106 public:
107 TreeNode( const NODETYPE & ); // constructor
108 NODETYPE getData() const; // return data
109 TreeNode *getLeftPtr() const { return leftPtr; }
110 TreeNode *getRightPtr() const { return rightPtr; }
111 void setLeftPtr( TreeNode *ptr ) { leftPtr = ptr; }
112 void setRightPtr( TreeNode *ptr ) { rightPtr = ptr; }
113 private:
114 TreeNode *leftPtr; // pointer to left subtree
115 NODETYPE data;
116 TreeNode *rightPtr; // pointer to right subtree
117 };
118
119 // Constructor
120 template< class NODETYPE >
121 TreeNode< NODETYPE >::TreeNode( const NODETYPE &d )
122 {
123 data = d;
124 leftPtr = rightPtr = 0;
125 }
126
127 //Return a copy of the data value
128 template< class NODETYPE >
129 NODETYPE TreeNode< NODETYPE >::getData() const { return data; }
130
131 #endif
132 // STRING2.H
133 // Definition of a String class
134 #ifndef STRING1_H
135 #define STRING1_H
136
137 #include <iostream>
138
139 using std::ostream;
434 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
140 using std::istream;
141
142 class String {
143 friend ostream &operator<<( ostream &, const String & );
144 friend istream &operator>>( istream &, String & );
145 public:
146 String( const char * = "" ); // conversion constructor
147 String( const String & ); // copy constructor
148 ~String(); // destructor
149 const String &operator=( const String & ); // assignment
150 String &operator+=( const String & ); // concatenation
151 bool operator!() const; // is String empty?
152 bool operator==( const String & ) const; // test s1 == s2
153 bool operator!=( const String & ) const; // test s1 != s2
154 bool operator<( const String & ) const; // test s1 < s2
155 bool operator>( const String & ) const; // test s1 > s2
156 bool operator>=( const String & ) const; // test s1 >= s2
157 bool operator<=( const String & ) const; // test s1 <= s2
158 char &operator[]( int ); // return char reference
159 String &operator()( int, int ); // return a substring
160 int getLength() const; // return string length
161 private:
162 char *sPtr; // pointer to start of string
163 int length; // string length
164 };
165
166 #endif
167 // STRING2.CPP
168 // Member function definitions for class String.
169 // NOTE: The printing capabilities have been removed
170 // from the constructor and destructor functions.
171 #include <iostream>
172
173 using std::cout;
174 using std::ostream;
175 using std::istream;
176
177 #include <iomanip>
178
179 using std::setw;
180
181 #include <cstring>
182 using std::string;
183
184 #include <cassert>
185 #include "string2.h"
186
187 // Conversion constructor: Convert char * to String
188 String::String( const char *ptr )
189 {
190 length = strlen( ptr ); // compute length
191 sPtr = new char[ length + 1 ]; // allocate storage
192 assert( sPtr != 0 ); // terminate if memory not allocated
193 strcpy( sPtr, ptr ); // copy literal to object
194 }
195
196 // Copy constructor
197 String::String( const String &copy )
198 {
199 length = copy.length; // copy length
Chapter 15 Data Structures Solutions 435
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
200 sPtr = new char[ length + 1 ]; // allocate storage
201 assert( sPtr != 0 ); // ensure memory allocated
202 strcpy( sPtr, copy.sPtr ); // copy string
203 }
204
205 // Destructor
206 String::~String()
207 {
208 delete [] sPtr; // reclaim string
209 }
210
211 // Overloaded = operator; avoids self assignment
212 const String &String::operator=( const String &right )
213 {
214 if ( &right != this ) { // avoid self assignment
215 delete [] sPtr; // prevents memory leak
216 length = right.length; // new String length
217 sPtr = new char[ length + 1 ]; // allocate memory
218 assert( sPtr != 0 ); // ensure memory allocated
219 strcpy( sPtr, right.sPtr ); // copy string
220 }
221 else
222 cout << "Attempted assignment of a String to itself\n";
223
224 return *this; // enables concatenated assignments
225 }
226
227 // Concatenate right operand to this object and
228 // store in this object.
229 String &String::operator+=( const String &right )
230 {
231 char *tempPtr = sPtr; // hold to be able to delete
232 length += right.length; // new String length
233 sPtr = new char[ length + 1 ]; // create space
234 assert( sPtr != 0 ); // terminate if memory not allocated
235 strcpy( sPtr, tempPtr ); // left part of new String
236 strcat( sPtr, right.sPtr ); // right part of new String
237 delete [] tempPtr; // reclaim old space
238 return *this; // enables concatenated calls
239 }
240
241 // Is this String empty?
242 bool String::operator!() const { return length == 0; }
243
244 // Is this String equal to right String?
245 bool String::operator==( const String &right ) const
246 { return strcmp( sPtr, right.sPtr ) == 0; }
247
248 // Is this String not equal to right String?
249 bool String::operator!=( const String &right ) const
250 { return strcmp( sPtr, right.sPtr ) != 0; }
251
252 // Is this String less than right String?
253 bool String::operator<( const String &right ) const
254 { return strcmp( sPtr, right.sPtr ) < 0; }
255
256 // Is this String greater than right String?
257 bool String::operator>( const String &right ) const
258 { return strcmp( sPtr, right.sPtr ) > 0; }
259
260 // Is this String greater than or equal to right String?
261 bool String::operator>=( const String &right ) const
436 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
262 { return strcmp( sPtr, right.sPtr ) >= 0; }
263
264 // Is this String less than or equal to right String?
265 bool String::operator<=( const String &right ) const
266 { return strcmp( sPtr, right.sPtr ) <= 0; }
267
268 // Return a reference to a character in a String.
269 char &String::operator[]( int subscript )
270 {
271 // First test for subscript out of range
272 assert( subscript >= 0 && subscript < length );
273
274 return sPtr[ subscript ]; // creates lvalue
275 }
276
277 // Return a substring beginning at index and
278 // of length subLength as a reference to a String object.
279 String &String::operator()( int index, int subLength )
280 {
281 // ensure index is in range and substring length >= 0
282 assert( index >= 0 && index < length && subLength >= 0 );
283
284 String *subPtr = new String; // empty String
285 assert( subPtr != 0 ); // ensure new String allocated
286
287 // determine length of substring
288 if ( ( subLength == 0 ) || ( index + subLength > length ) )
289 subPtr -> length = length - index + 1;
290 else
291 subPtr -> length = subLength + 1;
292
293 // allocate memory for substring
294 delete subPtr -> sPtr; // delete character from object
295 subPtr -> sPtr = new char[ subPtr -> length ];
296 assert( subPtr -> sPtr != 0 ); // ensure space allocated
297
298 // copy substring into new String
299 strncpy( subPtr -> sPtr, &sPtr[ index ], subPtr -> length );
300 subPtr -> sPtr[ subPtr -> length ] = '\0'; // terminate new String
301
302 return *subPtr; // return new String
303 }
304
305 // Return string length
306 int String::getLength() const { return length; }
307
308 // Overloaded output operator
309 ostream &operator<<( ostream &output, const String &s )
310 {
311 output << s.sPtr;
312 return output; // enables concatenation
313 }
314
315 // Overloaded input operator
316 istream &operator>>( istream &input, String &s )
317 {
318 char temp[ 100 ]; // buffer to store input
319
320 input >> setw( 100 ) >> temp;
321 s = temp; // use String class assignment operator
322 return input; // enables concatenation
Chapter 15 Data Structures Solutions 437
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.18 In this chapter, we saw that duplicate elimination is straightforward when creating a binary search tree. Describe how you
would perform duplicate elimination using only a single-subscripted array. Compare the performance of array-based duplicate elim-
ination with the performance of binary-search-tree-based duplicate elimination.
323 }
324 // Exercise 15.17 solution
325 #include <iostream>
326
327 using std::cout;
328 using std::endl;
329 using std::cin;
330
331 #include <cstring>
332 using std::string;
333
334 #include "tree.h"
335 #include "string2.h"
336
337 int main()
338 {
339 Tree< String > stringTree;
340 char sentence[ 80 ], *tokenPtr;
341
342 cout << "Enter a sentence:\n";
343 cin.getline( sentence, 80 );
344
345 tokenPtr = strtok( sentence, " " );
346
347 while ( tokenPtr != 0 ) {
348 String *newString = new String( tokenPtr );
349 stringTree.insertNode( *newString );
350 tokenPtr = strtok( 0, " " );
351 }
352
353 cout << "\nPreorder traversal\n";
354 stringTree.preOrderTraversal();
355
356 cout << "\nInorder traversal\n";
357 stringTree.inOrderTraversal();
358
359 cout << "\nPostorder traversal\n";
360 stringTree.postOrderTraversal();
361
362 cout << endl;
363
364 return 0;
365 }
Enter a sentence:
ANSI/ISO C++ How to Program
Preorder traversal
ANSI/ISO C++ How to Program
Inorder traversal
ANSI/ISO C++ How Program to
Postorder traversal
Program to How C++ ANSI/ISO
438 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.19 Write a function depth that receives a binary tree and determines how many levels it has.
1// TREE
2// Definition of template class Tree
3#ifndef TREE_H
4#define TREE_H
5
6#include <iostream>
7
8using std::cout;
9
10 #include <cassert>
11 #include "treenode.h"
12
13 template< class NODETYPE >
14 class Tree {
15 public:
16 Tree();
17 void insertNode( const NODETYPE & );
18 void preOrderTraversal() const;
19 void inOrderTraversal() const;
20 void postOrderTraversal() const;
21 protected:
22 TreeNode<NODETYPE> *rootPtr;
23
24 // utility functions
25 void insertNodeHelper( TreeNode< NODETYPE > **, const NODETYPE & );
26 void preOrderHelper( TreeNode< NODETYPE > * ) const;
27 void inOrderHelper( TreeNode< NODETYPE > * ) const;
28 void postOrderHelper( TreeNode< NODETYPE > * ) const;
29 };
30
31 template< class NODETYPE >
32 Tree< NODETYPE >::Tree() { rootPtr = 0; }
33
34 template< class NODETYPE >
35 void Tree< NODETYPE >::insertNode( const NODETYPE &value )
36 { insertNodeHelper( &rootPtr, value ); }
37
38 // This function receives a pointer to a pointer so the
39 // pointer can be modified.
40 // NOTE: THIS FUNCTION WAS MODIFIED TO ALLOW DUPLICATES.
41 template< class NODETYPE >
42 void Tree< NODETYPE >::insertNodeHelper( TreeNode< NODETYPE > **ptr,
43 const NODETYPE &value )
44 {
45 if ( *ptr == 0 ) { // tree is empty
46 *ptr = new TreeNode< NODETYPE >( value );
47 assert( *ptr != 0 );
48 }
49 else // tree is not empty
50 if ( value <= ( *ptr ) -> data )
51 insertNodeHelper( &( ( *ptr ) -> leftPtr ), value );
52 else
53 insertNodeHelper( &( ( *ptr ) -> rightPtr ), value );
54 }
55
56 template< class NODETYPE >
57 void Tree< NODETYPE >::preOrderTraversal() const { preOrderHelper( rootPtr ); }
58
59 template< class NODETYPE >
60 void Tree< NODETYPE >::preOrderHelper( TreeNode< NODETYPE > *ptr ) const
Chapter 15 Data Structures Solutions 439
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
61 {
62 if ( ptr != 0 ) {
63 cout << ptr -> data << ' ';
64 preOrderHelper( ptr -> leftPtr );
65 preOrderHelper( ptr -> rightPtr );
66 }
67 }
68
69 template< class NODETYPE >
70 void Tree< NODETYPE >::inOrderTraversal() const { inOrderHelper( rootPtr ); }
71
72 template< class NODETYPE >
73 void Tree< NODETYPE >::inOrderHelper( TreeNode< NODETYPE > *ptr ) const
74 {
75 if ( ptr != 0 ) {
76 inOrderHelper( ptr -> leftPtr );
77 cout << ptr -> data << ' ';
78 inOrderHelper( ptr -> rightPtr );
79 }
80 }
81
82 template< class NODETYPE >
83 void Tree< NODETYPE >::postOrderTraversal() const { postOrderHelper( rootPtr );
}
84
85 template< class NODETYPE >
86 void Tree< NODETYPE >::postOrderHelper( TreeNode< NODETYPE > *ptr ) const
87 {
88 if ( ptr != 0 ) {
89 postOrderHelper( ptr -> leftPtr );
90 postOrderHelper( ptr -> rightPtr );
91 cout << ptr -> data << ' ';
92 }
93 }
94
95 #endif
96 // TREENODE.H
97 // Definition of class TreeNode
98 #ifndef TREENODE_H
99 #define TREENODE_H
100
101 template< class T > class Tree; // forward declaration
102
103 template< class NODETYPE >
104 class TreeNode {
105 friend class Tree< NODETYPE >;
106 public:
107 TreeNode( const NODETYPE & ); // constructor
108 NODETYPE getData() const; // return data
109 TreeNode *getLeftPtr() const { return leftPtr; }
110 TreeNode *getRightPtr() const { return rightPtr; }
111 void setLeftPtr( TreeNode *ptr ) { leftPtr = ptr; }
112 void setRightPtr( TreeNode *ptr ) { rightPtr = ptr; }
113 private:
114 TreeNode *leftPtr; // pointer to left subtree
115 NODETYPE data;
116 TreeNode *rightPtr; // pointer to right subtree
117 };
118
119 // Constructor
440 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
120 template< class NODETYPE >
121 TreeNode< NODETYPE >::TreeNode( const NODETYPE &d )
122 {
123 data = d;
124 leftPtr = rightPtr = 0;
125 }
126
127 //Return a copy of the data value
128 template< class NODETYPE >
129 NODETYPE TreeNode< NODETYPE >::getData() const { return data; }
130
131 #endif
132 // TREE2.H
133 // Definition of template class Tree
134 // Modified to include getDepth and determineDepth member functions.
135 #ifndef TREE2_H
136 #define TREE2_H
137
138 #include <cassert>
139 #include "treenode.h"
140 #include "tree.h"
141
142 template< class NODETYPE >
143 class Tree2 : public Tree< NODETYPE > {
144 public:
145 int getDepth() const;
146 private:
147 void determineDepth( TreeNode< NODETYPE > *, int *, int * ) const;
148 };
149
150 template< class NODETYPE >
151 int Tree2< NODETYPE >::getDepth() const
152 {
153 int totalDepth = 0, currentDepth = 0;
154
155 determineDepth( rootPtr, &totalDepth, &currentDepth );
156
157 return totalDepth;
158 }
159
160 template< class NODETYPE >
161 void Tree2< NODETYPE >::determineDepth( TreeNode< NODETYPE > *ptr,
162 int *totPtr, int *currPtr ) const
163 {
164 if ( ptr != 0 ) {
165 ++( *currPtr );
166
167 if ( *currPtr > *totPtr )
168 *totPtr = *currPtr;
169
170 determineDepth( ptr -> getLeftPtr(), totPtr, currPtr );
171 determineDepth( ptr -> getRightPtr(), totPtr, currPtr );
172 --( *currPtr );
173 }
174 }
175
176 #endif
Chapter 15 Data Structures Solutions 441
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.20 (Recursively print a list backwards) Write a member function printListBackwards that recursively outputs the items
in a linked list object in reverse order. Write a test program that creates a sorted list of integers and prints the list in reverse order.
177 // Exercise 15.19 solution
178 #include <iostream>
179
180 using std::cout;
181 using std::cin;
182
183 #include "tree2.h"
184
185 int main()
186 {
187 Tree2< int > intTree;
188 int intVal;
189
190 cout << "Enter 10 integer values:\n";
191
192 for ( int i = 0; i < 10; ++i ) {
193 cin >> intVal;
194 intTree.insertNode( intVal );
195 }
196
197 cout << "\nPreorder traversal\n";
198 intTree.preOrderTraversal();
199
200 cout << "\nInorder traversal\n";
201 intTree.inOrderTraversal();
202
203 cout << "\nPostorder traversal\n";
204 intTree.postOrderTraversal();
205
206 cout << "\n\nThere are " << intTree.getDepth()
207 << " levels in this binary tree\n";
208
209 return 0;
210 }
Enter 10 integer values:
1 2 3 88 4 6 0 22 21 10
Preorder traversal
1 0 2 3 88 4 6 22 21 10
Inorder traversal
0 1 2 3 4 6 10 21 22 88
Postorder traversal
0 10 21 22 6 4 88 3 2 1
There are 9 levels in this binary tree
1// LIST
2// Template List class definition
3// Added copy constructor to member functions (not included in chapter).
4#ifndef LIST_H
5#define LIST_H
6
7#include <iostream>
8
442 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
9using std::cout;
10
11 #include <cassert>
12 #include "Listnd.h"
13
14 template< class NODETYPE >
15 class List {
16 public:
17 List(); // default constructor
18 List( const List< NODETYPE > & ); // copy constructor
19 ~List(); // destructor
20 void insertAtFront( const NODETYPE & );
21 void insertAtBack( const NODETYPE & );
22 bool removeFromFront( NODETYPE & );
23 bool removeFromBack( NODETYPE & );
24 bool isEmpty() const;
25 void print() const;
26 protected:
27 ListNode< NODETYPE > *firstPtr; // pointer to first node
28 ListNode< NODETYPE > *lastPtr; // pointer to last node
29
30 // Utility function to allocate a new node
31 ListNode< NODETYPE > *getNewNode( const NODETYPE & );
32 };
33
34 // Default constructor
35 template< class NODETYPE >
36 List< NODETYPE >::List() { firstPtr = lastPtr = 0; }
37
38 // Copy constructor
39 template< class NODETYPE >
40 List< NODETYPE >::List( const List<NODETYPE> &copy )
41 {
42 firstPtr = lastPtr = 0; // initialize pointers
43
44 ListNode< NODETYPE > *currentPtr = copy.firstPtr;
45
46 while ( currentPtr != 0 ) {
47 insertAtBack( currentPtr -> data );
48 currentPtr = currentPtr -> nextPtr;
49 }
50 }
51
52 // Destructor
53 template< class NODETYPE >
54 List< NODETYPE >::~List()
55 {
56 if ( !isEmpty() ) { // List is not empty
57 cout << "Destroying nodes ...\n";
58
59 ListNode< NODETYPE > *currentPtr = firstPtr, *tempPtr;
60
61 while ( currentPtr != 0 ) { // delete remaining nodes
62 tempPtr = currentPtr;
63 cout << tempPtr -> data << ' ';
64 currentPtr = currentPtr -> nextPtr;
65 delete tempPtr;
66 }
67 }
68
69 cout << "\nAll nodes destroyed\n\n";
70 }
Chapter 15 Data Structures Solutions 443
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
71
72 // Insert a node at the front of the list
73 template< class NODETYPE >
74 void List< NODETYPE >::insertAtFront( const NODETYPE &value )
75 {
76 ListNode<NODETYPE> *newPtr = getNewNode( value );
77
78 if ( isEmpty() ) // List is empty
79 firstPtr = lastPtr = newPtr;
80 else { // List is not empty
81 newPtr -> nextPtr = firstPtr;
82 firstPtr = newPtr;
83 }
84 }
85
86 // Insert a node at the back of the list
87 template< class NODETYPE >
88 void List< NODETYPE >::insertAtBack( const NODETYPE &value )
89 {
90 ListNode< NODETYPE > *newPtr = getNewNode( value );
91
92 if ( isEmpty() ) // List is empty
93 firstPtr = lastPtr = newPtr;
94 else { // List is not empty
95 lastPtr -> nextPtr = newPtr;
96 lastPtr = newPtr;
97 }
98 }
99
100 // Delete a node from the front of the list
101 template< class NODETYPE >
102 bool List< NODETYPE >::removeFromFront( NODETYPE &value )
103 {
104 if ( isEmpty() ) // List is empty
105 return false; // delete unsuccessful
106 else {
107 ListNode< NODETYPE > *tempPtr = firstPtr;
108
109 if ( firstPtr == lastPtr )
110 firstPtr = lastPtr = 0;
111 else
112 firstPtr = firstPtr -> nextPtr;
113
114 value = tempPtr -> data; // data being removed
115 delete tempPtr;
116 return true; // delete successful
117 }
118 }
119
120 // Delete a node from the back of the list
121 template< class NODETYPE >
122 bool List< NODETYPE >::removeFromBack( NODETYPE &value )
123 {
124 if ( isEmpty() )
125 return false; // delete unsuccessful
126 else {
127 ListNode< NODETYPE > *tempPtr = lastPtr;
128
129 if ( firstPtr == lastPtr )
130 firstPtr = lastPtr = 0;
131 else {
132 ListNode< NODETYPE > *currentPtr = firstPtr;
444 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
133
134 while ( currentPtr -> nextPtr != lastPtr )
135 currentPtr = currentPtr -> nextPtr;
136
137 lastPtr = currentPtr;
138 currentPtr -> nextPtr = 0;
139 }
140
141 value = tempPtr -> data;
142 delete tempPtr;
143 return true; // delete successful
144 }
145 }
146
147 // Is the List empty?
148 template< class NODETYPE >
149 bool List< NODETYPE >::isEmpty() const { return firstPtr == 0; }
150
151 // Return a pointer to a newly allocated node
152 template< class NODETYPE >
153 ListNode< NODETYPE > *List< NODETYPE >::getNewNode( const NODETYPE &value )
154 {
155 ListNode< NODETYPE > *ptr = new ListNode< NODETYPE >( value );
156 assert( ptr != 0 );
157 return ptr;
158 }
159
160 // Display the contents of the List
161 template< class NODETYPE >
162 void List< NODETYPE >::print() const
163 {
164 if ( isEmpty() ) {
165 cout << "The list is empty\n\n";
166 return;
167 }
168
169 ListNode< NODETYPE > *currentPtr = firstPtr;
170
171 cout << "The list is: ";
172
173 while ( currentPtr != 0 ) {
174 cout << currentPtr -> data << ' ';
175 currentPtr = currentPtr -> nextPtr;
176 }
177
178 cout << "\n\n";
179 }
180
181 #endif
182 // LISTND.H
183 // ListNode template definition
184 #ifndef LISTND_H
185 #define LISTND_H
186
187 template< class T > class List; // forward declaration
188
189 template< class NODETYPE >
190 class ListNode {
191 friend class List< NODETYPE >; // make List a friend
192 public:
Chapter 15 Data Structures Solutions 445
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
193 ListNode( const NODETYPE & ); // constructor
194 NODETYPE getData() const; // return the data in the node
195 void setNextPtr( ListNode *nPtr ) { nextPtr = nPtr; }
196 ListNode *getNextPtr() const { return nextPtr; }
197 private:
198 NODETYPE data; // data
199 ListNode *nextPtr; // next node in the list
200 };
201
202 // Constructor
203 template< class NODETYPE >
204 ListNode< NODETYPE >::ListNode( const NODETYPE &info )
205 {
206 data = info;
207 nextPtr = 0;
208 }
209
210 // Return a copy of the data in the node
211 template< class NODETYPE >
212 NODETYPE ListNode< NODETYPE >::getData() const { return data; }
213
214 #endif
215 // LIST2.H
216 // Template List class definition
217 #ifndef LIST2_H
218 #define LIST2_H
219
220 #include <iostream>
221
222 using std::cout;
223
224 #include <cassert>
225 #include "listnd.h"
226 #include "list.h"
227
228 template< class NODETYPE >
229 class List2 : public List< NODETYPE > {
230 public:
231 void recursivePrintReverse() const;
232 private:
233 void recursivePrintReverseHelper( ListNode< NODETYPE > * ) const;
234 };
235
236 // Print a List backwards recursively.
237 template< class NODETYPE >
238 void List2< NODETYPE >::recursivePrintReverse() const
239 {
240 cout << "The list printed recursively backwards is:\n";
241 recursivePrintReverseHelper( firstPtr );
242 cout << '\n';
243 }
244
245 // Helper for printing a list backwards recursively.
246 template< class NODETYPE >
247 void List2< NODETYPE >::recursivePrintReverseHelper(
248 ListNode< NODETYPE > *currentPtr ) const
249 {
250 if ( currentPtr == 0 )
251 return;
252
446 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.21 (Recursively search a list) Write a member function searchList that recursively searches a linked list object for a spec-
ified value. The function should return a pointer to the value if it is found; otherwise, null should be returned. Use your function in
a test program that creates a list of integers. The program should prompt the user for a value to locate in the list.
253 recursivePrintReverseHelper( currentPtr -> getNextPtr() );
254 cout << currentPtr -> getData() << ' ';
255 }
256
257 #endif
258 // Exercise 15.20 solution
259
260 #include "list2.h"
261
262 int main()
263 {
264 List2< int > intList;
265
266 for ( int i = 1; i <= 10; ++i )
267 intList.insertAtBack( i );
268
269 intList.print();
270 intList.recursivePrintReverse();
271
272 return 0;
273 }
The list is: 1 2 3 4 5 6 7 8 9 10
The list printed recursively backwards is:
10 9 8 7 6 5 4 3 2 1
Destroying nodes ...
1 2 3 4 5 6 7 8 9 10
All nodes destroyed
1// LIST
2// Template List class definition
3// Added copy constructor to member functions (not included in chapter).
4#ifndef LIST_H
5#define LIST_H
6
7#include <iostream>
8
9using std::cout;
10
11 #include <cassert>
12 #include "Listnd.h"
13
14 template< class NODETYPE >
15 class List {
16 public:
17 List(); // default constructor
18 List( const List< NODETYPE > & ); // copy constructor
19 ~List(); // destructor
20 void insertAtFront( const NODETYPE & );
21 void insertAtBack( const NODETYPE & );
22 bool removeFromFront( NODETYPE & );
23 bool removeFromBack( NODETYPE & );
Chapter 15 Data Structures Solutions 447
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
24 bool isEmpty() const;
25 void print() const;
26 protected:
27 ListNode< NODETYPE > *firstPtr; // pointer to first node
28 ListNode< NODETYPE > *lastPtr; // pointer to last node
29
30 // Utility function to allocate a new node
31 ListNode< NODETYPE > *getNewNode( const NODETYPE & );
32 };
33
34 // Default constructor
35 template< class NODETYPE >
36 List< NODETYPE >::List() { firstPtr = lastPtr = 0; }
37
38 // Copy constructor
39 template< class NODETYPE >
40 List< NODETYPE >::List( const List<NODETYPE> &copy )
41 {
42 firstPtr = lastPtr = 0; // initialize pointers
43
44 ListNode< NODETYPE > *currentPtr = copy.firstPtr;
45
46 while ( currentPtr != 0 ) {
47 insertAtBack( currentPtr -> data );
48 currentPtr = currentPtr -> nextPtr;
49 }
50 }
51
52 // Destructor
53 template< class NODETYPE >
54 List< NODETYPE >::~List()
55 {
56 if ( !isEmpty() ) { // List is not empty
57 cout << "Destroying nodes ...\n";
58
59 ListNode< NODETYPE > *currentPtr = firstPtr, *tempPtr;
60
61 while ( currentPtr != 0 ) { // delete remaining nodes
62 tempPtr = currentPtr;
63 cout << tempPtr -> data << ' ';
64 currentPtr = currentPtr -> nextPtr;
65 delete tempPtr;
66 }
67 }
68
69 cout << "\nAll nodes destroyed\n\n";
70 }
71
72 // Insert a node at the front of the list
73 template< class NODETYPE >
74 void List< NODETYPE >::insertAtFront( const NODETYPE &value )
75 {
76 ListNode<NODETYPE> *newPtr = getNewNode( value );
77
78 if ( isEmpty() ) // List is empty
79 firstPtr = lastPtr = newPtr;
80 else { // List is not empty
81 newPtr -> nextPtr = firstPtr;
82 firstPtr = newPtr;
83 }
84 }
85
448 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
86 // Insert a node at the back of the list
87 template< class NODETYPE >
88 void List< NODETYPE >::insertAtBack( const NODETYPE &value )
89 {
90 ListNode< NODETYPE > *newPtr = getNewNode( value );
91
92 if ( isEmpty() ) // List is empty
93 firstPtr = lastPtr = newPtr;
94 else { // List is not empty
95 lastPtr -> nextPtr = newPtr;
96 lastPtr = newPtr;
97 }
98 }
99
100 // Delete a node from the front of the list
101 template< class NODETYPE >
102 bool List< NODETYPE >::removeFromFront( NODETYPE &value )
103 {
104 if ( isEmpty() ) // List is empty
105 return false; // delete unsuccessful
106 else {
107 ListNode< NODETYPE > *tempPtr = firstPtr;
108
109 if ( firstPtr == lastPtr )
110 firstPtr = lastPtr = 0;
111 else
112 firstPtr = firstPtr -> nextPtr;
113
114 value = tempPtr -> data; // data being removed
115 delete tempPtr;
116 return true; // delete successful
117 }
118 }
119
120 // Delete a node from the back of the list
121 template< class NODETYPE >
122 bool List< NODETYPE >::removeFromBack( NODETYPE &value )
123 {
124 if ( isEmpty() )
125 return false; // delete unsuccessful
126 else {
127 ListNode< NODETYPE > *tempPtr = lastPtr;
128
129 if ( firstPtr == lastPtr )
130 firstPtr = lastPtr = 0;
131 else {
132 ListNode< NODETYPE > *currentPtr = firstPtr;
133
134 while ( currentPtr -> nextPtr != lastPtr )
135 currentPtr = currentPtr -> nextPtr;
136
137 lastPtr = currentPtr;
138 currentPtr -> nextPtr = 0;
139 }
140
141 value = tempPtr -> data;
142 delete tempPtr;
143 return true; // delete successful
144 }
145 }
146
Chapter 15 Data Structures Solutions 449
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
147 // Is the List empty?
148 template< class NODETYPE >
149 bool List< NODETYPE >::isEmpty() const { return firstPtr == 0; }
150
151 // Return a pointer to a newly allocated node
152 template< class NODETYPE >
153 ListNode< NODETYPE > *List< NODETYPE >::getNewNode( const NODETYPE &value )
154 {
155 ListNode< NODETYPE > *ptr = new ListNode< NODETYPE >( value );
156 assert( ptr != 0 );
157 return ptr;
158 }
159
160 // Display the contents of the List
161 template< class NODETYPE >
162 void List< NODETYPE >::print() const
163 {
164 if ( isEmpty() ) {
165 cout << "The list is empty\n\n";
166 return;
167 }
168
169 ListNode< NODETYPE > *currentPtr = firstPtr;
170
171 cout << "The list is: ";
172
173 while ( currentPtr != 0 ) {
174 cout << currentPtr -> data << ' ';
175 currentPtr = currentPtr -> nextPtr;
176 }
177
178 cout << "\n\n";
179 }
180
181 #endif
182 // LISTND.H
183 // ListNode template definition
184 #ifndef LISTND_H
185 #define LISTND_H
186
187 template< class T > class List; // forward declaration
188
189 template< class NODETYPE >
190 class ListNode {
191 friend class List< NODETYPE >; // make List a friend
192 public:
193 ListNode( const NODETYPE & ); // constructor
194 NODETYPE getData() const; // return the data in the node
195 void setNextPtr( ListNode *nPtr ) { nextPtr = nPtr; }
196 ListNode *getNextPtr() const { return nextPtr; }
197 private:
198 NODETYPE data; // data
199 ListNode *nextPtr; // next node in the list
200 };
201
202 // Constructor
203 template< class NODETYPE >
204 ListNode< NODETYPE >::ListNode( const NODETYPE &info )
205 {
206 data = info;
450 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
207 nextPtr = 0;
208 }
209
210 // Return a copy of the data in the node
211 template< class NODETYPE >
212 NODETYPE ListNode< NODETYPE >::getData() const { return data; }
213
214 #endif
215 // LIST2.H
216 // Template List class definition
217 #ifndef LIST2_H
218 #define LIST2_H
219
220 #include <iostream>
221
222 using std::cout;
223
224 #include <cassert>
225 #include "listnd.h"
226 #include "list.h"
227
228 template< class NODETYPE >
229 class List2 : public List< NODETYPE > {
230 public:
231 void recursivePrintReverse() const;
232 NODETYPE *recursiveSearch( NODETYPE & ) const;
233 private:
234 // Utility functions
235 void recursivePrintReverseHelper( ListNode< NODETYPE > * ) const;
236 NODETYPE *recursiveSearchHelper( ListNode< NODETYPE > *, NODETYPE & ) const;
237 };
238
239 // Print a List backwards recursively.
240 template< class NODETYPE >
241 void List2< NODETYPE >::recursivePrintReverse() const
242 {
243 cout << "The list printed recursively backwards is:\n";
244 recursivePrintReverseHelper( firstPtr );
245 cout << '\n';
246 }
247
248 // Helper for printing a list backwards recursively.
249 template< class NODETYPE >
250 void List2< NODETYPE >::recursivePrintReverseHelper(
251 ListNode< NODETYPE > *currentPtr ) const
252 {
253 if ( currentPtr == 0 )
254 return;
255
256 recursivePrintReverseHelper( currentPtr -> nextPtr );
257 cout << currentPtr -> data << ' ';
258 }
259
260 // Search a List recursively.
261 template< class NODETYPE >
262 NODETYPE *List2< NODETYPE >::recursiveSearch( NODETYPE &val ) const
263 { return recursiveSearchHelper( firstPtr, val ); }
264
265 // Helper for searching a list recursively.
266 template< class NODETYPE >
Chapter 15 Data Structures Solutions 451
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.22 (Binary tree delete) In this exercise, we discuss deleting items from binary search trees. The deletion algorithm is not as
straightforward as the insertion algorithm. There are three cases that are encountered when deleting an item—the item is contained
in a leaf node (i.e., it has no children), the item is contained in a node that has one child or the item is contained in a node that has
two children.
If the item to be deleted is contained in a leaf node, the node is deleted and the pointer in the parent node is set to null.
If the item to be deleted is contained in a node with one child, the pointer in the parent node is set to point to the child node
267 NODETYPE *List2< NODETYPE >::recursiveSearchHelper(
268 ListNode< NODETYPE > *currentPtr, NODETYPE &value ) const
269 {
270 if ( currentPtr == 0 )
271 return 0;
272
273 if ( currentPtr -> getData() == value )
274 return currentPtr -> getAddress();
275
276 return recursiveSearchHelper( currentPtr -> getNextPtr(), value );
277 }
278
279 #endif
280 // Exercise 15.21 solution
281 #include <iostream>
282
283 using std::cout;
284 using std::cin;
285
286 #include "list2.h"
287
288 int main()
289 {
290 List2< int > intList;
291
292 for ( int i = 2; i <= 20; i += 2 )
293 intList.insertAtBack( i );
294
295 intList.print();
296
297 int value, *ptr;
298
299 cout << "Enter a value to search for: ";
300 cin >> value;
301 ptr = intList.recursiveSearch( value );
302
303 if ( ptr != 0 )
304 cout << *ptr << " was found\n";
305 else
306 cout << "Element not found\n";
307
308 return 0;
309 }
The list is: 2 4 6 8 10 12 14 16 18 20
Enter a value to search for: 14
14 was found
Destroying nodes ...
2 4 6 8 10 12 14 16 18 20
All nodes destroyed
452 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
and the node containing the data item is deleted. This causes the child node to take the place of the deleted node in the tree.
The last case is the most difficult. When a node with two children is deleted, another node in the tree must take its place. How-
ever, the pointer in the parent node cannot be assigned to point to one of the children of the node to be deleted. In most cases, the
resulting binary search tree would not adhere to the following characteristic of binary search trees (with no duplicate values): The
values in any left subtree are less than the value in the parent node, and the values in any right subtree are greater than the value
in the parent node.
Which node is used as a replacement node to maintain this characteristic? Either the node containing the largest value in the
tree less than the value in the node being deleted, or the node containing the smallest value in the tree greater than the value in the
node being deleted. Let us consider the node with the smaller value. In a binary search tree, the largest value less than a parent’s
value is located in the left subtree of the parent node and is guaranteed to be contained in the rightmost node of the subtree. This
node is located by walking down the left subtree to the right until the pointer to the right child of the current node is null. We are
now pointing to the replacement node, which is either a leaf node or a node with one child to its left. If the replacement node is a
leaf node, the steps to perform the deletion are as follows:
1) Store the pointer to the node to be deleted in a temporary pointer variable (this pointer is used to delete the dynamically
allocated memory)
2) Set the pointer in the parent of the node being deleted to point to the replacement node
3) Set the pointer in the parent of the replacement node to null
4) Set the pointer to the right subtree in the replacement node to point to the right subtree of the node to be deleted
5) Delete the node to which the temporary pointer variable points.
The deletion steps for a replacement node with a left child are similar to those for a replacement node with no children, but the
algorithm also must move the child in to the replacement node’s position in the tree. If the replacement node is a node with a left
child, the steps to perform the deletion are as follows:
1) Store the pointer to the node to be deleted in a temporary pointer variable
2) Set the pointer in the parent of the node being deleted to point to the replacement node
3) Set the pointer in the parent of the replacement node to point to the left child of the replacement node
4) Set the pointer to the right subtree in the replacement node to point to the right subtree of the node to be deleted
5) Delete the node to which the temporary pointer variable points.
Write member function deleteNode, which takes as its arguments a pointer to the root node of the tree object and the value
to be deleted. The function should locate in the tree the node containing the value to be deleted and use the algorithms discussed
here to delete the node. If the value is not found in the tree, the function should print a message that indicates whether or not the
value is deleted. Modify the program of Fig. 15.16 to use this function. After deleting an item, call the inOrder, preOrder and
postOrder traversal functions to confirm that the delete operation was performed correctly.
15.23 (Binary tree search) Write member function binaryTreeSearch, which attempts to locate a specified value in a binary
search tree object. The function should take as arguments a pointer to the root node of the binary tree and a search key to be l ocated.
If the node containing the search key is found, the function should return a pointer to that node; otherwise, the function should return
a null pointer.
1// TREE
2// Definition of template class Tree
3#ifndef TREE_H
4#define TREE_H
5
6#include <iostream>
7
8using std::cout;
9
10 #include <cassert>
11 #include "treenode.h"
12
13 template< class NODETYPE >
14 class Tree {
15 public:
16 Tree();
17 void insertNode( const NODETYPE & );
18 void preOrderTraversal() const;
19 void inOrderTraversal() const;
20 void postOrderTraversal() const;
Chapter 15 Data Structures Solutions 453
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
21 protected:
22 TreeNode<NODETYPE> *rootPtr;
23
24 // utility functions
25 void insertNodeHelper( TreeNode< NODETYPE > **, const NODETYPE & );
26 void preOrderHelper( TreeNode< NODETYPE > * ) const;
27 void inOrderHelper( TreeNode< NODETYPE > * ) const;
28 void postOrderHelper( TreeNode< NODETYPE > * ) const;
29 };
30
31 template< class NODETYPE >
32 Tree< NODETYPE >::Tree() { rootPtr = 0; }
33
34 template< class NODETYPE >
35 void Tree< NODETYPE >::insertNode( const NODETYPE &value )
36 { insertNodeHelper( &rootPtr, value ); }
37
38 // This function receives a pointer to a pointer so the
39 // pointer can be modified.
40 // NOTE: THIS FUNCTION WAS MODIFIED TO ALLOW DUPLICATES.
41 template< class NODETYPE >
42 void Tree< NODETYPE >::insertNodeHelper( TreeNode< NODETYPE > **ptr,
43 const NODETYPE &value )
44 {
45 if ( *ptr == 0 ) { // tree is empty
46 *ptr = new TreeNode< NODETYPE >( value );
47 assert( *ptr != 0 );
48 }
49 else // tree is not empty
50 if ( value <= ( *ptr ) -> data )
51 insertNodeHelper( &( ( *ptr ) -> leftPtr ), value );
52 else
53 insertNodeHelper( &( ( *ptr ) -> rightPtr ), value );
54 }
55
56 template< class NODETYPE >
57 void Tree< NODETYPE >::preOrderTraversal() const { preOrderHelper( rootPtr ); }
58
59 template< class NODETYPE >
60 void Tree< NODETYPE >::preOrderHelper( TreeNode< NODETYPE > *ptr ) const
61 {
62 if ( ptr != 0 ) {
63 cout << ptr -> data << ' ';
64 preOrderHelper( ptr -> leftPtr );
65 preOrderHelper( ptr -> rightPtr );
66 }
67 }
68
69 template< class NODETYPE >
70 void Tree< NODETYPE >::inOrderTraversal() const { inOrderHelper( rootPtr ); }
71
72 template< class NODETYPE >
73 void Tree< NODETYPE >::inOrderHelper( TreeNode< NODETYPE > *ptr ) const
74 {
75 if ( ptr != 0 ) {
76 inOrderHelper( ptr -> leftPtr );
77 cout << ptr -> data << ' ';
78 inOrderHelper( ptr -> rightPtr );
79 }
80 }
81
82 template< class NODETYPE >
454 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
83 void Tree< NODETYPE >::postOrderTraversal() const { postOrderHelper( rootPtr );}
84
85 template< class NODETYPE >
86 void Tree< NODETYPE >::postOrderHelper( TreeNode< NODETYPE > *ptr ) const
87 {
88 if ( ptr != 0 ) {
89 postOrderHelper( ptr -> leftPtr );
90 postOrderHelper( ptr -> rightPtr );
91 cout << ptr -> data << ' ';
92 }
93 }
94
95 #endif
96 // TREENODE.H
97 // Definition of class TreeNode
98 #ifndef TREENODE_H
99 #define TREENODE_H
100
101 template< class T > class Tree; // forward declaration
102
103 template< class NODETYPE >
104 class TreeNode {
105 friend class Tree< NODETYPE >;
106 public:
107 TreeNode( const NODETYPE & ); // constructor
108 NODETYPE getData() const; // return data
109 TreeNode *getLeftPtr() const { return leftPtr; }
110 TreeNode *getRightPtr() const { return rightPtr; }
111 void setLeftPtr( TreeNode *ptr ) { leftPtr = ptr; }
112 void setRightPtr( TreeNode *ptr ) { rightPtr = ptr; }
113 private:
114 TreeNode *leftPtr; // pointer to left subtree
115 NODETYPE data;
116 TreeNode *rightPtr; // pointer to right subtree
117 };
118
119 // Constructor
120 template< class NODETYPE >
121 TreeNode< NODETYPE >::TreeNode( const NODETYPE &d )
122 {
123 data = d;
124 leftPtr = rightPtr = 0;
125 }
126
127 //Return a copy of the data value
128 template< class NODETYPE >
129 NODETYPE TreeNode< NODETYPE >::getData() const { return data; }
130
131 #endif
132 // TREE2.H
133 // Definition of template class Tree
134 #ifndef TREE2_H
135 #define TREE2_H
136
137 #include <iostream>
138
139 using std::cout;
Chapter 15 Data Structures Solutions 455
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
140
141 #include <cassert>
142 #include "treenode.h"
143 #include "tree.h"
144
145 template< class NODETYPE >
146 class Tree2 : public Tree< NODETYPE > {
147 public:
148 TreeNode< NODETYPE > *binarySearch( int ) const;
149 private:
150 TreeNode< NODETYPE > *binarySearchHelper( TreeNode< NODETYPE > *,
151 int ) const;
152 };
153
154 template< class NODETYPE >
155 TreeNode< NODETYPE > *Tree2< NODETYPE >::binarySearch( int val ) const
156 { return binarySearchHelper( rootPtr, val ); }
157
158 template< class NODETYPE >
159 TreeNode< NODETYPE > *Tree2< NODETYPE >::binarySearchHelper(
160 TreeNode< NODETYPE > *ptr, int value ) const
161 {
162 if ( ptr == 0 )
163 return 0;
164
165 cout << "Comparing " << value << " to " << ptr -> getData();
166
167 if ( value == ptr -> getData() ) { // match
168 cout << "; search complete\n";
169 return ptr;
170 }
171 else if ( value < ptr -> getData() ) { // search val less than current data
172 cout << "; smaller, walk left\n";
173 return binarySearchHelper( ptr -> getLeftPtr(), value );
174 }
175 else { // search val greater than current data
176 cout << "; larger, walk right\n";
177 return binarySearchHelper( ptr -> getRightPtr(), value );
178 }
179 }
180
181 #endif
182 // Exercise 15.23 solution
183 #include <iostream>
184
185 using std::cout;
186 using std::endl;
187 using std::cin;
188
189 #include <cstdlib>
190 #include <ctime>
191 #include "tree2.h"
192
193 int main()
194 {
195 srand( time( 0 ) ); // randomize the random number generator
196
197 Tree2< int > intTree;
198 int intVal;
199
456 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.24 (Level-order binary tree traversal) The program of Fig. 15.16 illustrated three recursive methods of traversing a binary
tree—inorder, preorder and postorder traversals. This exercise presents the level-order traversal of a binary tree in which the node
values are printed level by level, starting at the root node level. The nodes on each level are printed from left to right. The level-
order traversal is not a recursive algorithm. It uses a queue object to control the output of the nodes. The algorithm is as follows:
1) Insert the root node in the queue
2) While there are nodes left in the queue,
Get the next node in the queue
Print the node’s value
If the pointer to the left child of the node is not null
Insert the left child node in the queue
If the pointer to the right child of the node is not null
Insert the right child node in the queue.
Write member function levelOrder to perform a level-order traversal of a binary tree object. Modify the program of Fig
15.16 to use this function. (Note: You will also need to modify and incorporate the queue-processing functions of Fig. 15.12 in this
program.)
200 cout << "The values being placed in the tree are:\n";
201
202 for ( int i = 1; i <= 15; ++i ) {
203 intVal = rand() % 100;
204 cout << intVal << ' ';
205 intTree.insertNode( intVal );
206 }
207
208 cout << "\n\nEnter a value to search for: ";
209 cin >> intVal;
210
211 TreeNode< int > *ptr = intTree.binarySearch( intVal );
212
213 if ( ptr != 0 )
214 cout << ptr -> getData() << " was found\n";
215 else
216 cout << "Element was not found\n";
217
218 cout << endl;
219
220 return 0;
221 }
The values being placed in the tree are:
96 96 58 31 44 0 12 61 99 32 29 92 79 55 1
Enter a value to search for: 1
Comparing 1 to 96; smaller, walk left
Comparing 1 to 96; smaller, walk left
Comparing 1 to 58; smaller, walk left
Comparing 1 to 31; smaller, walk left
Comparing 1 to 0; larger, walk right
Comparing 1 to 12; smaller, walk left
Comparing 1 to 1; search complete
1 was found
1// TREE
2// Definition of template class Tree
3#ifndef TREE_H
4#define TREE_H
5
Chapter 15 Data Structures Solutions 457
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
6#include <iostream>
7
8using std::cout;
9
10 #include <cassert>
11 #include "treenode.h"
12
13 template< class NODETYPE >
14 class Tree {
15 public:
16 Tree();
17 void insertNode( const NODETYPE & );
18 void preOrderTraversal() const;
19 void inOrderTraversal() const;
20 void postOrderTraversal() const;
21 protected:
22 TreeNode<NODETYPE> *rootPtr;
23
24 // utility functions
25 void insertNodeHelper( TreeNode< NODETYPE > **, const NODETYPE & );
26 void preOrderHelper( TreeNode< NODETYPE > * ) const;
27 void inOrderHelper( TreeNode< NODETYPE > * ) const;
28 void postOrderHelper( TreeNode< NODETYPE > * ) const;
29 };
30
31 template< class NODETYPE >
32 Tree< NODETYPE >::Tree() { rootPtr = 0; }
33
34 template< class NODETYPE >
35 void Tree< NODETYPE >::insertNode( const NODETYPE &value )
36 { insertNodeHelper( &rootPtr, value ); }
37
38 // This function receives a pointer to a pointer so the
39 // pointer can be modified.
40 // NOTE: THIS FUNCTION WAS MODIFIED TO ALLOW DUPLICATES.
41 template< class NODETYPE >
42 void Tree< NODETYPE >::insertNodeHelper( TreeNode< NODETYPE > **ptr,
43 const NODETYPE &value )
44 {
45 if ( *ptr == 0 ) { // tree is empty
46 *ptr = new TreeNode< NODETYPE >( value );
47 assert( *ptr != 0 );
48 }
49 else // tree is not empty
50 if ( value <= ( *ptr ) -> data )
51 insertNodeHelper( &( ( *ptr ) -> leftPtr ), value );
52 else
53 insertNodeHelper( &( ( *ptr ) -> rightPtr ), value );
54 }
55
56 template< class NODETYPE >
57 void Tree< NODETYPE >::preOrderTraversal() const { preOrderHelper( rootPtr ); }
58
59 template< class NODETYPE >
60 void Tree< NODETYPE >::preOrderHelper( TreeNode< NODETYPE > *ptr ) const
61 {
62 if ( ptr != 0 ) {
63 cout << ptr -> data << ' ';
64 preOrderHelper( ptr -> leftPtr );
65 preOrderHelper( ptr -> rightPtr );
66 }
67 }
458 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
68
69 template< class NODETYPE >
70 void Tree< NODETYPE >::inOrderTraversal() const { inOrderHelper( rootPtr ); }
71
72 template< class NODETYPE >
73 void Tree< NODETYPE >::inOrderHelper( TreeNode< NODETYPE > *ptr ) const
74 {
75 if ( ptr != 0 ) {
76 inOrderHelper( ptr -> leftPtr );
77 cout << ptr -> data << ' ';
78 inOrderHelper( ptr -> rightPtr );
79 }
80 }
81
82 template< class NODETYPE >
83 void Tree< NODETYPE >::postOrderTraversal() const { postOrderHelper( rootPtr );}
84
85 template< class NODETYPE >
86 void Tree< NODETYPE >::postOrderHelper( TreeNode< NODETYPE > *ptr ) const
87 {
88 if ( ptr != 0 ) {
89 postOrderHelper( ptr -> leftPtr );
90 postOrderHelper( ptr -> rightPtr );
91 cout << ptr -> data << ' ';
92 }
93 }
94
95 #endif
96 // TREENODE.H
97 // Definition of class TreeNode
98 #ifndef TREENODE_H
99 #define TREENODE_H
100
101 template< class T > class Tree; // forward declaration
102
103 template< class NODETYPE >
104 class TreeNode {
105 friend class Tree< NODETYPE >;
106 public:
107 TreeNode( const NODETYPE & ); // constructor
108 NODETYPE getData() const; // return data
109 TreeNode *getLeftPtr() const { return leftPtr; }
110 TreeNode *getRightPtr() const { return rightPtr; }
111 void setLeftPtr( TreeNode *ptr ) { leftPtr = ptr; }
112 void setRightPtr( TreeNode *ptr ) { rightPtr = ptr; }
113 private:
114 TreeNode *leftPtr; // pointer to left subtree
115 NODETYPE data;
116 TreeNode *rightPtr; // pointer to right subtree
117 };
118
119 // Constructor
120 template< class NODETYPE >
121 TreeNode< NODETYPE >::TreeNode( const NODETYPE &d )
122 {
123 data = d;
124 leftPtr = rightPtr = 0;
125 }
126
127 //Return a copy of the data value
Chapter 15 Data Structures Solutions 459
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
128 template< class NODETYPE >
129 NODETYPE TreeNode< NODETYPE >::getData() const { return data; }
130
131 #endif
132 // TREE2.H
133 // Definition of template class Tree
134 #ifndef TREE2_H
135 #define TREE2_H
136
137 #include <iostream>
138
139 using std::cout;
140
141 #include <cassert>
142 #include "treenode.h"
143 #include "queue.h"
144 #include "tree.h"
145
146 template< class NODETYPE >
147 class Tree2 : public Tree< NODETYPE > {
148 public:
149 void levelOrderTraversal();
150 };
151
152 template< class NODETYPE >
153 void Tree2< NODETYPE >::levelOrderTraversal()
154 {
155 Queue< TreeNode< NODETYPE > * > queue;
156 TreeNode< NODETYPE > *nodePtr;
157
158 if ( rootPtr != 0 )
159 queue.enqueue( rootPtr );
160
161 while ( !queue.isEmpty() ) {
162 nodePtr = queue.dequeue();
163 cout << nodePtr -> getData() << ' ';
164
165 if ( nodePtr -> getLeftPtr() != 0 )
166 queue.enqueue( nodePtr -> getLeftPtr() );
167
168 if ( nodePtr -> getRightPtr() != 0 )
169 queue.enqueue( nodePtr -> getRightPtr() );
170 }
171 }
172
173 #endif
174 // QUEUE.H
175 // Definition of class Queue
176 #ifndef QUEUE_H
177 #define QUEUE_H
178
179 #include <iostream>
180
181 using std::cout;
182
183 #include <new>
184 #include <cstdlib>
185 #include "queuend.h"
460 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
186
187 template < class T >
188 class Queue {
189 public:
190 Queue(); // default constructor
191 ~Queue(); // destructor
192 void enqueue( T ); // insert item in queue
193 T dequeue(); // remove item from queue
194 bool isEmpty() const; // is the queue empty?
195 void print() const; // output the queue
196 private:
197 QueueNode< T > *headPtr; // pointer to first QueueNode
198 QueueNode< T > *tailPtr; // pointer to last QueueNode
199 };
200
201 // Member function definitions for class Queue
202 template < class T >
203 Queue< T >::Queue() { headPtr = tailPtr = 0; }
204
205 template < class T >
206 Queue< T >::~Queue()
207 {
208 QueueNode< T > *tempPtr, *currentPtr = headPtr;
209
210 while ( currentPtr != 0 ) {
211 tempPtr = currentPtr;
212 currentPtr = currentPtr -> nextPtr;
213 delete tempPtr;
214 }
215 }
216
217 template < class T >
218 void Queue< T >::enqueue( T d )
219 {
220 QueueNode< T > *newPtr = new QueueNode< T >( d );
221 assert( newPtr != 0 );
222
223 if ( isEmpty() )
224 headPtr = tailPtr = newPtr;
225 else {
226 tailPtr -> nextPtr = newPtr;
227 tailPtr = newPtr;
228 }
229 }
230
231 template < class T >
232 T Queue< T >::dequeue()
233 {
234 assert( !isEmpty() );
235
236 QueueNode< T > *tempPtr = headPtr;
237
238 headPtr = headPtr -> nextPtr;
239 T value = tempPtr -> data;
240 delete tempPtr;
241
242 if ( headPtr == 0 )
243 tailPtr = 0;
244
245 return value;
246 }
247
Chapter 15 Data Structures Solutions 461
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
248 template < class T >
249 bool Queue< T >::isEmpty() const { return headPtr == 0; }
250
251 template < class T >
252 void Queue< T >::print() const
253 {
254 QueueNode< T > *currentPtr = headPtr;
255
256 if ( isEmpty() ) // Queue is empty
257 cout << "Queue is empty\n";
258 else { // Queue is not empty
259 cout << "The queue is:\n";
260
261 while ( currentPtr != 0 ) {
262 cout << currentPtr -> data << ' ';
263 currentPtr = currentPtr -> nextPtr;
264 }
265
266 cout << endl;
267 }
268 }
269
270 #endif
271 // QUEUEND.H
272 // Definition of template class QueueNode
273 #ifndef QUEUEND_H
274 #define QUEUEND_H
275
276 template< class T > class Queue; // forward declaration
277
278 template < class T >
279 class QueueNode {
280 friend class Queue< T >;
281 public:
282 QueueNode( const T & = 0 );
283 T getData() const;
284 private:
285 T data;
286 QueueNode *nextPtr;
287 };
288
289 // Member function definitions for class QueueNode
290 template < class T >
291 QueueNode< T >::QueueNode( const T &d )
292 {
293 data = d;
294 nextPtr = 0;
295 }
296
297 template < class T >
298 T QueueNode< T >::getData() const { return data; }
299
300 #endif
301 // Exercise 15.24 solution
302 #include <iostream>
303 using std::cout;
304 using std::endl;
462 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.25 (Printing trees) Write a recursive member function outputTree to display a binary tree object on the screen. The func-
tion should output the tree row by row, with the top of the tree at the left of the screen and the bottom of the tree toward the right of
the screen. Each row is output vertically. For example, the binary tree illustrated in Fig. 15.19 is output as follows:
Note that the rightmost leaf node appears at the top of the output in the rightmost column and the root node appears at the left of the
output. Each column of output starts five spaces to the right of the previous column. Function outputTree should receive an argu-
ment totalSpaces representing the number of spaces preceding the value to be output (this variable should start at zero so the
305
306 #include <cstdlib>
307 #include <ctime>
308 #include "tree2.h"
309
310 int main()
311 {
312 srand( time( 0 ) ); // randomize the random number generator
313
314 Tree2< int > intTree;
315 int intVal;
316
317 cout << "The values being placed in the tree are:\n";
318
319 for ( int i = 1; i <= 15; ++i ) {
320 intVal = rand() % 100;
321 cout << intVal << ' ';
322 intTree.insertNode( intVal );
323 }
324
325 cout << "\n\nThe level order traversal is:\n";
326 intTree.levelOrderTraversal();
327
328 cout << endl;
329
330 return 0;
331 }
The values being placed in the tree are:
13 21 85 48 83 42 93 38 29 11 21 4 6 69 81
The level order traversal is:
13 11 21 4 21 85 6 48 93 42 83 38 69 29 81
99
97
92
83
72
71
69
49
44
40
32
28
19
18
11
Chapter 15 Data Structures Solutions 463
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
root node is output at the left of the screen). The function uses a modified inorder traversal to output the tree—it starts at the right-
most node in the tree and works back to the left. The algorithm is as follows:
While the pointer to the current node is not null
Recursively call outputTree with the right subtree of the current node and
totalSpaces + 5
Use a for structure to count from 1 to totalSpaces and output spaces
Output the value in the current node
Set the pointer to the current node to point to the left subtree of the current node
Increment totalSpaces by 5.
1// TREE
2// Definition of template class Tree
3#ifndef TREE_H
4#define TREE_H
5
6#include <iostream>
7
8using std::cout;
9
10 #include <cassert>
11 #include "treenode.h"
12
13 template< class NODETYPE >
14 class Tree {
15 public:
16 Tree();
17 void insertNode( const NODETYPE & );
18 void preOrderTraversal() const;
19 void inOrderTraversal() const;
20 void postOrderTraversal() const;
21 protected:
22 TreeNode<NODETYPE> *rootPtr;
23
24 // utility functions
25 void insertNodeHelper( TreeNode< NODETYPE > **, const NODETYPE & );
26 void preOrderHelper( TreeNode< NODETYPE > * ) const;
27 void inOrderHelper( TreeNode< NODETYPE > * ) const;
28 void postOrderHelper( TreeNode< NODETYPE > * ) const;
29 };
30
31 template< class NODETYPE >
32 Tree< NODETYPE >::Tree() { rootPtr = 0; }
33
34 template< class NODETYPE >
35 void Tree< NODETYPE >::insertNode( const NODETYPE &value )
36 { insertNodeHelper( &rootPtr, value ); }
37
38 // This function receives a pointer to a pointer so the
39 // pointer can be modified.
40 // NOTE: THIS FUNCTION WAS MODIFIED TO ALLOW DUPLICATES.
41 template< class NODETYPE >
42 void Tree< NODETYPE >::insertNodeHelper( TreeNode< NODETYPE > **ptr,
43 const NODETYPE &value )
44 {
45 if ( *ptr == 0 ) { // tree is empty
46 *ptr = new TreeNode< NODETYPE >( value );
47 assert( *ptr != 0 );
48 }
49 else // tree is not empty
50 if ( value <= ( *ptr ) -> data )
51 insertNodeHelper( &( ( *ptr ) -> leftPtr ), value );
464 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
52 else
53 insertNodeHelper( &( ( *ptr ) -> rightPtr ), value );
54 }
55
56 template< class NODETYPE >
57 void Tree< NODETYPE >::preOrderTraversal() const { preOrderHelper( rootPtr ); }
58
59 template< class NODETYPE >
60 void Tree< NODETYPE >::preOrderHelper( TreeNode< NODETYPE > *ptr ) const
61 {
62 if ( ptr != 0 ) {
63 cout << ptr -> data << ' ';
64 preOrderHelper( ptr -> leftPtr );
65 preOrderHelper( ptr -> rightPtr );
66 }
67 }
68
69 template< class NODETYPE >
70 void Tree< NODETYPE >::inOrderTraversal() const { inOrderHelper( rootPtr ); }
71
72 template< class NODETYPE >
73 void Tree< NODETYPE >::inOrderHelper( TreeNode< NODETYPE > *ptr ) const
74 {
75 if ( ptr != 0 ) {
76 inOrderHelper( ptr -> leftPtr );
77 cout << ptr -> data << ' ';
78 inOrderHelper( ptr -> rightPtr );
79 }
80 }
81
82 template< class NODETYPE >
83 void Tree< NODETYPE >::postOrderTraversal() const { postOrderHelper( rootPtr );}
84
85 template< class NODETYPE >
86 void Tree< NODETYPE >::postOrderHelper( TreeNode< NODETYPE > *ptr ) const
87 {
88 if ( ptr != 0 ) {
89 postOrderHelper( ptr -> leftPtr );
90 postOrderHelper( ptr -> rightPtr );
91 cout << ptr -> data << ' ';
92 }
93 }
94
95 #endif
96 // TREENODE.H
97 // Definition of class TreeNode
98 #ifndef TREENODE_H
99 #define TREENODE_H
100
101 template< class T > class Tree; // forward declaration
102
103 template< class NODETYPE >
104 class TreeNode {
105 friend class Tree< NODETYPE >;
106 public:
107 TreeNode( const NODETYPE & ); // constructor
108 NODETYPE getData() const; // return data
109 TreeNode *getLeftPtr() const { return leftPtr; }
110 TreeNode *getRightPtr() const { return rightPtr; }
111 void setLeftPtr( TreeNode *ptr ) { leftPtr = ptr; }
Chapter 15 Data Structures Solutions 465
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
112 void setRightPtr( TreeNode *ptr ) { rightPtr = ptr; }
113 private:
114 TreeNode *leftPtr; // pointer to left subtree
115 NODETYPE data;
116 TreeNode *rightPtr; // pointer to right subtree
117 };
118
119 // Constructor
120 template< class NODETYPE >
121 TreeNode< NODETYPE >::TreeNode( const NODETYPE &d )
122 {
123 data = d;
124 leftPtr = rightPtr = 0;
125 }
126
127 //Return a copy of the data value
128 template< class NODETYPE >
129 NODETYPE TreeNode< NODETYPE >::getData() const { return data; }
130
131 #endif
132 // TREE2
133 // Definition of template class Tree
134 #ifndef TREE2_H
135 #define TREE2_H
136
137 #include <iostream>
138
139 using std::cout;
140
141 #include <cassert>
142 #include "treenode.h"
143 #include "tree.h"
144
145 template< class NODETYPE >
146 class Tree2 : public Tree< NODETYPE > {
147 public:
148 void outputTree() const;
149 private:
150 void outputTreeHelper( TreeNode< NODETYPE > *, int ) const;
151 };
152
153 template< class NODETYPE >
154 void Tree2< NODETYPE >::outputTree() const { outputTreeHelper( rootPtr, 0 ); }
155
156 template< class NODETYPE >
157 void Tree2< NODETYPE >::outputTreeHelper( TreeNode< NODETYPE > *ptr,
158 int totalSpaces ) const
159 {
160 if ( ptr != 0 ) {
161 outputTreeHelper( ptr -> getRightPtr(), totalSpaces + 5 );
162
163 for ( int i = 1; i <= totalSpaces; ++i )
164 cout << ' ';
165
166 cout << ptr -> getData() << '\n';
167 outputTreeHelper( ptr -> getLeftPtr(), totalSpaces + 5 );
168 }
169 }
170
171 #endif
466 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
SPECIAL SECTION—BUILDING YOUR OWN COMPILER
In Exercises 5.18 and 5.19, we introduced Simpletron Machine Language (SML) and you implemented a Simpletron computer
simulator to execute programs written in SML. In this section, we build a compiler that converts programs written in a high-level
programming language to SML. This section “ties” together the entire programming process. You will write programs in this new
high-level language, compile these programs on the compiler you build and run the programs on the simulator you built in Exercise
7.19. You should make every effort to implement your compiler in an object-oriented manner.
172 // Exercise 15.25 solution
173 #include <iostream>
174
175 using std::cout;
176
177 #include <cstdlib>
178 #include <ctime>
179 #include "tree2.h"
180
181 int main()
182 {
183 srand( time( 0 ) ); // randomize the random number generator
184
185 Tree2< int > intTree;
186 int intVal;
187
188 cout << "The values being placed in the tree are:\n";
189
190 for ( int i = 1; i <= 15; ++i ) {
191 intVal = rand() % 100;
192 cout << intVal << ' ';
193 intTree.insertNode( intVal );
194 }
195
196 cout << "\n\nThe tree is:\n";
197 intTree.outputTree();
198
199 return 0;
200 }
The values being placed in the tree are:
12 14 56 18 12 97 12 82 96 27 99 90 22 87 15
The tree is:
99
97
96
90
87
82
56
27
22
18
15
14
12
12
12
Chapter 15 Data Structures Solutions 467
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.26 (The Simple Language) Before we begin building the compiler, we discuss a simple, yet powerful, high-level language sim-
ilar to early versions of the popular language BASIC. We call the language Simple. Every Simple statement consists of a line number
and a Simple instruction. Line numbers must appear in ascending order. Each instruction begins with one of the following Simple
commands: rem, input, let, print, goto, if/goto and end (see Fig. 15.20). All commands except end can be used repeat-
edly. Simple evaluates only integer expressions using the +, -, * and / operators. These operators have the same precedence as in
C. Parentheses can be used to change the order of evaluation of an expression.
Our Simple compiler recognizes only lowercase letters. All characters in a Simple file should be lowercase (uppercase letters
result in a syntax error unless they appear in a rem statement, in which case they are ignored). A variable name is a single letter.
Simple does not allow descriptive variable names, so variables should be explained in remarks to indicate their use in a program.
Simple uses only integer variables. Simple does not have variable declarations—merely mentioning a variable name in a program
causes the variable to be declared and initialized to zero automatically. The syntax of Simple does not allow string manipulation
(reading a string, writing a string, comparing strings, etc.). If a string is encountered in a Simple program (after a command other
than rem), the compiler generates a syntax error. The first version of our compiler will assume that Simple programs are entered
correctly. Exercise 15.29 asks the student to modify the compiler to perform syntax error checking.
Simple uses the conditional if/goto statement and the unconditional goto statement to alter the flow of control during pro-
gram execution. If the condition in the if/goto statement is true, control is transferred to a specific line of the program. The fol-
lowing relational and equality operators are valid in an if/goto statement: <, >, <=, >=, == and !=. The precedence of these
operators is the same as in C++.
Let us now consider several programs that demonstrate Simple’s features. The first program (Fig. 15.21) reads two integers
from the keyboard, stores the values in variables a and b and computes and prints their sum (stored in variable c).
The program of Fig. 15.22 determines and prints the larger of two integers. The integers are input from the keyboard and
stored in s and t. The if/goto statement tests the condition s >= t. If the condition is true, control is transferred to line 90 and
s is output; otherwise, t is output and control is transferred to the end statement in line 99 where the program terminates.
Simple does not provide a repetition structure (such as C++’s for, while or do/while). However, Simple can simulate
each of C++'s repetition structures using the if/goto and goto statements. Figure 15.23 uses a sentinel-controlled loop to calcu-
late the squares of several integers. Each integer is input from the keyboard and stored in variable j. If the value entered is the sen-
tinel
-9999, control is transferred to line 99, where the program terminates. Otherwise, k is assigned the square of j, k is output to the
screen and control is passed to line 20, where the next integer is input.
Command Example statement Description
rem 50 rem this is a remark Text following rem is for documentation purposes and is ignored
by the compiler.
input 30 input x Display a question mark to prompt the user to enter an integer.
Read that integer from the keyboard and store the integer in x.
let 80 let u = 4 * (j - 56) Assign u the value of 4 * (j - 56). Note that an arbitrarily com-
plex expression can appear to the right of the equals sign.
print 10 print w Display the value of w.
goto 70 goto 45 Transfer program control to line 45.
if/goto 35 if i == z goto 80 Compare i and z for equality and transfer control to line 80 if the
condition is true; otherwise, continue execution with the next state-
ment.
end 99 end Terminate program execution.
Fig. 15.20 Simple commands.
110 rem determine and print the sum of two integers
215 rem
Fig. 15.21 Simple program that determines the sum of two integers (part 1 of 2).
468 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Using the sample programs of Fig. 15.21, Fig. 15.22 and Fig. 15.23 as your guide, write a Simple program to accomplish each
of the following:
a) Input three integers, determine their average and print the result.
b) Use a sentinel-controlled loop to input 10 integers and compute and print their sum.
c) Use a counter-controlled loop to input 7 integers, some positive and some negative, and compute and print their average.
d) Input a series of integers and determine and print the largest. The first integer input indicates how many numbers should
be processed.
e) Input 10 integers and print the smallest.
f) Calculate and print the sum of the even integers from 2 to 30.
g) Calculate and print the product of the odd integers from 1 to 9.
320 rem input the two integers
430 input a
540 input b
645 rem
750 rem add integers and store result in c
860 let c = a + b
965 rem
10 70 rem print the result
11 80 print c
12 90 rem terminate program execution
13 99 end
110 rem determine the larger of two integers
220 input s
330 input t
432 rem
535 rem test if s >= t
640 if s >= t goto 90
745 rem
850 rem t is greater than s, so print t
960 print t
10 70 goto 99
11 75 rem
12 80 rem s is greater than or equal to t, so print s
13 90 print s
14 99 end
Fig. 15.22 Simple program that finds the larger of two integers.
110 rem calculate the squares of several integers
220 input j
323 rem
425 rem test for sentinel value
530 if j == -9999 goto 99
633 rem
735 rem calculate square of j and assign result to k
840 let k = j * j
950 print k
10 53 rem
11 55 rem loop to get next j
12 60 goto 20
13 99 end
Fig. 15.23 Calculate the squares of several integers.
Fig. 15.21 Simple program that determines the sum of two integers (part 2 of 2).
Chapter 15 Data Structures Solutions 469
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.27 (Building A Compiler; Prerequisite: Complete Exercises 5.18, 5.19, 15.12, 15.13 and 15.26) Now that the Simple language
has been presented (Exercise 15.26), we discuss how to build a Simple compiler. First, we consider the process by which a Simple
program is converted to SML and executed by the Simpletron simulator (see Fig. 15.24). A file containing a Simple program is read
by the compiler and converted to SML code. The SML code is output to a file on disk, in which SML instructions appear one per
line. The SML file is then loaded into the Simpletron simulator, and the results are sent to a file on disk and to the screen. Note that
the Simpletron program developed in Exercise 5.19 took its input from the keyboard. It must be modified to read from a file so it
can run the programs produced by our compiler.
Fig. 15.24 Writing, compiling and executing a Simple language program.
The Simple compiler performs two passes of the Simple program to convert it to SML. The first pass constructs a symbol
table (object) in which every line number (object), variable name (object) and constant (object) of the Simple program is stored
with its type and corresponding location in the final SML code (the symbol table is discussed in detail below). The first pass also
produces the corresponding SML instruction object(s) for each of the Simple statements (object, etc.). As we will see, if the Simple
program contains statements that transfer control to a line later in the program, the first pass results in an SML program containing
some “unfinished” instructions. The second pass of the compiler locates and completes the unfinished instructions, and outputs the
SML program to a file.
First Pass
The compiler begins by reading one statement of the Simple program into memory. The line must be separated into its individual
tokens (i.e., “pieces” of a statement) for processing and compilation (standard library function strtok can be used to facilitate
this task). Recall that every statement begins with a line number followed by a command. As the compiler breaks a statement into
tokens, if the token is a line number, a variable or a constant, it is placed in the symbol table. A line number is placed in the symbol
table only if it is the first token in a statement. The symbolTable object is an array of tableEntry objects representing each
symbol in the program. There is no restriction on the number of symbols that can appear in the program. Therefore, the sym-
bolTable for a particular program could be large. Make the symbolTable a 100-element array for now. You can increase or
decrease its size once the program is working.
Each tableEntry object contains three members. Member symbol is an integer containing the ASCII representation of a
variable (remember that variable names are single characters), a line number or a constant. Member type is one of the following
characters indicating the symbol’s type: 'C' for constant, 'L' for line number and 'V' for variable. Member location con-
tains the Simpletron memory location (00 to 99) to which the symbol refers. Simpletron memory is an array of 100 integers in
which SML instructions and data are stored. For a line number, the location is the element in the Simpletron memory array at
which the SML instructions for the Simple statement begin. For a variable or constant, the location is the element in the Simpletron
memory array in which the variable or constant is stored. Variables and constants are allocated from the end of Simpletron’s mem-
ory backwards. The first variable or constant is stored in location at 99, the next in location at 98, etc.
The symbol table plays an integral part in converting Simple programs to SML. We learned in Chapter 5 that an SML instruc-
tion is a four-digit integer composed of two parts—the operation code and the operand. The operation code is determined by com-
mands in Simple. For example, the simple command input corresponds to SML operation code 10 (read), and the Simple
command print corresponds to SML operation code 11 (write). The operand is a memory location containing the data on which
the operation code performs its task (e.g., operation code 10 reads a value from the keyboard and stores it in the memory location
specified by the operand). The compiler searches symbolTable to determine the Simpletron memory location for each symbol
so the corresponding location can be used to complete the SML instructions.
The compilation of each Simple statement is based on its command. For example, after the line number in a rem statement is
inserted in the symbol table, the remainder of the statement is ignored by the compiler because a remark is for documentation pur-
poses only. The input, print, goto and end statements correspond to the SML read, write, branch (to a specific location) and
halt instructions. Statements containing these Simple commands are converted directly to SML (note that a goto statement may
SML file
Simple file compiler Simpletron
Simulator
output to
screen
output to
disk
470 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
contain an unresolved reference if the specified line number refers to a statement further into the Simple program file; this is some-
times called a forward reference).
When a goto statement is compiled with an unresolved reference, the SML instruction must be flagged to indicate that the
second pass of the compiler must complete the instruction. The flags are stored in 100-element array flags of type int in which
each element is initialized to -1. If the memory location to which a line number in the Simple program refers is not yet known
(i.e., it is not in the symbol table), the line number is stored in array flags in the element with the same subscript as the incom-
plete instruction. The operand of the incomplete instruction is set to 00 temporarily. For example, an unconditional branch instruc-
tion (making a forward reference) is left as +4000 until the second pass of the compiler. The second pass of the compiler is
described shortly.
Compilation of if/goto and let statements is more complicated than other statements—they are the only statements that
produce more than one SML instruction. For an if/goto, the compiler produces code to test the condition and to branch to
another line if necessary. The result of the branch could be an unresolved reference. Each of the relational and equality operators
can be simulated using SML’s branch zero and branch negative instructions (or a combination of both).
For a let statement, the compiler produces code to evaluate an arbitrarily complex arithmetic expression consisting of inte-
ger variables and/or constants. Expressions should separate each operand and operator with spaces. Exercises 15.12 and 15.13 pre-
sented the infix-to-postfix conversion algorithm and the postfix evaluation algorithm used by compilers to evaluate expressions.
Before proceeding with your compiler, you should complete each of these exercises. When a compiler encounters an expression, it
converts the expression from infix notation to postfix notation and then evaluates the postfix expression.
How is it that the compiler produces the machine language to evaluate an expression containing variables? The postfix evalu-
ation algorithm contains a “hook” where the compiler can generate SML instructions rather than actually evaluating the expres-
sion. To enable this “hook” in the compiler, the postfix evaluation algorithm must be modified to search the symbol table for each
symbol it encounters (and possibly insert it), determine the symbol’s corresponding memory location and push the memory loca-
tion onto the stack (instead of the symbol). When an operator is encountered in the postfix expression, the two memory locations at
the top of the stack are popped and machine language for effecting the operation is produced using the memory locations as oper-
ands. The result of each subexpression is stored in a temporary location in memory and pushed back onto the stack so the evalua-
tion of the postfix expression can continue. When postfix evaluation is complete, the memory location containing the result is the
only location left on the stack. This is popped and SML instructions are generated to assign the result to the variable at the left of
the let statement.
Second Pass
The second pass of the compiler performs two tasks: resolve any unresolved references and output the SML code to a file. Resolu-
tion of references occurs as follows:
a) Search the flags array for an unresolved reference (i.e., an element with a value other than -1).
b) Locate the object in array symbolTable, containing the symbol stored in the flags array (be sure that the type of
the symbol is 'L' for line number).
c) Insert the memory location from member location into the instruction with the unresolved reference (remember that
an instruction containing an unresolved reference has operand 00).
d) Repeat steps 1, 2 and 3 until the end of the flags array is reached.
After the resolution process is complete, the entire array containing the SML code is output to a disk file with one SML instruction
per line. This file can be read by the Simpletron for execution (after the simulator is modified to read its input from a file). Compil-
ing your first Simple program into an SML file and then executing that file should give you a real sense of personal accomplish-
ment.
A Complete Example
The following example illustrates a complete conversion of a Simple program to SML as it will be performed by the Simple com-
piler. Consider a Simple program that inputs an integer and sums the values from 1 to that integer. The program and the SML
instructions produced by the first pass of the Simple compiler are illustrated in Fig. 15.25. The symbol table constructed by the first
pass is shown in Fig. 15.26.
Simple program
SML location
and instruction Description
5 rem sum 1 to x none rem ignored
Fig. 15.25 SML instructions produced after the compiler’s first pass.
Chapter 15 Data Structures Solutions 471
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
.
10 input x 00 +1099 read x into location 99
15 rem check y == x none rem ignored
20 if y == x goto 60 01 +2098 load y (98) into accumulator
02 +3199 sub x (99) from accumulator
03 +4200 branch zero to unresolved location
25 rem increment y none rem ignored
30 let y = y + 1 04 +2098 load y into accumulator
05 +3097 add 1 (97) to accumulator
06 +2196 store in temporary location 96
07 +2096 load from temporary location 96
08 +2198 store accumulator in y
35 rem add y to total none rem ignored
40 let t = t + y 09 +2095 load t (95) into accumulator
10 +3098 add y to accumulator
11 +2194 store in temporary location 94
12 +2094 load from temporary location 94
13 +2195 store accumulator in t
45 rem loop y none rem ignored
50 goto 20 14 +4001 branch to location 01
55 rem output result none rem ignored
60 print t 15 +1195 output t to screen
99 end 16 +4300 terminate execution
Symbol Type Location
5L00
10 L00
'x' V99
15 L01
20 L01
'y' V98
25 L04
30 L04
1C97
35 L09
40 L09
't' V95
Fig. 15.26 Symbol table for program of Fig. 15.25 (part 1 of 2).
Simple program
SML location
and instruction Description
Fig. 15.25 SML instructions produced after the compiler’s first pass.
472 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Most Simple statements convert directly to single SML instructions. The exceptions in this program are remarks, the if/
goto statement in line 20 and the let statements. Remarks do not translate into machine language. However, the line number for
a remark is placed in the symbol table in case the line number is referenced in a goto statement or an if/goto statement. Line
20 of the program specifies that if the condition y == x is true, program control is transferred to line 60. Because line 60 appears
later in the program, the first pass of the compiler has not as yet placed 60 in the symbol table (statement line numbers are placed
in the symbol table only when they appear as the first token in a statement). Therefore, it is not possible at this time to determine
the operand of the SML branch zero instruction at location 03 in the array of SML instructions. The compiler places 60 in loca-
tion 03 of the flags array to indicate that the second pass completes this instruction.
We must keep track of the next instruction location in the SML array because there is not a one-to-one correspondence
between Simple statements and SML instructions. For example, the if/goto statement of line 20 compiles into three SML
instructions. Each time an instruction is produced, we must increment the instruction counter to the next location in the SML array.
Note that the size of Simpletron’s memory could present a problem for Simple programs with many statements, variables and con-
stants. It is conceivable that the compiler will run out of memory. To test for this case, your program should contain a data counter
to keep track of the location at which the next variable or constant will be stored in the SML array. If the value of the instruction
counter is larger than the value of the data counter, the SML array is full. In this case, the compilation process should terminate and
the compiler should print an error message indicating that it ran out of memory during compilation. This serves to emphasize that
although the programmer is freed from the burdens of managing memory by the compiler, the compiler itself must carefully deter-
mine the placement of instructions and data in memory, and must check for such errors as memory being exhausted during the
compilation process.
A Step-by-Step View of the Compilation Process
Let us now walk through the compilation process for the Simple program in Fig. 15.25. The compiler reads the first line of the pro-
gram
5 rem sum 1 to x
into memory. The first token in the statement (the line number) is determined using strtok (see Chapters 5 and 16 for a discussion
of C++’s string manipulation functions). The token returned by strtok is converted to an integer using atoi so the symbol 5
can be located in the symbol table. If the symbol is not found, it is inserted in the symbol table. Since we are at the beginning of the
program and this is the first line, no symbols are in the table yet. So, 5 is inserted into the symbol table as type L (line number) and
assigned the first location in SML array ( 00). Although this line is a remark, a space in the symbol table is still allocated for the line
number (in case it is referenced by a goto or an if/goto). No SML instruction is generated for a rem statement, so the instruction
counter is not incremented.
The statement
10 input x
is tokenized next. The line number 10 is placed in the symbol table as type L and assigned the first location in the SML array (00
because a remark began the program so the instruction counter is currently 00). The command input indicates that the next token
is a variable (only a variable can appear in an input statement). Because input corresponds directly to an SML operation code,
the compiler has to determine the location of x in the SML array. Symbol x is not found in the symbol table. So, it is inserted into
the symbol table as the ASCII representation of x, given type V, and assigned location 99 in the SML array (data storage begins at
99 and is allocated backwards). SML code can now be generated for this statement. Operation code 10 (the SML read operation
code) is multiplied by 100, and the location of x (as determined in the symbol table) is added to complete the instruction. The
instruction is then stored in the SML array at location 00. The instruction counter is incremented by 1 because a single SML
45 L14
50 L14
55 L15
60 L15
99 L16
Symbol Type Location
Fig. 15.26 Symbol table for program of Fig. 15.25 (part 2 of 2).
Chapter 15 Data Structures Solutions 473
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
instruction was produced.
The statement
15 rem check y == x
is tokenized next. The symbol table is searched for line number 15 (which is not found). The line number is inserted as type L and
assigned the next location in the array, 01 (remember that rem statements do not produce code, so the instruction counter is not
incremented).
The statement
20 if y == x goto 60
is tokenized next. Line number 20 is inserted in the symbol table and given type L with the next location in the SML array 01. The
command if indicates that a condition is to be evaluated. The variable y is not found in the symbol table, so it is inserted and given
the type V and the SML location 98. Next, SML instructions are generated to evaluate the condition. Since there is no direct equiv-
alent in SML for the if/goto, it must be simulated by performing a calculation using x and y and branching based on the result.
If y is equal to x, the result of subtracting x from y is zero, so the branch zero instruction can be used with the result of the cal-
culation to simulate the if/goto statement. The first step requires that y be loaded (from SML location 98) into the accumulator.
This produces the instruction 01 +2098. Next, x is subtracted from the accumulator. This produces the instruction 02 +3199. The
value in the accumulator may be zero, positive or negative. Since the operator is ==, we want to branch zero. First, the symbol table
is searched for the branch location (60 in this case), which is not found. So, 60 is placed in the flags array at location 03, and
the instruction 03 +4200 is generated (we cannot add the branch location, because we have not assigned a location to line 60 in
the SML array yet). The instruction counter is incremented to 04.
The compiler proceeds to the statement
25 rem increment y
The line number 25 is inserted in the symbol table as type L and assigned SML location 04. The instruction counter is not incre-
mented.
When the statement
30 let y = y + 1
is tokenized, the line number 30 is inserted in the symbol table as type L and assigned SML location 04. Command let indicates
that the line is an assignment statement. First, all the symbols on the line are inserted in the symbol table (if they are not already
there). The integer 1 is added to the symbol table as type C and assigned SML location 97. Next, the right side of the assignment
is converted from infix to postfix notation. Then the postfix expression (y 1 +) is evaluated. Symbol y is located in the symbol
table and its corresponding memory location is pushed onto the stack. Symbol 1 is also located in the symbol table and its corre-
sponding memory location is pushed onto the stack. When the operator + is encountered, the postfix evaluator pops the stack into
the right operand of the operator, pops the stack again into the left operand of the operator and then produces the SML instructions
04 +2098 (load y)
05 +3097 (add 1)
The result of the expression is stored in a temporary location in memory (96) with instruction
06 +2196 (store temporary)
and the temporary location is pushed on the stack. Now that the expression has been evaluated, the result must be stored in y (i.e.,
the variable on the left side of =). So, the temporary location is loaded into the accumulator and the accumulator is stored in y with
the instructions
07 +2096 (load temporary)
08 +2198 (store y)
The reader will immediately notice that SML instructions appear to be redundant. We will discuss this issue shortly.
When the statement
35 rem add y to total
474 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
is tokenized, line number 35 is inserted in the symbol table as type L and assigned location 09.
The statement
40 let t = t + y
is similar to line 30. The variable t is inserted in the symbol table as type V and assigned SML location 95. The instructions fol-
low the same logic and format as line 30, and the instructions 09 +2095, 10 +3098, 11 +2194, 12 +2094 and 13 +2195
are generated. Note that the result of t + y is assigned to temporary location 94 before being assigned to t (95). Once again, the
reader will note that the instructions in memory locations 11 and 12 appear to be redundant. Again, we will discuss this shortly.
The statement
45 rem loop y
is a remark, so line 45 is added to the symbol table as type L and assigned SML location 14.
The statement
50 goto 20
transfers control to line 20. Line number 50 is inserted in the symbol table as type L and assigned SML location 14. The equiva-
lent of goto in SML is the unconditional branch (40) instruction that transfers control to a specific SML location. The compiler
searches the symbol table for line 20 and finds that it corresponds to SML location 01. The operation code (40) is multiplied by
100, and location 01 is added to it to produce the instruction 14 +4001.
The statement
55 rem output result
is a remark, so line 55 is inserted in the symbol table as type L and assigned SML location 15.
The statement
60 print t
is an output statement. Line number 60 is inserted in the symbol table as type L and assigned SML location 15. The equivalent of
print in SML is operation code 11 (write). The location of t is determined from the symbol table and added to the result of the
operation code multiplied by 100.
The statement
99 end
is the final line of the program. Line number 99 is stored in the symbol table as type L and assigned SML location 16. The end
command produces the SML instruction +4300 (43 is halt in SML), which is written as the final instruction in the SML memory
array.
This completes the first pass of the compiler. We now consider the second pass. The flags array is searched for values other
than -1. Location 03 contains 60, so the compiler knows that instruction 03 is incomplete. The compiler completes the instruc-
tion by searching the symbol table for 60, determining its location and adding the location to the incomplete instruction. In this
case, the search determines that line 60 corresponds to SML location 15, so the completed instruction 03 +4215 is produced,
replacing 03 +4200. The Simple program has now been compiled successfully.
To build the compiler, you will have to perform each of the following tasks:
a) Modify the Simpletron simulator program you wrote in Exercise 5.19 to take its input from a file specified by the user
(see Chapter 14). The simulator should output its results to a disk file in the same format as the screen output. Convert
the simulator to be an object-oriented program. In particular, make each part of the hardware an object. Arrange the
instruction types into a class hierarchy using inheritance. Then execute the program polymorphically by telling each
instruction to execute itself with an executeInstruction message.
b) Modify the infix-to-postfix conversion algorithm of Exercise 15.12 to process multi-digit integer operands and single-
letter variable name operands. (Hint: Standard library function strtok can be used to locate each constant and vari-
able in an expression, and constants can be converted from strings to integers using standard library function atoi.)
(Note: The data representation of the postfix expression must be altered to support variable names and integer con-
stants.)
Chapter 15 Data Structures Solutions 475
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
c) Modify the postfix evaluation algorithm to process multidigit integer operands and variable name operands. Also, the
algorithm should now implement the “hook” discussed above so that SML instructions are produced rather than directly
evaluating the expression. (Hint: Standard library function strtok can be used to locate each constant and variable in
an expression, and constants can be converted from strings to integers using standard library function atoi.) (Note:
The data representation of the postfix expression must be altered to support variable names and integer constants.)
d) Build the compiler. Incorporate parts (b) and (c) for evaluating expressions in let statements. Your program should
contain a function that performs the first pass of the compiler and a function that performs the second pass of the com-
piler. Both functions can call other functions to accomplish their tasks. Make your compiler as object oriented as pos-
sible.
1// STACKND.H
2// Definition of template class StackNode
3#ifndef STACKND_H
4#define STACKND_H
5
6template < class T > class Stack;
7
8template < class T >
9class StackNode {
10 friend class Stack< T >;
11 public:
12 StackNode( const T & = 0, StackNode * = 0 );
13 T getData() const;
14 private:
15 T data;
16 StackNode *nextPtr;
17 };
18
19 // Member function definitions for class StackNode
20 template < class T >
21 StackNode< T >::StackNode( const T &d, StackNode< T > *ptr )
22 {
23 data = d;
24 nextPtr = ptr;
25 }
26
27 template < class T >
28 T StackNode< T >::getData() const { return data; }
29
30 #endif
31 // STACK.H
32 // Definition of class Stack
33 #ifndef STACK_H
34 #define STACK_H
35
36 #include <iostream>
37 using std::cout;
38
39 #include <cassert>
40 #include "stacknd.h"
41
42 template < class T >
43 class Stack {
44 public:
45 Stack(); // default constructor
46 ~Stack(); // destructor
47 void push( T & ); // insert item in stack
476 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
48 T pop(); // remove item from stack
49 bool isEmpty() const; // is the stack empty?
50 T stackTop() const; // return the top element of stack
51 void print() const; // output the stack
52 private:
53 StackNode< T > *topPtr; // pointer to fist StackNode
54 };
55
56 // Member function definitions for class Stack
57 template < class T >
58 Stack< T >::Stack() { topPtr = 0; }
59
60 template < class T >
61 Stack< T >::~Stack()
62 {
63 StackNode< T > *tempPtr, *currentPtr = topPtr;
64
65 while ( currentPtr != 0 ) {
66 tempPtr = currentPtr;
67 currentPtr = currentPtr -> nextPtr;
68 delete tempPtr;
69 }
70 }
71
72 template < class T >
73 void Stack< T >::push( T &d )
74 {
75 StackNode< T > *newPtr = new StackNode< T >( d, topPtr );
76
77 assert( newPtr != 0 ); // was memory allocated?
78 topPtr = newPtr;
79 }
80
81 template < class T >
82 T Stack< T >::pop()
83 {
84 assert( !isEmpty() );
85
86 StackNode< T > *tempPtr = topPtr;
87
88 topPtr = topPtr -> nextPtr;
89 T poppedValue = tempPtr -> data;
90 delete tempPtr;
91 return poppedValue;
92 }
93
94 template < class T >
95 bool Stack< T >::isEmpty() const { return topPtr == 0; }
96
97 template < class T >
98 T Stack< T >::stackTop() const
99 { return !isEmpty() ? topPtr -> data : 0; }
100
101 template < class T >
102 void Stack< T >::print() const
103 {
104 StackNode< T > *currentPtr = topPtr;
105
106 if ( isEmpty() ) // Stack is empty
107 cout << "Stack is empty\n";
108 else { // Stack is not empty
109 cout << "The stack is:\n";
Chapter 15 Data Structures Solutions 477
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
110
111 while ( currentPtr != 0 ) {
112 cout << currentPtr -> data << ' ';
113 currentPtr = currentPtr -> nextPtr;
114 }
115
116 cout << '\n';
117 }
118 }
119
120 #endif
121 // compiler.h
122
123 const int MAXIMUM = 81; // maximum length for lines
124 const int SYMBOLTABLESIZE = 100; // maximum size of symbol table
125 const int MEMORYSIZE = 100; // maximum Simpletron memory
126
127 // Definition of structure for symbol table entries
128 struct TableEntry {
129 int location; // SML memory location 00 to 99
130 char type; // 'C' = constant, 'V' = variable,
131 int symbol; // or 'L' = line number
132 };
133
134 // Function prototypes for compiler functions
135 int checkSymbolTable( TableEntry *, int, char );
136 int checkOperand( TableEntry *, char *, int *, int *, int * );
137 void addToSymbolTable( char, int, int, TableEntry *, int );
138 void addLineToFlags( int, int, int *, int *, const int * );
139 void compile( ifstream &, char * );
140 void printOutput( const int [], char * );
141 void lineNumber( char *, TableEntry *, int, int );
142 void initArrays( int *, int *, TableEntry * );
143 void firstPass( int *, int *, TableEntry *, ifstream & );
144 void secondPass( int *, int *, TableEntry * );
145 void separateToken( char *, int *, int *, TableEntry *, int *, int * );
146 void keyWord( char *, int *, int *, TableEntry *, int *, int * );
147 void keyLet( char *, int *, TableEntry *, int *, int * );
148 void keyInput( char *, int *, TableEntry *, int *, int * );
149 void keyPrint( char *, int *, TableEntry *, int *, int * );
150 void keyGoto( char *, int *, int *, TableEntry *, int * );
151 void keyIfGoto( char *, int *, int *, TableEntry *, int *, int * );
152 void evaluateExpression( int, int, char *, int *, TableEntry *,
153 int *, int *, char * );
154 int createLetSML( int, int, int *, int *, int *, char );
155 void infixToPostfix( char *, char *, int, TableEntry *, int *, int *, int * );
156 void evaluatePostfix( char *, int *, int *, int *, int, TableEntry * );
157 bool isOperator( char );
158 bool precedence( char, char );
159
160 // Simpletron Machine Language (SML) Operation Codes
161 enum SMLOperationCodes { READ = 10, WRITE = 11, LOAD = 20, STORE = 21, ADD = 30,
162 SUBTRACT = 31, DIVIDE = 32, MULTIPLY = 33, BRANCH = 40,
163 BRANCHNEG = 41, BRANCHZERO = 42, HALT = 43 };
164 // Exercise 15.27 Solution
165 // Non-optimized version.
166 #include <iostream>
167
478 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
168 using std::cout;
169 using std::cin;
170 using std::ios;
171 using std::cerr;
172
173 #include <iomanip>
174
175 using std::setw;
176
177 #include <fstream>
178
179 using std::ifstream;
180 using std::ofstream;
181
182 #include <cstring>
183 #include <cctype>
184 #include <cstdlib>
185 #include "stack.h"
186
187 #include "compiler.h"
188
189 int main()
190 {
191 char inFileName[ 15 ] = "", outFileName[ 15 ] = "";
192 int last = 0;
193
194 cout << "Enter Simple file to be compiled: ";
195 cin >> setw( 15 ) >> inFileName;
196
197 while ( isalnum( inFileName[ last ] ) != 0 ) {
198 outFileName[ last ] = inFileName[ last ];
199 last++; // note the last occurance
200 }
201
202 outFileName[ last ] = '\0'; // append a NULL character
203 strcat( outFileName, ".sml" ); // add .sml to name
204
205 ifstream inFile( inFileName, ios::in );
206
207 if ( inFile )
208 compile( inFile, outFileName );
209 else
210 cerr << "File not opened. Program execution terminating.\n";
211
212 return 0;
213 }
214
215 // compile function calls the first pass and the second pass
216 void compile( ifstream &input, char *outFileName )
217 {
218 TableEntry symbolTable[ SYMBOLTABLESIZE ]; // symbol table
219 int flags[ MEMORYSIZE ]; // array for forward references
220 int machineArray[ MEMORYSIZE ]; // array for SML instructions
221
222 initArrays( flags, machineArray, symbolTable );
223
224 firstPass( flags, machineArray, symbolTable, input );
225 secondPass( flags, machineArray, symbolTable );
226
227 printOutput( machineArray, outFileName );
228 }
229
Chapter 15 Data Structures Solutions 479
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
230 // firstPass constructs the symbol table, creates SML, and flags unresolved
231 // references for goto and if/goto statements.
232 void firstPass( int flags[], int machineArray[], TableEntry symbolTable[],
233 ifstream &input )
234 {
235 char array[ MAXIMUM ]; // array to copy a Simple line
236 int n = MAXIMUM; // required for fgets()
237 int dataCounter = MEMORYSIZE - 1; // 1st data location in machineArray
238 int instCounter = 0; // 1st instruction location in machineArray
239
240 input.getline( array, n );
241
242 while ( !input.eof() ) {
243 separateToken( array, flags, machineArray, symbolTable, &dataCounter,
244 &instCounter );
245 input.getline( array, n );
246 }
247 }
248
249 // Separate Tokens tokenizes a Simple statement, process the line number,
250 // and passes the next token to keyWord for processing.
251 void separateToken( char array[], int flags[], int machineArray[],
252 TableEntry symbolTable[], int *dataCounterPtr,
253 int *instCounterPtr )
254 {
255 char *tokenPtr = strtok( array, " " ); // tokenize line
256 lineNumber( tokenPtr, symbolTable, *instCounterPtr, *dataCounterPtr );
257 tokenPtr = strtok( 0, " \n" ); // get next token
258 keyWord( tokenPtr, flags, machineArray, symbolTable, dataCounterPtr,
259 instCounterPtr );
260 }
261
262 // checkSymbolTable searches the symbol table and returns
263 // the symbols SML location or a -1 if not found.
264 int checkSymbolTable( TableEntry symbolTable[], int symbol, char type )
265 {
266 for ( int loop = 0; loop < SYMBOLTABLESIZE; ++loop )
267 if ( ( symbol == symbolTable[ loop ].symbol ) &&
268 ( type == symbolTable[ loop ].type ) )
269 return symbolTable[ loop ].location; // return SML location
270
271 return -1; // symbol not found
272 }
273
274 // lineNumber processes line numbers
275 void lineNumber( char *tokenPtr, TableEntry symbolTable[],
276 int instCounter, int dataCounter )
277 {
278 const char type = 'L';
279 int symbol;
280
281 if ( isdigit( tokenPtr[ 0 ] ) ) {
282 symbol = atoi( tokenPtr );
283
284 if ( -1 == checkSymbolTable( symbolTable, symbol, type ) )
285 addToSymbolTable( type, symbol, dataCounter, symbolTable,
286 instCounter );
287 }
288 }
289
290 // keyWord determines the key word type and calls the appropriate function
291 void keyWord( char *tokenPtr, int flags[], int machineArray[],
480 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
292 TableEntry symbolTable[], int *dataCounterPtr,
293 int *instCounterPtr )
294 {
295 if ( strcmp( tokenPtr, "rem" ) == 0 )
296 ; // no instructions are generated by comments
297 else if ( strcmp( tokenPtr, "input" ) == 0 ) {
298 tokenPtr = strtok( 0, " " ); // assign pointer to next token
299 keyInput( tokenPtr, machineArray, symbolTable, dataCounterPtr,
300 instCounterPtr );
301 }
302 else if ( strcmp( tokenPtr, "print" ) == 0 ) {
303 tokenPtr = strtok( 0, " " ); // assign pointer to next token
304 keyPrint( tokenPtr, machineArray, symbolTable, dataCounterPtr,
305 instCounterPtr );
306 }
307 else if ( strcmp( tokenPtr, "goto" ) == 0 ) {
308 tokenPtr = strtok( 0, " " ); // assign pointer to next token
309 keyGoto( tokenPtr, flags, machineArray, symbolTable, instCounterPtr );
310 }
311 else if ( strcmp( tokenPtr, "if" ) == 0 ) {
312 tokenPtr = strtok( 0, " " ); // assign pointer to next token
313 keyIfGoto( tokenPtr, flags, machineArray, symbolTable, dataCounterPtr,
314 instCounterPtr );
315 }
316 else if ( strcmp( tokenPtr, "end" ) == 0 ) {
317 machineArray[ *instCounterPtr ] = HALT * 100;
318 ++( *instCounterPtr );
319 tokenPtr = 0; // assign tokenPtr to 0
320 }
321 else if ( strcmp( tokenPtr, "let" ) == 0 ) {
322 tokenPtr = strtok( 0, " " ); // assign pointer to next token
323 keyLet( tokenPtr, machineArray, symbolTable, dataCounterPtr,
324 instCounterPtr );
325 }
326 }
327
328 // keyInput process input keywords
329 void keyInput( char *tokenPtr, int machineArray[], TableEntry symbolTable[],
330 int *dataCounterPtr, int *instCounterPtr )
331 {
332 const char type = 'V';
333
334 machineArray[ *instCounterPtr ] = READ * 100;
335 int symbol = tokenPtr[ 0 ];
336 int tableTest = checkSymbolTable( symbolTable, symbol, type );
337
338 if ( -1 == tableTest ) {
339 addToSymbolTable( type, symbol, *dataCounterPtr, symbolTable,
340 *instCounterPtr );
341 machineArray[ *instCounterPtr ] += *dataCounterPtr;
342 --( *dataCounterPtr );
343 }
344 else
345 machineArray[ *instCounterPtr ] += tableTest;
346
347 ++( *instCounterPtr );
348 }
349
350 // keyPrint process print keywords
351 void keyPrint( char *tokenPtr, int machineArray[], TableEntry symbolTable[],
352 int *dataCounterPtr, int *instCounterPtr )
353 {
Chapter 15 Data Structures Solutions 481
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
354 const char type = 'V';
355
356 machineArray[ *instCounterPtr ] = WRITE * 100;
357 int symbol = tokenPtr[ 0 ];
358 int tableTest = checkSymbolTable( symbolTable, symbol, type );
359
360 if ( -1 == tableTest ) {
361 addToSymbolTable( type, symbol, *dataCounterPtr, symbolTable,
362 *instCounterPtr );
363 machineArray[*instCounterPtr] += *dataCounterPtr;
364 --( *dataCounterPtr );
365 }
366 else
367 machineArray[ *instCounterPtr ] += tableTest;
368
369 ++( *instCounterPtr );
370 }
371
372 // keyGoto process goto keywords
373 void keyGoto( char *tokenPtr, int flags[], int machineArray[],
374 TableEntry symbolTable[], int *instCounterPtr )
375 {
376 const char type = 'L';
377
378 machineArray[*instCounterPtr] = BRANCH * 100;
379 int symbol = atoi( tokenPtr );
380 int tableTest = checkSymbolTable( symbolTable, symbol, type );
381 addLineToFlags( tableTest, symbol, flags, machineArray, instCounterPtr );
382 ++( *instCounterPtr );
383 }
384
385 // keyIfGoto process if/goto commands
386 void keyIfGoto( char *tokenPtr, int flags[], int machineArray[],
387 TableEntry symbolTable[], int *dataCounterPtr,
388 int *instCounterPtr )
389 {
390 int operand1Loc = checkOperand( symbolTable, tokenPtr, dataCounterPtr,
391 instCounterPtr, machineArray );
392
393 char *operatorPtr = strtok( 0, " " ); // get the operator
394
395 tokenPtr = strtok( 0, " " ); // get the right operand of comparison operator
396
397 int operand2Loc = checkOperand( symbolTable, tokenPtr, dataCounterPtr,
398 instCounterPtr, machineArray );
399
400 tokenPtr = strtok( 0, " " ); // read in the goto keyword
401
402 char *gotoLinePtr = strtok( 0, " " ); // read in the goto line number
403
404 evaluateExpression( operand1Loc, operand2Loc, operatorPtr, machineArray,
405 symbolTable, instCounterPtr, flags, gotoLinePtr );
406 }
407
408 // checkOperand ensures that the operands of an if/goto statement are
409 // in the symbol table.
410 int checkOperand( TableEntry symbolTable[], char *symPtr, int *dataCounterPtr,
411 int *instCounterPtr, int machineArray[] )
412 {
413 char type;
414 int tableTest, operand, temp;
415
482 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
416 if ( isalpha( symPtr[ 0 ] ) ) {
417 type = 'V';
418 operand = symPtr[ 0 ];
419 tableTest = checkSymbolTable( symbolTable, operand, type );
420
421 if ( tableTest == -1 ) {
422 addToSymbolTable( type, operand, *dataCounterPtr, symbolTable,
423 *instCounterPtr );
424 temp = *dataCounterPtr;
425 --( *dataCounterPtr );
426 return temp;
427 }
428 else
429 return tableTest;
430 }
431 // if the symbol is a digit or a signed digit
432 else if ( isdigit( symPtr[ 0 ] ) ||
433 ( ( symPtr[ 0 ] == '-' || symPtr[ 0 ] == '+' ) &&
434 isdigit( symPtr[ 1 ] ) != 0 ) ) {
435 type = 'C';
436 operand = atoi( symPtr );
437 tableTest = checkSymbolTable( symbolTable, operand, type );
438
439 if ( tableTest == -1 ) {
440 addToSymbolTable( type, operand, *dataCounterPtr, symbolTable,
441 *instCounterPtr );
442 machineArray[ *dataCounterPtr ] = operand;
443 temp = *dataCounterPtr;
444 --( *dataCounterPtr );
445 return temp ;
446 }
447 else
448 return tableTest;
449 }
450
451 return 0; // default return for compilation purposes
452 }
453
454 // evaluateExpression creates SML for conditional operators
455 void evaluateExpression( int operator1Loc, int operator2Loc, char *operandPtr,
456 int machineArray[], TableEntry symbolTable[],
457 int *instCounterPtr, int flags[], char *gotoLinePtr )
458 {
459 const char type = 'L';
460 int tableTest, symbol;
461
462 if ( strcmp( operandPtr, "==" ) == 0 ) {
463 machineArray[ *instCounterPtr ] = LOAD * 100;
464 machineArray[ *instCounterPtr ] += operator1Loc;
465 ++( *instCounterPtr );
466
467 machineArray[ *instCounterPtr ] = SUBTRACT * 100;
468 machineArray[ *instCounterPtr ] += operator2Loc;
469 ++( *instCounterPtr );
470
471 machineArray[ *instCounterPtr ] = BRANCHZERO * 100;
472
473 symbol = atoi( gotoLinePtr );
474 tableTest = checkSymbolTable( symbolTable, symbol, type );
475 addLineToFlags( tableTest, symbol, flags, machineArray, instCounterPtr );
476 ++( *instCounterPtr );
477 }
Chapter 15 Data Structures Solutions 483
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
478 else if ( strcmp( operandPtr, "!=" ) == 0 ) {
479 machineArray[ *instCounterPtr ] = LOAD * 100;
480 machineArray[ *instCounterPtr ] += operator2Loc;
481 ++( *instCounterPtr );
482
483 machineArray[ *instCounterPtr ] = SUBTRACT * 100;
484 machineArray[ *instCounterPtr ] += operator1Loc;
485 ++( *instCounterPtr );
486
487 machineArray[ *instCounterPtr ] = BRANCHNEG * 100;
488
489 symbol = atoi( gotoLinePtr );
490 tableTest = checkSymbolTable( symbolTable, symbol, type );
491
492 addLineToFlags( tableTest, symbol, flags, machineArray, instCounterPtr );
493
494 ++( *instCounterPtr );
495
496 machineArray[ *instCounterPtr ] = LOAD * 100;
497 machineArray[ *instCounterPtr ] += operator1Loc;
498 ++( *instCounterPtr );
499
500 machineArray[ *instCounterPtr ] = SUBTRACT * 100;
501 machineArray[ *instCounterPtr ] += operator2Loc;
502 ++( *instCounterPtr );
503
504 machineArray[ *instCounterPtr ] = BRANCHNEG * 100;
505
506 symbol = atoi( gotoLinePtr );
507 tableTest = checkSymbolTable( symbolTable, symbol, type );
508
509 addLineToFlags( tableTest, symbol, flags, machineArray, instCounterPtr );
510
511 ++( *instCounterPtr );
512 }
513 else if ( strcmp( operandPtr, ">" ) == 0 ) {
514 machineArray[ *instCounterPtr ] = LOAD * 100;
515 machineArray[ *instCounterPtr ] += operator2Loc;
516 ++( *instCounterPtr );
517
518 machineArray[ *instCounterPtr ] = SUBTRACT * 100;
519 machineArray[ *instCounterPtr ] += operator1Loc;
520 ++( *instCounterPtr );
521
522 machineArray[ *instCounterPtr ] = BRANCHNEG * 100;
523
524 symbol = atoi( gotoLinePtr );
525 tableTest = checkSymbolTable( symbolTable, symbol, type );
526
527 addLineToFlags( tableTest, symbol, flags, machineArray, instCounterPtr );
528 ++( *instCounterPtr );
529 }
530 else if ( strcmp( operandPtr, "<" ) == 0 ) {
531 machineArray[ *instCounterPtr ] = LOAD * 100;
532 machineArray[ *instCounterPtr ] += operator1Loc;
533 ++( *instCounterPtr );
534
535 machineArray[ *instCounterPtr ] = SUBTRACT * 100;
536 machineArray[ *instCounterPtr ] += operator2Loc;
537 ++( *instCounterPtr );
538
539 machineArray[ *instCounterPtr ] = BRANCHNEG * 100;
484 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
540
541 symbol = atoi( gotoLinePtr );
542 tableTest = checkSymbolTable( symbolTable, symbol, type );
543
544 addLineToFlags( tableTest, symbol, flags, machineArray, instCounterPtr );
545 ++( *instCounterPtr );
546 }
547 else if ( strcmp( operandPtr, ">=" ) == 0 ) {
548 machineArray[ *instCounterPtr ] = LOAD * 100;
549 machineArray[ *instCounterPtr ] += operator2Loc;
550 ++( *instCounterPtr );
551
552 machineArray[ *instCounterPtr ] = SUBTRACT * 100;
553 machineArray[ *instCounterPtr ] += operator1Loc;
554 ++( *instCounterPtr );
555
556 machineArray[ *instCounterPtr ] = BRANCHNEG * 100;
557
558 symbol = atoi( gotoLinePtr );
559 tableTest = checkSymbolTable( symbolTable, symbol, type );
560
561 addLineToFlags( tableTest, symbol, flags, machineArray, instCounterPtr );
562 ++( *instCounterPtr );
563
564 machineArray[ *instCounterPtr ] = BRANCHZERO * 100;
565
566 addLineToFlags( tableTest, symbol, flags, machineArray, instCounterPtr );
567 ++( *instCounterPtr );
568 }
569 else if ( strcmp( operandPtr, "<=" ) == 0 ) {
570 machineArray[ *instCounterPtr ] = LOAD * 100;
571 machineArray[ *instCounterPtr ] += operator1Loc;
572 ++( *instCounterPtr );
573
574 machineArray[ *instCounterPtr ] = SUBTRACT * 100;
575 machineArray[ *instCounterPtr ] += operator2Loc;
576 ++( *instCounterPtr );
577
578 machineArray[ *instCounterPtr ] = BRANCHNEG * 100;
579
580 symbol = atoi( gotoLinePtr );
581 tableTest = checkSymbolTable( symbolTable, symbol, type );
582
583 addLineToFlags( tableTest, symbol, flags, machineArray, instCounterPtr );
584 ++( *instCounterPtr );
585
586 machineArray[ *instCounterPtr ] = BRANCHZERO * 100;
587
588 addLineToFlags( tableTest, symbol, flags, machineArray, instCounterPtr );
589 ++( *instCounterPtr );
590 }
591 }
592
593 // secondPass resolves incomplete SML instructions for forward references
594 void secondPass( int flags[], int machineArray[], TableEntry symbolTable[] )
595 {
596 const char type = 'L';
597
598 for ( int loop = 0; loop < MEMORYSIZE; ++loop ) {
599 if ( flags[ loop ] != -1 ) {
600 int symbol = flags[ loop ];
601 int flagLocation = checkSymbolTable( symbolTable, symbol, type );
Chapter 15 Data Structures Solutions 485
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
602 machineArray[ loop ] += flagLocation;
603 }
604 }
605 }
606
607 // keyLet processes the keyword let
608 void keyLet( char *tokenPtr, int machineArray[], TableEntry symbolTable[],
609 int *dataCounterPtr, int *instCounterPtr )
610 {
611 const char type = 'V';
612 char infixArray[ MAXIMUM ] = "", postfixArray[ MAXIMUM ] = "";
613 int tableTest, symbol, location;
614 static int subscript = 0;
615
616 symbol = tokenPtr[ 0 ];
617 tableTest = checkSymbolTable( symbolTable, symbol, type );
618
619 if ( -1 == tableTest ) {
620 addToSymbolTable( type, symbol, *dataCounterPtr, symbolTable,
621 *instCounterPtr );
622 location = *dataCounterPtr;
623 --( *dataCounterPtr );
624 }
625 else
626 location = tableTest;
627
628 tokenPtr = strtok( 0, " " ); // grab equal sign
629 tokenPtr = strtok( 0, " " ); // get next token
630
631 while ( tokenPtr != 0 ) {
632 checkOperand( symbolTable, tokenPtr, dataCounterPtr,
633 instCounterPtr, machineArray );
634 infixArray[ subscript ] = tokenPtr[ 0 ];
635 ++subscript;
636 tokenPtr = strtok( 0, " " ); // get next token
637 }
638
639 infixArray[ subscript ] = '\0';
640
641 infixToPostfix( infixArray, postfixArray, location, symbolTable,
642 instCounterPtr, dataCounterPtr, machineArray );
643
644 subscript = 0; // reset static subscript when done
645 }
646
647 void addToSymbolTable( char type, int symbol, int dataCounter,
648 TableEntry symbolTable[], int instCounter )
649 {
650 static int symbolCounter = 0;
651
652 symbolTable[ symbolCounter ].type = type;
653 symbolTable[ symbolCounter ].symbol = symbol;
654
655 if ( type == 'V' || type == 'C' )
656 symbolTable[ symbolCounter ].location = dataCounter;
657 else
658 symbolTable[ symbolCounter ].location = instCounter;
659
660 ++symbolCounter;
661 }
662
663 void addLineToFlags( int tableTest, int symbol, int flags[],
486 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
664 int machineArray[], const int *instCounterPtr )
665 {
666 if ( tableTest == -1 )
667 flags[ *instCounterPtr ] = symbol;
668 else
669 machineArray[ *instCounterPtr ] += tableTest;
670 }
671
672 void printOutput( const int machineArray[], char *outFileName )
673 {
674 ofstream output( outFileName, ios::out );
675
676 if ( !output )
677 cerr << "File was not opened.\n";
678 else // output every memory cell
679 for ( int loop = 0; loop <= MEMORYSIZE - 1; ++loop )
680 output << machineArray[ loop ] << '\n';
681 }
682
683 void initArrays( int flags[], int machineArray[], TableEntry symbolTable[] )
684 {
685 TableEntry initEntry = { 0, 0, -1 };
686
687 for ( int loop = 0; loop < MEMORYSIZE; ++loop ) {
688 flags[ loop ] = -1;
689 machineArray[ loop ] = 0;
690 symbolTable[ loop ] = initEntry;
691 }
692 }
693
694 //////////////////////////////////////////////////////////////////////////////
695 // INFIX TO POSTFIX CONVERSION and POSTFIX EVALUATION FOR THE LET STATEMENT //
696 //////////////////////////////////////////////////////////////////////////////
697
698 // infixToPostfix converts an infix expression to a postfix expression
699 void infixToPostfix( char infix[], char postfix[], int getsVariable,
700 TableEntry symbolTable[], int *instCounterPtr,
701 int *dataCounterPtr, int machineArray[] )
702 {
703 Stack< int > intStack;
704 int infixCount, postfixCount, popValue;
705 bool higher;
706 int leftParen = '('; // made int
707
708 // push a left paren onto the stack and add a right paren to infix
709 intStack.push( leftParen );
710 strcat( infix, ")" );
711
712 // convert the infix expression to postfix
713 for ( infixCount = 0, postfixCount = 0; intStack.stackTop();
714 ++infixCount ) {
715
716 if ( isalnum( infix[ infixCount ] ) )
717 postfix[ postfixCount++ ] = infix[ infixCount ];
718 else if ( infix[ infixCount ] == '(' )
719 intStack.push( leftParen );
720 else if ( isOperator( infix[ infixCount ] ) ) {
721 higher = true; // used to store value of precedence test
722
723 while ( higher ) {
724 if ( isOperator( static_cast< char >( intStack.stackTop() ) ) )
725 if ( precedence( static_cast< char >( intStack.stackTop() ),
Chapter 15 Data Structures Solutions 487
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
726 infix[ infixCount ] ) )
727
728 postfix[ postfixCount++ ] =
729 static_cast< char >( intStack.pop() );
730 else
731 higher = false;
732 else
733 higher = false;
734 }
735
736 // See chapter 21 for a discussion of reinterpret_cast
737 intStack.push( reinterpret_cast< int & > ( infix[ infixCount ] ) );
738 }
739 else if ( infix[ infixCount ] == ')' )
740 while ( ( popValue = intStack.pop() ) != '(' )
741 postfix[ postfixCount++ ] = static_cast< char >( popValue );
742 }
743
744 postfix[ postfixCount ] = '\0';
745
746 evaluatePostfix( postfix, dataCounterPtr, instCounterPtr,
747 machineArray, getsVariable, symbolTable );
748 }
749
750 // check if c is an operator
751 bool isOperator( char c )
752 {
753 if ( c == '+' || c == '-' || c == '*' || c == '/' || c == '^' )
754 return true;
755 else
756 return false;
757 }
758
759 // If the precedence of operator1 is >= operator2,
760 bool precedence( char operator1, char operator2 )
761 {
762 if ( operator1 == '^' )
763 return true;
764 else if ( operator2 == '^' )
765 return false;
766 else if ( operator1 == '*' || operator1 == '/' )
767 return true;
768 else if ( operator1 == '+' || operator1 == '-' )
769 if ( operator2 == '*' || operator2 == '/' )
770 return false;
771 else
772 return true;
773
774 return false;
775 }
776
777 // evaluate postfix expression and produce code
778 void evaluatePostfix( char *expr, int *dataCounterPtr,
779 int *instCounterPtr, int machineArray[],
780 int getsVariable, TableEntry symbolTable[] )
781 {
782 Stack< int > intStack;
783 int popRightValue, popLeftValue, accumResult, symbolLocation, symbol;
784 char type, array[ 2 ] = "";
785 int i;
786
787 strcat( expr, ")" );
488 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
788
789 for ( i = 0; expr[ i ] != ')'; ++i )
790 if ( isdigit( expr[ i ] ) ) {
791 type = 'C';
792 array[ 0 ] = expr[ i ];
793 symbol = atoi( array );
794
795 symbolLocation = checkSymbolTable( symbolTable, symbol, type );
796 intStack.push( symbolLocation );
797 }
798 else if ( isalpha( expr[ i ] ) ) {
799 type = 'V';
800 symbol = expr[ i ];
801 symbolLocation = checkSymbolTable( symbolTable, symbol, type );
802 intStack.push( symbolLocation );
803 }
804 else {
805 popRightValue = intStack.pop();
806 popLeftValue = intStack.pop();
807 accumResult = createLetSML( popRightValue, popLeftValue, machineArray,
808 instCounterPtr, dataCounterPtr,
809 expr[ i ] );
810 intStack.push( accumResult );
811 }
812
813 machineArray[ *instCounterPtr ] = LOAD * 100;
814 machineArray[ *instCounterPtr ] += intStack.pop();
815 ++( *instCounterPtr );
816 machineArray[ *instCounterPtr ] = STORE * 100;
817 machineArray[ *instCounterPtr ] += getsVariable;
818 ++( *instCounterPtr );
819 }
820
821 int createLetSML( int right, int left, int machineArray[],
822 int *instCounterPtr, int *dataCounterPtr, char oper )
823 {
824 int location;
825
826 switch( oper ) {
827 case '+':
828 machineArray[ *instCounterPtr ] = LOAD * 100;
829 machineArray[ *instCounterPtr ] += left;
830 ++( *instCounterPtr );
831 machineArray[ *instCounterPtr ] = ADD * 100;
832 machineArray[ *instCounterPtr ] += right;
833 ++( *instCounterPtr );
834 machineArray[ *instCounterPtr ] = STORE * 100;
835 machineArray[ *instCounterPtr ] += *dataCounterPtr;
836 location = *dataCounterPtr;
837 --( *dataCounterPtr );
838 ++( *instCounterPtr );
839 return location;
840 case '-':
841 machineArray[ *instCounterPtr ] = LOAD * 100;
842 machineArray[ *instCounterPtr ] += left;
843 ++( *instCounterPtr );
844 machineArray[ *instCounterPtr ] = SUBTRACT * 100;
845 machineArray[ *instCounterPtr ] += right;
846 ++( *instCounterPtr );
847 machineArray[ *instCounterPtr ] = STORE * 100;
848 machineArray[ *instCounterPtr ] += *dataCounterPtr;
849 location = *dataCounterPtr;
Chapter 15 Data Structures Solutions 489
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.28 (Optimizing the Simple Compiler) When a program is compiled and converted into SML, a set of instructions is generated.
Certain combinations of instructions often repeat themselves, usually in triplets called productions. A production normally consists
of three instructions such as load, add and store. For example, Fig. 15.27 illustrates five of the SML instructions that were produced
in the compilation of the program in Fig. 15.25 The first three instructions are the production that adds 1 to y. Note that instructions
06 and 07 store the accumulator value in temporary location 96 and then load the value back into the accumulator so instruction
08 can store the value in location 98. Often a production is followed by a load instruction for the same location that was just stored.
This code can be optimized by eliminating the store instruction and the subsequent load instruction that operate on the same memory
location, thus enabling the Simpletron to execute the program faster. Figure 15.28 illustrates the optimized SML for the program of
Fig. 15.25. Note that there are four fewer instructions in the optimized code—a memory-space savings of 25%.
Modify the compiler to provide an option for optimizing the Simpletron Machine Language code it produces. Manually com-
pare the nonoptimized code with the optimized code, and calculate the percentage reduction.
15.29 (Modifications to the Simple compiler) Perform the following modifications to the Simple compiler. Some of these modi-
fications may also require modifications to the Simpletron Simulator program written in Exercise 5.19.
a) Allow the modulus operator (%) to be used in let statements. Simpletron Machine Language must be modified to in-
clude a modulus instruction.
b) Allow exponentiation in a let statement using ^ as the exponentiation operator. Simpletron Machine Language must
be modified to include an exponentiation instruction.
850 --( *dataCounterPtr );
851 ++( *instCounterPtr );
852 return location;
853 case '/':
854 machineArray[ *instCounterPtr ] = LOAD * 100;
855 machineArray[ *instCounterPtr ] += left;
856 ++( *instCounterPtr );
857 machineArray[ *instCounterPtr ] = DIVIDE * 100;
858 machineArray[ *instCounterPtr ] += right;
859 ++( *instCounterPtr );
860 machineArray[ *instCounterPtr ] = STORE * 100;
861 machineArray[ *instCounterPtr ] += *dataCounterPtr;
862 location = *dataCounterPtr;
863 --( *dataCounterPtr );
864 ++( *instCounterPtr );
865 return location;
866 case '*':
867 machineArray[ *instCounterPtr ] = LOAD * 100;
868 machineArray[ *instCounterPtr ] += left;
869 ++( *instCounterPtr );
870 machineArray[ *instCounterPtr ] = MULTIPLY * 100;
871 machineArray[ *instCounterPtr ] += right;
872 ++( *instCounterPtr );
873 machineArray[ *instCounterPtr ] = STORE * 100;
874 machineArray[ *instCounterPtr ] += *dataCounterPtr;
875 location = *dataCounterPtr;
876 --( *dataCounterPtr );
877 ++( *instCounterPtr );
878 return location;
879 default:
880 cerr << "ERROR: operator not recognized.\n";
881 break;
882 }
883
884 return 0; // default return
885 }
104 +2098 (load)
205 +3097 (add)
Fig. 15.27 Nonoptimized code from the program of Fig. 15.25.
490 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
c) Allow the compiler to recognize uppercase and lowercase letters in Simple statements (e.g., 'A' is equivalent to 'a').
No modifications to the Simulator are required.
d) Allow input statements to read values for multiple variables such as input x, y. No modifications to the Simpletron
Simulator are required.
e) Allow the compiler to output multiple values in a single print statement such as print a, b, c. No modifications
to the Simpletron Simulator are required.
f) Add syntax-checking capabilities to the compiler so error messages are output when syntax errors are encountered in a
Simple program. No modifications to the Simpletron Simulator are required.
g) Allow arrays of integers. No modifications to the Simpletron Simulator are required.
h) Allow subroutines specified by the Simple commands gosub and return. Command gosub passes program control
to a subroutine, and command return passes control back to the statement after the gosub. This is similar to a func-
tion call in C++. The same subroutine can be called from many gosub commands distributed throughout a program.
No modifications to the Simpletron Simulator are required.
i) Allow repetition structures of the form
for x = 2 to 10 step 2
Simple statements
next
This for statement loops from 2 to 10 with an increment of 2. The next line marks the end of the body of the for
line. No modifications to the Simpletron Simulator are required.
306 +2196 (store)
407 +2096 (load)
508 +2198 (store)
Simple program
SML location
and instruction Description
5 rem sum 1 to x none rem ignored
10 input x 00 +1099 read x into location 99
15 rem check y == x none rem ignored
20 if y == x goto 60 01 +2098 load y (98) into accumulator
02 +3199 sub x (99) from accumulator
03 +4211 branch to location 11 if zero
25 rem increment y none rem ignored
30 let y = y + 1 04 +2098 load y into accumulator
05 +3097 add 1 (97) to accumulator
06 +2198 store accumulator in y (98)
35 rem add y to total none rem ignored
40 let t = t + y 07 +2096 load t from location (96 )
08 +3098 add y (98) accumulator
09 +2196 store accumulator in t (96)
45 rem loop y none rem ignored
50 goto 20 10 +4001 branch to location 01
55 rem output result none rem ignored
60 print t 11 +1196 output t (96) to screen
99 end 12 +4300 terminate execution
Fig. 15.28 Optimized code for the program of Fig. 15.25.
Fig. 15.27 Nonoptimized code from the program of Fig. 15.25.
Chapter 15 Data Structures Solutions 491
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
j) Allow repetition structures of the form
for x = 2 to 10
Simple statements
next
This for statement loops from 2 to 10 with a default increment of 1. No modifications to the Simpletron Simulator
are required.
k) Allow the compiler to process string input and output. This requires the Simpletron Simulator to be modified to process
and store string values. (Hint: Each Simpletron word can be divided into two groups, each holding a two-digit integer.
Each two-digit integer represents the ASCII decimal equivalent of a character. Add a machine language instruction that
will print a string beginning at a certain Simpletron memory location. The first half of the word at that location is a count
of the number of characters in the string (i.e., the length of the string). Each succeeding half word contains one ASCII
character expressed as two decimal digits. The machine language instruction checks the length and prints the string by
translating each two-digit number into its equivalent character.)
l) Allow the compiler to process floating-point values in addition to integers. The Simpletron Simulator must also be mod-
ified to process floating-point values.
15.30 (A Simple interpreter) An interpreter is a program that reads a high-level language program statement, determines the op-
eration to be performed by the statement and executes the operation immediately. The high-level language program is not converted
into machine language first. Interpreters execute slowly because each statement encountered in the program must first be deci-
phered. If statements are contained in a loop, the statements are deciphered each time they are encountered in the loop. Early ver-
sions of the BASIC programming language were implemented as interpreters.
Write an interpreter for the Simple language discussed in Exercise 15.26. The program should use the infix-to-postfix con-
verter developed in Exercise 15.12 and the postfix evaluator developed in Exercise 15.13 to evaluate expressions in a let state-
ment. The same restrictions placed on the Simple language in Exercise 15.26 should be adhered to in this program. Test the
interpreter with the Simple programs written in Exercise 15.26. Compare the results of running these programs in the interpreter
with the results of compiling the Simple programs and running them in the Simpletron Simulator built in Exercise 5.19.
15.31 (Insert/Delete Anywhere in a Linked List) Our linked list class template allowed insertions and deletions at only the front
and the back of the linked list. These capabilities were convenient for us when we used private inheritance and composition to pro-
duce a stack class template and a queue class template with a minimal amount of code by reusing the list class template. Actually,
linked lists are more general that those we provided. Modify the linked list class template we developed in this chapter to handle
insertions and deletions anywhere in the list.
1// LIST.H
2// Template List class definition
3// Added copy constructor to member functions (not included in chapter).
4#ifndef LIST_H
5#define LIST_H
6
7#include <iostream>
8
9using std::cout;
10
11 #include <cassert>
12 #include "listnd.h"
13
14 template< class NODETYPE >
15 class List {
16 public:
17 List(); // default constructor
18 List( const List< NODETYPE > & ); // copy constructor
19 ~List(); // destructor
20 void insertAtFront( const NODETYPE & );
21 void insertAtBack( const NODETYPE & );
22 bool removeFromFront( NODETYPE & );
23 bool removeFromBack( NODETYPE & );
24 void insertInOrder( const NODETYPE & );
25 bool isEmpty() const;
26 void print() const;
492 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
27 protected:
28 ListNode< NODETYPE > *firstPtr; // pointer to first node
29 ListNode< NODETYPE > *lastPtr; // pointer to last node
30
31 // Utility function to allocate a new node
32 ListNode< NODETYPE > *getNewNode( const NODETYPE & );
33 };
34
35 // Default constructor
36 template< class NODETYPE >
37 List< NODETYPE >::List() { firstPtr = lastPtr = 0; }
38
39 // Copy constructor
40 template< class NODETYPE >
41 List< NODETYPE >::List( const List<NODETYPE> &copy )
42 {
43 firstPtr = lastPtr = 0; // initialize pointers
44
45 ListNode< NODETYPE > *currentPtr = copy.firstPtr;
46
47 while ( currentPtr != 0 ) {
48 insertAtBack( currentPtr -> data );
49 currentPtr = currentPtr -> nextPtr;
50 }
51 }
52
53 // Destructor
54 template< class NODETYPE >
55 List< NODETYPE >::~List()
56 {
57 if ( !isEmpty() ) { // List is not empty
58 cout << "Destroying nodes ...\n";
59
60 ListNode< NODETYPE > *currentPtr = firstPtr, *tempPtr;
61
62 while ( currentPtr != 0 ) { // delete remaining nodes
63 tempPtr = currentPtr;
64 cout << tempPtr -> data << ' ';
65 currentPtr = currentPtr -> nextPtr;
66 delete tempPtr;
67 }
68 }
69
70 cout << "\nAll nodes destroyed\n\n";
71 }
72
73 // Insert a node at the front of the list
74 template< class NODETYPE >
75 void List< NODETYPE >::insertAtFront( const NODETYPE &value )
76 {
77 ListNode<NODETYPE> *newPtr = getNewNode( value );
78
79 if ( isEmpty() ) // List is empty
80 firstPtr = lastPtr = newPtr;
81 else { // List is not empty
82 newPtr -> nextPtr = firstPtr;
83 firstPtr = newPtr;
84 }
85 }
86
87 // Insert a node at the back of the list
88 template< class NODETYPE >
Chapter 15 Data Structures Solutions 493
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
89 void List< NODETYPE >::insertAtBack( const NODETYPE &value )
90 {
91 ListNode< NODETYPE > *newPtr = getNewNode( value );
92
93 if ( isEmpty() ) // List is empty
94 firstPtr = lastPtr = newPtr;
95 else { // List is not empty
96 lastPtr -> nextPtr = newPtr;
97 lastPtr = newPtr;
98 }
99 }
100
101 // Delete a node from the front of the list
102 template< class NODETYPE >
103 bool List< NODETYPE >::removeFromFront( NODETYPE &value )
104 {
105 if ( isEmpty() ) // List is empty
106 return false; // delete unsuccessful
107 else {
108 ListNode< NODETYPE > *tempPtr = firstPtr;
109
110 if ( firstPtr == lastPtr )
111 firstPtr = lastPtr = 0;
112 else
113 firstPtr = firstPtr -> nextPtr;
114
115 value = tempPtr -> data; // data being removed
116 delete tempPtr;
117 return true; // delete successful
118 }
119 }
120
121 // Delete a node from the back of the list
122 template< class NODETYPE >
123 bool List< NODETYPE >::removeFromBack( NODETYPE &value )
124 {
125 if ( isEmpty() )
126 return false; // delete unsuccessful
127 else {
128 ListNode< NODETYPE > *tempPtr = lastPtr;
129
130 if ( firstPtr == lastPtr )
131 firstPtr = lastPtr = 0;
132 else {
133 ListNode< NODETYPE > *currentPtr = firstPtr;
134
135 while ( currentPtr -> nextPtr != lastPtr )
136 currentPtr = currentPtr -> nextPtr;
137
138 lastPtr = currentPtr;
139 currentPtr -> nextPtr = 0;
140 }
141
142 value = tempPtr -> data;
143 delete tempPtr;
144 return true; // delete successful
145 }
146 }
147
148 // Is the List empty?
149 template< class NODETYPE >
150 bool List< NODETYPE >::isEmpty() const { return firstPtr == 0; }
494 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
151
152 // Return a pointer to a newly allocated node
153 template< class NODETYPE >
154 ListNode< NODETYPE > *List< NODETYPE >::getNewNode( const NODETYPE &value )
155 {
156 ListNode< NODETYPE > *ptr = new ListNode< NODETYPE >( value );
157 assert( ptr != 0 );
158 return ptr;
159 }
160
161 // Display the contents of the List
162 template< class NODETYPE >
163 void List< NODETYPE >::print() const
164 {
165 if ( isEmpty() ) {
166 cout << "The list is empty\n\n";
167 return;
168 }
169
170 ListNode< NODETYPE > *currentPtr = firstPtr;
171
172 cout << "The list is: ";
173
174 while ( currentPtr != 0 ) {
175 cout << currentPtr -> data << ' ';
176 currentPtr = currentPtr -> nextPtr;
177 }
178
179 cout << "\n\n";
180 }
181
182 template< class NODETYPE >
183 void List< NODETYPE >::insertInOrder( const NODETYPE &value )
184 {
185 if ( isEmpty() ) {
186 ListNode< NODETYPE > *newPtr = getNewNode( value );
187 firstPtr = lastPtr = newPtr;
188 }
189 else {
190 if ( firstPtr -> data > value )
191 insertAtFront( value );
192 else if ( lastPtr -> data < value )
193 insertAtBack( value );
194 else {
195 ListNode< NODETYPE > *currentPtr = firstPtr -> nextPtr,
196 *previousPtr = firstPtr,
197 *newPtr = getNewNode( value );
198
199 while ( currentPtr != lastPtr && currentPtr -> data < value ) {
200 previousPtr = currentPtr;
201 currentPtr = currentPtr -> nextPtr;
202 }
203
204 previousPtr -> nextPtr = newPtr;
205 newPtr -> nextPtr = currentPtr;
206 }
207 }
208 }
209
210 #endif
Chapter 15 Data Structures Solutions 495
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
211 // LISTND.H
212 // ListNode template definition
213 #ifndef LISTND_H
214 #define LISTND_H
215
216 template< class T > class List; // forward declaration
217
218 template< class NODETYPE >
219 class ListNode {
220 friend class List< NODETYPE >; // make List a friend
221 public:
222 ListNode( const NODETYPE & ); // constructor
223 NODETYPE getData() const; // return the data in the node
224 void setNextPtr( ListNode *nPtr ) { nextPtr = nPtr; }
225 ListNode *getNextPtr() const { return nextPtr; }
226 private:
227 NODETYPE data; // data
228 ListNode *nextPtr; // next node in the list
229 };
230
231 // Constructor
232 template< class NODETYPE >
233 ListNode< NODETYPE >::ListNode( const NODETYPE &info )
234 {
235 data = info;
236 nextPtr = 0;
237 }
238
239 // Return a copy of the data in the node
240 template< class NODETYPE >
241 NODETYPE ListNode< NODETYPE >::getData() const { return data; }
242
243 #endif
244 // LIST2.H
245 // Template List class definition
246 // NOTE: This solution only provides the delete anywhere operation.
247
248 #ifndef LIST2_H
249 #define LIST2_H
250
251 #include <cassert>
252 #include "listnd.h"
253 #include "list.h"
254
255 template< class NODETYPE >
256 class List2 : public List< NODETYPE > {
257 public:
258 bool deleteNode( const NODETYPE &, NODETYPE & );
259 };
260
261 // Delete a node from anywhere in the list
262 template< class NODETYPE >
263 bool List2< NODETYPE >::deleteNode( const NODETYPE &val, NODETYPE &deletedVal )
264 {
265 if ( isEmpty() )
266 return false; // delete unsuccessful
267 else {
268 if ( firstPtr -> getData() == val ) {
496 Data Structures Solutions Chapter 15
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
269 removeFromFront( deletedVal );
270 return true; // delete successful
271 }
272 else if ( lastPtr -> getData() == val ) {
273 removeFromBack( deletedVal );
274 return true; // delete successful
275 }
276 else {
277 ListNode< NODETYPE > *currentPtr = firstPtr -> getNextPtr(),
278 *previousPtr = firstPtr;
279
280 while ( currentPtr != lastPtr && currentPtr -> getData() < val ) {
281 previousPtr = currentPtr;
282 currentPtr = currentPtr -> getNextPtr();
283 }
284
285 if ( currentPtr -> getData() == val ) {
286 ListNode< NODETYPE > *tempPtr = currentPtr;
287 deletedVal = currentPtr -> getData();
288 previousPtr -> setNextPtr( currentPtr -> getNextPtr() );
289 delete tempPtr;
290 return true; // delete successful
291 }
292 else
293 return false; // delete unsuccessful
294 }
295 }
296 }
297
298 #endif
299 // Exercise 15.31 solution
300 #include <iostream>
301
302 using std::cout;
303 using std::cin;
304
305 #include <cstdlib>
306 #include <ctime>
307 #include "list2.h"
308
309 int main()
310 {
311 srand( time( 0 ) ); // randomize the random number generator
312
313 List2< int > intList;
314
315 for ( int i = 1; i <= 10; ++i )
316 intList.insertInOrder( rand() % 101 );
317
318 intList.print();
319
320 int value, deletedValue;
321
322 cout << "Enter an integer to delete (-1 to end): ";
323 cin >> value;
324
325 while ( value != -1 ) {
326 if ( intList.deleteNode( value, deletedValue ) ) {
327 cout << deletedValue << " was deleted from the list\n";
328 intList.print();
Chapter 15 Data Structures Solutions 497
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15.32 (List and Queues without Tail Pointers) Our implementation of a linked list (Fig. 15.3) used both a firstPtr and a
lastPtr. The lastPtr was useful for the insertAtBack and removeFromBack member functions of the List class. The
insertAtBack function corresponds to the enqueue member function of the Queue class. Rewrite the List class so that it
does not use a lastPtr. Thus, any operations on the tail of a list must begin searching the list from the front. Does this affect our
implementation of the Queue class (Fig. 15.12)?
15.33 Use the composition version of the stack program (Fig. 15.11) to form a complete working stack program. Modify this pro-
gram to inline the member functions. Compare the two approaches. Summarize the advantages and disadvantages of inlining
member functions.
15.34 (Performance of Binary Tree Sorting and Searching) One problem with the binary tree sort is that the order in which the
data are inserted affects the shape of the tree—for the same collection of data, different orderings can yield binary trees of d ramat-
ically different shapes. The performance of the binary tree sorting and searching algorithms is sensitive to the shape of the binary
tree. What shape would a binary tree have if its data were inserted in increasing order? in decreasing order? What shape should the
tree have to achieve maximal searching performance?
15.35 (Indexed Lists) As presented in the text, linked lists must be searched sequentially. For large lists, this can result in poor
performance. A common technique for improving list searching performance is to create and maintain an index to the list. An index
is a set of pointers to various key places in the list. For example, an application that searches a large list of names could improve
performance by creating an index with 26 entries—one for each letter of the alphabet. A search operation for a last name beginning
with ‘Y’ would then first search the index to determine where the ‘Y’ entries begin, and then “jump into” the list at that point and
search linearly until the desired name is found. This would be much faster than searching the linked list from the beginning. Use
the List class of Fig. 15.3 as the basis of an IndexedList class. Write a program that demonstrates the operation of indexed
lists. Be sure to include member functions insertInIndexedList, searchIndexedList and deleteFromInd-
exedList.
329 }
330 else
331 cout << "Element was not found";
332
333 cout << "Enter an integer to delete (-1 to end): ";
334 cin >> value;
335 }
336
337 return 0;
338 }
The list is: 0 3 20 35 39 51 61 62 64 82
Enter an integer to delete (-1 to end): 8
Element was not foundEnter an integer to delete (-1 to end): 82
82 was deleted from the list
The list is: 0 3 20 35 39 51 61 62 64
Enter an integer to delete (-1 to end): -1
Destroying nodes ...
0 3 20 35 39 51 61 62 64
All nodes destroyed
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16
Bits, Characters, Strings
and Structures
Solutions
Solutions
16.6 Provide the definition for each of the following structures and unions:
a) Structure Inventory containing character array partName[ 30 ], integer partNumber, floating-point price,
integer stock and integer reorder.
ANS:
struct Inventory {
char partName[ 30 ];
int partNumber;
double price;
int stock;
int reorder;
};
b) A structure called Address that contains character arrays streetAddress[ 25 ], city[ 20 ], state[ 3 ] and
zipCode[ 6 ].
ANS:
struct Address {
char streetAddress[ 25 ];
char city[ 20 ];
char state[ 3 ];
char zipCode[ 6 ];
};
c) Structure Student that contains arrays firstName[ 15 ] and lastName[ 15 ], and variable homeAddress of
type struct Address from part (b).
ANS:
struct Student {
char firstName[ 15 ];
char lastName[ 15 ];
struct Address homeAddress;
};
d) Structure Test containing 16 bit fields with widths of 1 bit. The names of the bit fields are the letters a to p.
Chapter 16 Bits, Characters, Strings and Structures Solutions 499
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
ANS:
struct Test {
unsigned a:1, b:1, c:1, d:1, e:1, f:1, g:1, h:1,
i:1, j:1, k:1, l:1, m:1, n:1, o:1, p:1;
};
16.7 Consider the following structure definitions and variable declarations,
struct Customer {
char lastName[ 15 ];
char firstName[ 15 ];
int customerNumber;
struct {
char phoneNumber[ 11 ];
char address[ 50 ];
char city[ 15 ];
char state[ 3 ];
char zipCode[ 6 ];
} personal;
} customerRecord, *customerPtr;
customerPtr = &customerRecord;
Write a separate expression that accesses the structure members in each of the following parts:
a) Member lastName of structure customerRecord.
ANS: customerRecord.lastName
b) Member lastName of the structure pointed to by customerPtr.
ANS: customerPtr->lastName
c) Member firstName of structure customerRecord.
ANS: customerRecord.firstName
d) Member firstName of the structure pointed to by customerPtr.
ANS: customerPtr->firstName
e) Member customerNumber of structure customerRecord.
ANS: customerRecord.customerNumber
f) Member customerNumber of the structure pointed to by customerPtr.
ANS: customerPtr->customerNumber
g) Member phoneNumber of member personal of structure customerRecord.
ANS: customerRecord.personal.phoneNumber
h) Member phoneNumber of member personal of the structure pointed to by customerPtr.
ANS: customerPtr->personal.phoneNumber
i) Member address of member personal of structure customerRecord.
ANS: customerRecord.personal.address
j) Member address of member personal of the structure pointed to by customerPtr.
ANS: customerPtr->personal.address
k) Member city of member personal of structure customerRecord.
ANS: customerRecord.personal.city
l) Member city of member personal of the structure pointed to by customerPtr.
ANS: customerPtr->personal.city
m) Member state of member personal of structure customerRecord.
ANS: customerRecord.personal.state
n) Member state of member personal of the structure pointed to by customerPtr.
ANS: customerPtr->personal.state
o) Member zipCode of member personal of structure customerRecord.
ANS: customerRecord.personal.zipCode
p) Member zipCode of member personal of the structure pointed to by customerPtr.
ANS: customerPtr->personal.zipCode
500 Bits, Characters, Strings and Structures Solutions Chapter 16
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.8 Modify the program of Fig. 16.14 to shuffle the cards using a high-performance shuffle as shown in Fig. 16.2. Print the
resulting deck in two column format as in Fig. 16.3. Precede each card with its color.
1// Exercise 16.8 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::ios;
7
8#include <iomanip>
9
10 using std::setw;
11 using std::setprecision;
12 using std::setiosflags;
13 using std::resetiosflags;
14
15 #include <cstdlib>
16 #include <ctime>
17
18 struct bitCard {
19 unsigned face : 4;
20 unsigned suit : 2;
21 unsigned color : 1;
22 };
23
24 typedef struct bitCard Card;
25
26 void fillDeck( Card * const );
27 void shuffle( Card * const );
28 void deal( const Card * const );
29
30 int main()
31 {
32 Card deck[ 52 ];
33
34 srand( 0 );
35
36 fillDeck( deck );
37 shuffle( deck );
38 deal( deck );
39
40 return 0;
41 }
42
43 void fillDeck( Card * const wDeck )
44 {
45 for ( int i = 0; i < 52; ++i ) {
46 wDeck[ i ].face = i % 13;
47 wDeck[ i ].suit = i / 13;
48 wDeck[ i ].color = i / 26;
49 }
50 }
51
52 void shuffle( Card * const wDeck )
53 {
54 int j;
55 Card temp;
56
57 for ( int i = 0; i < 52; ++i ) {
58 j = rand() % 52;
59
Chapter 16 Bits, Characters, Strings and Structures Solutions 501
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.9 Write a program that right shifts an integer variable 4 bits. The program should print the integer in bits before and after the
shift operation. Does your system place zeros or ones in the vacated bits?
60 temp = wDeck[ i ];
61 wDeck[ i ] = wDeck[ j ];
62 wDeck[ j ] = temp;
63 }
64 }
65
66 void deal( const Card * const wDeck2 )
67 {
68 char *face[] = { "Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven",
69 "Eight", "Nine", "Ten", "Jack", "Queen", "King" },
70 *suit[] = { "Hearts", "Diamonds", "Clubs", "Spades" },
71 *color[] = { "Red", "Black" };
72
73 for ( int i = 0; i < 52; ++i ) {
74
75 cout << setw( 5 ) << color[ wDeck2[ i ].color ] << ": "
76 << setw( 8 ) << face[ wDeck2[ i ].face ] << " of "
77 << setiosflags( ios::left ) << setw( 8 )
78 << suit[ wDeck2[ i ].suit ] << resetiosflags( ios::left );
79
80 cout.put( ( i + 1 ) % 2 ? '\t' : '\n' );
81 }
82 }
Black: King of Clubs Black: Three of Clubs
Black: Five of Clubs Red: Ten of Hearts
Black: Deuce of Clubs Red: Four of Hearts
Red: Six of Hearts Black: Nine of Clubs
Black: Seven of Clubs Red: Five of Hearts
Black: Deuce of Spades Red: Eight of Diamonds
Red: Nine of Hearts Red: Nine of Diamonds
Black: Three of Spades Black: Nine of Spades
Red: Seven of Diamonds Red: King of Diamonds
Black: Six of Clubs Red: Jack of Diamonds
Red: Queen of Hearts Black: Ten of Clubs
Red: Deuce of Hearts Red: Six of Diamonds
Black: Five of Spades Black: Four of Clubs
Black: Jack of Clubs Red: Three of Diamonds
Red: Jack of Hearts Red: Ace of Hearts
Red: Ten of Diamonds Black: Eight of Clubs
Black: Queen of Spades Black: Six of Spades
Red: Seven of Hearts Black: Ace of Spades
Black: Seven of Spades Red: King of Hearts
Black: Ten of Spades Black: Four of Spades
Red: Queen of Diamonds Black: Jack of Spades
Black: Ace of Clubs Black: King of Spades
Black: Eight of Spades Black: Queen of Clubs
Red: Eight of Hearts Red: Ace of Diamonds
Red: Four of Diamonds Red: Three of Hearts
Red: Five of Diamonds Red: Deuce of Diamonds
1// Exercise 16.9 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
502 Bits, Characters, Strings and Structures Solutions Chapter 16
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.10 If your computer uses 4-byte integers, modify the program of Fig. 16.5 so that it works with 4-byte integers.
16.11 Left shifting an unsigned integer by 1 bit is equivalent to multiplying the value by 2. Write function power2 that takes
two integer arguments number and pow and calculates
number * 2pow
Use a shift operator to calculate the result. The program should print the values as integers and as bits.
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setw;
12 using std::setprecision;
13 using std::setiosflags;
14 using std::resetiosflags;
15
16 void displayBits( unsigned );
17
18 int main()
19 {
20 unsigned val;
21
22 cout << "Enter an integer: ";
23 cin >> val;
24
25 cout << "Before right shifting 4 bits is:\n";
26 displayBits( val );
27 cout << "After right shifting 4 bits is:\n";
28 displayBits( val >> 4 );
29
30 return 0;
31 }
32
33 void displayBits( unsigned value )
34 {
35 const int SHIFT = 8 * sizeof( unsigned ) - 1;
36 const unsigned MASK = 1 << SHIFT;
37 cout << setw( 7 ) << value << " = ";
38
39 for ( unsigned c = 1; c <= SHIFT + 1; c++ ) {
40 cout << ( value & MASK ? '1' : '0' );
41 value <<= 1;
42
43 if ( c % 8 == 0 )
44 cout << ' ';
45 }
46
47 cout << endl;
48 }
Enter an integer: 888
Before right shifting 4 bits is:
888 = 00000000 00000000 00000011 01111000
After right shifting 4 bits is:
55 = 00000000 00000000 00000000 00110111
Chapter 16 Bits, Characters, Strings and Structures Solutions 503
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1// Exercise 16.11 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <iomanip>
9
10 using std::setw;
11 using std::setprecision;
12
13 void displayBits( unsigned );
14 unsigned power2( unsigned, unsigned );
15
16 int main()
17 {
18 unsigned number, pow, result;
19
20 cout << "Enter two integers: ";
21 cin >> number >> pow;
22
23 cout << "number:\n";
24 displayBits( number );
25 cout << "\npower:\n";
26 displayBits( pow );
27 result = power2( number, pow );
28 cout << '\n' << number << " * 2^" << pow << " = " << result << '\n';
29 displayBits( result );
30
31 return 0;
32 }
33
34 unsigned power2( unsigned n, unsigned p ) { return n << p; }
35
36 void displayBits( unsigned value )
37 {
38 const int SHIFT = 8 * sizeof( unsigned ) - 1;
39 const unsigned MASK = 1 << SHIFT;
40 cout << setw( 7 ) << value << " = ";
41
42 for ( unsigned c = 1; c <= SHIFT + 1; c++ ) {
43 cout << ( value & MASK ? '1' : '0' );
44 value <<= 1;
45
46 if ( c % 8 == 0 )
47 cout << ' ';
48 }
49
50 cout << endl;
51 }
504 Bits, Characters, Strings and Structures Solutions Chapter 16
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.12 The left-shift operator can be used to pack two character values into a 2-byte unsigned integer variable. Write a program
that inputs two characters from the keyboard and passes them to function packCharacters. To pack two characters into an un-
signed integer variable, assign the first character to the unsigned variable, shift the unsigned variable left by 8 bit positions
and combine the unsigned variable with the second character using the bitwise inclusive-OR operator. The program should out-
put the characters in their bit format before and after they are packed into the unsigned integer to prove that the characters are in
fact packed correctly in the unsigned variable.
Enter an integer: 888
Before right shifting 4 bits is:
888 = 00000000 00000000 00000011 01111000
After right shifting 4 bits is:
55 = 00000000 00000000 00000000 00110111
Enter two integers: 3 4
number:
3 = 00000000 00000000 00000000 00000011
power:
4 = 00000000 00000000 00000000 00000100
3 * 2^4 = 48
48 = 00000000 00000000 00000000 00110000
1// Exercise 16.12 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setw;
12
13 unsigned packCharacters( char, char );
14 void displayBits( unsigned );
15
16 int main()
17 {
18 char a, b;
19 unsigned result;
20
21 cout << "Enter two characters: ";
22 cin.setf( ios::skipws );
23 cin >> a >> b;
24
25 cout << '\'' << a << '\'' << " in bits as an unsigned integers is:\n";
26 displayBits( a );
27
28 cout << '\'' << b << '\'' << " in bits as an unsigned integers is:\n";
29 displayBits( b );
30
31 result = packCharacters( a, b );
32
33 cout << "\n\'" << a << '\'' << " and " << '\'' << b << '\''
34 << " packed in an unsigned integer:\n";
Chapter 16 Bits, Characters, Strings and Structures Solutions 505
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.13 Using the right-shift operator, the bitwise AND operator and a mask, write function unpackCharacters that takes the
unsigned integer from Exercise 16.12 and unpacks it into two characters. To unpack two characters from an unsigned 2-byte
integer, combine the unsigned integer with the mask 65280 (11111111 00000000) and right shift the result 8 bits. Assign the
resulting value to a char variable. Then, combine the unsigned integer with the mask 255 (00000000 11111111). Assign
the result to another char variable. The program should print the unsigned integer in bits before it is unpacked, and then print
the characters in bits to confirm that they were unpacked correctly.
35 displayBits( result );
36
37 return 0;
38 }
39
40 unsigned packCharacters( char x, char y )
41 {
42 unsigned pack = x;
43
44 pack <<= 8;
45 pack |= y;
46 return pack;
47 }
48
49 void displayBits( unsigned value )
50 {
51 const int SHIFT = 8 * sizeof( unsigned ) - 1;
52 const unsigned MASK = 1 << SHIFT;
53 cout << setw( 7 ) << value << " = ";
54
55 for ( unsigned c = 1; c <= SHIFT + 1; c++ ) {
56 cout << ( value & MASK ? '1' : '0' );
57 value <<= 1;
58
59 if ( c % 8 == 0 )
60 cout << ' ';
61 }
62
63 cout << endl;
64 }
Enter two characters: T N
'T' in bits as an unsigned integers is:
84 = 00000000 00000000 00000000 01010100
'N' in bits as an unsigned integers is:
78 = 00000000 00000000 00000000 01001110
'T' and 'N' packed in an unsigned integer:
21582 = 00000000 00000000 01010100 01001110
1// Exercise 16.13 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#include <iomanip>
8
9using std::setw;
10
11 void unpackCharacters( char * const, char * const, unsigned );
12 void displayBits( unsigned );
506 Bits, Characters, Strings and Structures Solutions Chapter 16
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.14 If your system uses 4-byte integers, rewrite the program of Exercise 16.12 to pack 4 characters.
16.15 If your system uses 4-byte integers, rewrite the function unpackCharacters of Exercise 16.13 to unpack 4 characters.
Create the masks you need to unpack the 4 characters by left shifting the value 255 in the mask variable by 8 bits 0, 1, 2 or 3 times
(depending on the byte you are unpacking).
13
14 int main()
15 {
16 char a, b;
17 unsigned packed = 16706;
18
19 cout << "The packed character representation is:\n";
20 displayBits( packed );
21 unpackCharacters( &a, &b, packed );
22 cout << "\nThe unpacked characters are \'" << a << "\' and \'" << b
23 << "\'\n";
24 displayBits( a );
25 displayBits( b );
26
27 return 0;
28 }
29
30 void unpackCharacters( char * const aPtr, char * const bPtr, unsigned pack )
31 {
32 unsigned mask1 = 65280, mask2 = 255;
33
34 *aPtr = static_cast< char >( ( pack & mask1 ) >> 8 );
35 *bPtr = static_cast< char >( pack & mask2 );
36 }
37
38 void displayBits( unsigned value )
39 {
40 const int SHIFT = 8 * sizeof( unsigned ) - 1;
41 const unsigned MASK = 1 << SHIFT;
42 cout << setw( 7 ) << value << " = ";
43
44 for ( unsigned c = 1; c <= SHIFT + 1; c++ ) {
45 cout << ( value & MASK ? '1' : '0' );
46 value <<= 1;
47
48 if ( c % 8 == 0 )
49 cout << ' ';
50 }
51
52 cout << endl;
53 }
The packed character representation is:
16706 = 00000000 00000000 01000001 01000010
The unpacked characters are 'A' and 'B'
65 = 00000000 00000000 00000000 01000001
66 = 00000000 00000000 00000000 01000010
Chapter 16 Bits, Characters, Strings and Structures Solutions 507
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.16 Write a program that reverses the order of the bits in an unsigned integer value. The program should input the value from
the user and call function reverseBits to print the bits in reverse order. Print the value in bits both before and after the bits are
reversed to confirm that the bits are reversed properly.
1// Exercise 16.16 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setw;
12
13 void reverseBits( unsigned * const );
14 void displayBits( unsigned );
15
16 int main()
17 {
18 unsigned a;
19
20 cout << "Enter an unsigned integer: ";
21 cin >> a;
22
23 cout << "\nBefore bits are reversed:\n";
24 displayBits( a );
25 reverseBits( &a );
26 cout << "\nAfter bits are reversed:\n";
27 displayBits( a );
28
29 return 0;
30 }
31
32 void reverseBits( unsigned * const vPtr )
33 {
34 const int SHIFT = 8 * sizeof( unsigned ) - 1;
35 const unsigned MASK = 1;
36 unsigned value = *vPtr;
37
38 for ( int i = 0; i <= 15; ++i ) {
39 *vPtr <<= 1;
40 *vPtr |= ( value & MASK );
41 value >>= 1;
42 }
43 }
44 void displayBits( unsigned value )
45 {
46 const int SHIFT = 8 * sizeof( unsigned ) - 1;
47 const unsigned MASK = 1 << SHIFT;
48 cout << setw( 7 ) << value << " = ";
49
50 for ( unsigned c = 1; c <= SHIFT + 1; c++ ) {
51 cout << ( value & MASK ? '1' : '0' );
52 value <<= 1;
53
54 if ( c % 8 == 0 )
55 cout << ' ';
56 }
57
508 Bits, Characters, Strings and Structures Solutions Chapter 16
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.17 Write a program that demonstrates passing an array by value. (Hint: use a struct). Prove that a copy was passed by mod-
ifying the array copy in the called function.
16.18 Write a program that inputs a character from the keyboard and tests the character with each of the functions in the character
handling library. The program should print the value returned by each function.
58 cout << endl;
59 }
Enter an unsigned integer: 330
Before bits are reversed:
330 = 00000000 00000000 00000001 01001010
After bits are reversed:
21648000 = 00000001 01001010 01010010 10000000
1// Exercise 16.18 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cctype>
9
10 int main()
11 {
12 char c;
13
14 cout << "Enter a character: ";
15 c = static_cast< char >( cin.get() );
16
17 cout << "isdigit(\'" << c << "\') = " << isdigit( c )
18 << "\nisalpha(\'" << c << "\') = " << isalpha( c )
19 << "\nisalnum(\'" << c << "\') = " << isalnum( c );
20
21 cout << "\nisxdigit(\'" << c << "\') = " << isxdigit( c )
22 << "\nislower(\'" << c << "\') = " << islower( c )
23 << "\nisupper(\'" << c << "\') = " << isupper( c )
24 << "\ntolower(\'" << c << "\') = " << tolower( c )
25 << "\ntoupper(\'" << c << "\') = " << toupper( c )
26 << "\nisspace(\'" << c << "\') = " << isspace( c );
27
28 cout << "\niscntrl(\'" << c << "\') = " << iscntrl( c )
29 << "\nispunct(\'" << c << "\') = " << ispunct( c )
30 << "\nisprint(\'" << c << "\') = " << isprint( c )
31 << "\nisgraph(\'" << c << "\') = " << isgraph( c ) << endl;
32
33 return 0;
34 }
Chapter 16 Bits, Characters, Strings and Structures Solutions 509
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.19 The following program uses function multiple to determine if the integer entered from the keyboard is a multiple of
some integer X. Examine function multiple, and then determine the value of X.
Enter a character: ~
isdigit('~') = 0
isalpha('~') = 0
isalnum('~') = 0
isxdigit('~') = 0
islower('~') = 0
isupper('~') = 0
tolower('~') = 126
toupper('~') = 126
isspace('~') = 0
iscntrl('~') = 0
ispunct('~') = 16
isprint('~') = 16
isgraph('~') = 16
1// ex16_19.cpp
2// This program determines if a value is a multiple of X
3#include <iostream>
4
5using std::cout;
6using std::cin;
7using std::endl;
8
9bool multiple( int );
10
11 int main()
12 {
13 int y;
14
15 cout << "Enter an integer between 1 and 32000: ";
16 cin >> y;
17
18 if ( multiple( y ) )
19 cout << y << " is a multiple of X" << endl;
20 else
21 cout << y << " is not a multiple of X" << endl;
22
23 return 0;
24 }
25
26 bool multiple( int num )
27 {
28 bool mult = true;
29
30 for ( int i = 0, mask = 1; i < 10; i++, mask <<= 1 )
31 if ( ( num & mask ) != 0 ) {
32 mult = false;
33 break;
34 }
35
36 return mult;
37 }
510 Bits, Characters, Strings and Structures Solutions Chapter 16
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
ANS: Determines if the number input is a multiple of X. The value of X is 1024.
16.20 What does the following program do?
ANS: The program prints 0 if the total number of 1s in the bit representation is odd, and prints a 1 if the number of bits is
even.
16.21 Write a program that inputs a line of text with istream member function getline (see Chapter 11) into character array
s[ 100 ]. Output the line in uppercase letters and lowercase letters.
1// ex16_20.cpp
2#include <iostream>
3
4using std::cout;
5using std::cin;
6using std::endl;
7
8int mystery( unsigned );
9
10 int main()
11 {
12 unsigned x;
13
14 cout << "Enter an integer: ";
15 cin >> x;
16 cout << "The result is " << mystery( x ) << endl;
17
18 return 0;
19 }
20
21 int mystery( unsigned bits )
22 {
23 const int SHIFT = 8 * sizeof( unsigned ) - 1;
24 const unsigned MASK = 1 << SHIFT;
25 unsigned total = 0;
26
27 for ( int i = 0; i < SHIFT + 1; i++, bits <<= 1 )
28 if ( ( bits & MASK ) == MASK )
29 ++total;
30
31 return !( total % 2 );
32 }
1// Exercise 16.21 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6
7#include <cctype>
8
9const int SIZE = 100;
10
11 int main()
12 {
13 char s[ SIZE ];
14 int i;
15
16 cout << "Enter a line of text:\n";
17 cin.getline( s, SIZE );
Chapter 16 Bits, Characters, Strings and Structures Solutions 511
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.22 Write a program that inputs four strings that represent integers, converts the strings to integers sums the values, and prints
the total of the four values.
18
19 cout << "\nThe line in uppercase is:\n";
20
21 for ( i = 0; s[ i ] != '\0'; ++i )
22 cout.put( static_cast< char >( toupper( s[ i ] ) ) );
23
24 cout << "\n\nThe line in lowercase is:\n";
25
26 for ( i = 0; s[ i ] != '\0'; ++i )
27 cout.put( static_cast< char >( tolower( s[ i ] ) ) );
28
29 return 0;
30 }
Enter a line of text:
CPPHTP2 Instructor's Manual
The line in uppercase is:
CPPHTP2 INSTRUCTOR'S MANUAL
The line in lowercase is:
cpphtp2 instructor's manual
1// Exercise 16.22 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <cstdlib>
9
10 const int SIZE = 6;
11
12 int main()
13 {
14 char stringValue[ SIZE ];
15 int sum = 0;
16
17 for ( int i = 1; i <= 4; ++i ) {
18 cout << "Enter an integer string: ";
19 cin >> stringValue;
20 sum += atoi( stringValue );
21 }
22
23 cout << "The total of the values is " << sum << endl;
24
25 return 0;
26 }
Enter an integer string: 11
Enter an integer string: 22
Enter an integer string: 44
Enter an integer string: 88
The total of the values is 165
512 Bits, Characters, Strings and Structures Solutions Chapter 16
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.23 Write a program that inputs four strings that represent floating-point values, converts the strings to double values, sums the
values and prints the total of the four values.
16.24 Write a program that inputs a line of text and a search string from the keyboard. Using function strstr, locate the first
occurrence of the search string in the line of text, and assign the location to variable searchPtr of type char *. If the search
string is found, print the remainder of the line of text beginning with the search string. Then, use strstr again to locate the next
occurrence of the search string in the line of text. If a second occurrence is found, print the remainder of the line of text beginning
with the second occurrence. (Hint: The second call to strstr should contain the expression searchPtr + 1 as its first argu-
ment.)
1// Exercise 16.23 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setw;
12 using std::setprecision;
13
14 #include <cstdlib>
15
16 const int SIZE = 15;
17
18 int main()
19 {
20 char stringValue[ SIZE ];
21 double sum = 0.0;
22
23 for ( int i = 1; i <= 4; ++i ) {
24 cout << "Enter a double point string: ";
25 cin >> stringValue;
26 sum += atof( stringValue );
27 }
28
29 cout.setf( ios::fixed | ios::showpoint );
30 cout << "\nThe total of the values is " << setprecision( 3 ) << sum
31 << endl;
32
33 return 0;
34 }
Enter a double point string: 1.1
Enter a double point string: 1.2
Enter a double point string: 1.3
Enter a double point string: 1.4
The total of the values is 5.000
1// Exercise 16.24 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6
7#include <cstring>
Chapter 16 Bits, Characters, Strings and Structures Solutions 513
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.25 Write a program based on the program of Exercise 16.24 that inputs several lines of text and a search string, and uses func-
tion strstr to determine the total number of occurrences of the string in the lines of text. Print the result.
8
9const int SIZE1 = 80, SIZE2 = 15;
10
11 int main()
12 {
13 char text[ SIZE1 ], search[ SIZE2 ], *searchPtr;
14
15 cout << "Enter a line of text:\n";
16 cin.get( text, SIZE1 );
17 cout << "Enter a search string: ";
18 cin >> search;
19 searchPtr = strstr( text, search );
20
21 if ( searchPtr ) {
22 cout << "\nThe remainder of the line beginning with\n"
23 << "the first occurrence of\n\"" << search << "\":\n"
24 << searchPtr << '\n';
25
26 searchPtr = strstr( searchPtr + 1, search );
27
28 if ( searchPtr )
29 cout << "\nThe remainder of the line beginning with"
30 << "\nthe second occurrence of\n\"" << search << "\":\n"
31 << searchPtr << '\n';
32 else
33 cout << "The search string appeared only once.\n";
34 }
35 else
36 cout << "\"" << search << "\" not found.\n";
37
38 return 0;
39 }
Enter a line of text:
alphabet soup tastes good
Enter a search string: be
The remainder of the line beginning with
the first occurrence of
"be":
bet soup tastes good
The search string appeared only once.
1// Exercise 16.25 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <iomanip>
9
10 using std::setw;
11 using std::setprecision;
12 using std::setiosflags;
13 using std::resetiosflags;
514 Bits, Characters, Strings and Structures Solutions Chapter 16
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.26 Write a program that inputs several lines of text and a search character and uses function strchr to determine the total
number of occurrences of the character in the lines of text.
14
15 #include <cstring>
16 #include <cctype>
17
18 const int SIZE1 = 80, SIZE2 = 20;
19
20 int main()
21 {
22 char text[ 3 ][ SIZE1 ], search[ SIZE2 ], *searchPtr;
23 int count = 0, i;
24
25 cout << "Enter three lines of text:\n";
26
27 for ( i = 0; i <= 2; ++i )
28 cin.getline( &text[ i ][ 0 ], SIZE1 );
29
30 // make all characters lowercase
31 for ( i = 0; i <= 2; ++i )
32 for ( int j = 0; text[ i ][ j ] != '\0'; ++j ) {
33 char c = static_cast< char >( tolower( text[ i ][ j ] ) );
34 text[ i ][ j ] = c;
35 }
36
37 cout << "\nEnter a search string: ";
38 cin >> search;
39
40 for ( i = 0; i <= 2; ++i ) {
41 searchPtr = &text[ i ][ 0 ];
42
43 while ( searchPtr = strstr( searchPtr, search ) ) {
44 ++count;
45 ++searchPtr;
46 }
47 }
48
49 cout << "\nThe total occurrences of \"" << search
50 << "\" in the text is:" << setw( 3 ) << count << endl;
51
52 return 0;
53 }
Enter three lines of text:
first line of text
second line of text
third line of text
Enter a search string: in
The total occurrences of "in" in the text is: 3
1// Exercise 16.26 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
Chapter 16 Bits, Characters, Strings and Structures Solutions 515
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.27 Write a program based on the program of Exercise 16.26 that inputs several lines of text and uses function strchr to de-
termine the total number of occurrences of each letter of the alphabet in the text. Uppercase and lowercase letters should be counted
together. Store the totals for each letter in an array, and print the values in tabular format after the totals have been determined.
7
8#include <iomanip>
9
10 using std::setw;
11
12 #include <cstring>
13 #include <cctype>
14
15 const int SIZE = 80;
16
17 int main()
18 {
19 char text[ 3 ][ SIZE ], search, *searchPtr;
20 int count = 0, i;
21
22 cout << "Enter three lines of text:\n";
23
24 for ( i = 0; i <= 2; ++i )
25 cin.getline( &text[ i ][ 0 ], SIZE );
26
27 // convert all letters to lowercase
28 for ( i = 0; i <= 2; ++i )
29 for ( int j = 0; text[ i ][ j ] != '\0'; ++j ) {
30 char c = static_cast< char >( tolower( text[ i ][ j ] ) );
31 text[ i ][ j ] = c;
32 }
33
34 cout << "\nEnter a search character: ";
35 cin >> search;
36
37 for ( i = 0; i <= 2; ++i ) {
38 searchPtr = &text[ i ][ 0 ];
39
40 while ( searchPtr = strchr( searchPtr, search ) ) {
41 ++count;
42 ++searchPtr;
43 }
44 }
45
46 cout << "The total occurrences of \'" << search << "\' in the text is:"
47 << setw( 3 ) << count << endl;
48
49 return 0;
50 }
Enter three lines of text:
one line of text
two lines of text
three lines of text
Enter a search character: e
The total occurrences of 'e' in the text is: 9
1// Exercise 16.27 Solution
2#include <iostream>
516 Bits, Characters, Strings and Structures Solutions Chapter 16
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8#include <iomanip>
9
10 using std::setw;
11
12 #include <cstring>
13 #include <cctype>
14
15 const int SIZE1 = 80, SIZE2 = 26;
16
17 int main()
18 {
19 char text[ 3 ][ SIZE1 ], *searchPtr;
20 int characters[ SIZE2 ] = { 0 }, count = 0;
21
22 cout << "Enter three lines of text:\n";
23
24 for ( int i = 0; i <= 2; ++i )
25 cin.getline( &text[ i ][ 0 ], SIZE1 );
26
27 // convert letters to lowercase
28 for ( int k = 0; k <= 2; ++k )
29 for ( int j = 0; text[ k ][ j ] != '\0'; ++j ) {
30 char c = static_cast< char >( tolower( text[ k ][ j ] ) );
31 text[ k ][ j ] = c;
32 }
33
34 for ( int q = 0; q < SIZE2; ++q ) {
35 count = 0;
36
37 for ( int j = 0; j <= 2; ++j ) {
38 searchPtr = &text[ j ][ 0 ];
39
40 while ( searchPtr = strchr( searchPtr, 'a' + q ) ) {
41 ++count;
42 ++searchPtr;
43 }
44 }
45
46 characters[ q ] = count;
47 }
48
49 cout << "\nThe total occurrences of each character:\n";
50
51 for ( int w = 0; w < SIZE2; ++w )
52 cout << setw( 3 ) << static_cast< char >( 'a' + w ) << ':' << setw( 3 )
53 << characters[ w ] << '\n';
54
55 return 0;
56 }
Chapter 16 Bits, Characters, Strings and Structures Solutions 517
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.28 The chart in Appendix B shows the numeric code representations for the characters in the ASCII character set. Study this
chart, and then state whether each of the following is true or false:
a) The letter “A” comes before the letter “B”.
b) The digit “9” comes before the digit “0”.
c) The commonly used symbols for addition, subtraction, multiplication and division all come before any of the digits.
d) The digits come before the letters.
e) If a sort program sorts strings into ascending sequence, then the program will place the symbol for a right parenthesis
before the symbol for a left parenthesis.
Enter three lines of text:
The yak ran away
A giant parrot flew by
The cat pounced on the rat
The total occurrences of each character:
a: 9
b: 1
c: 2
d: 1
e: 5
f: 1
g: 1
h: 3
i: 1
j: 0
k: 1
l: 1
m: 0
n: 4
o: 3
p: 2
q: 0
r: 4
s: 0
t: 7
u: 1
v: 0
w: 2
x: 0
y: 3
z: 0
1// Exercise 16.28 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9
10 const int SIZE = 20;
11
12 int main()
13 {
14 char array[ 5 ][ SIZE ];
15 int i;
16
17 for ( i = 0; i <= 4; ++i ) {
518 Bits, Characters, Strings and Structures Solutions Chapter 16
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.29 Write a program that reads a series of strings and prints only those strings beginning with the letter “b”.
18 cout << "Enter a string: ";
19 cin.getline( &array[ i ][ 0 ], SIZE );
20 }
21
22 cout << "The strings starting with 'b' are:\n";
23
24 for ( i = 0; i <= 4; ++i )
25 if ( array[ i ][ 0 ] == 'b' )
26 cout << &array[ i ][ 0 ] << '\n';
27
28 return 0;
29 }
Enter a string: c++
Enter a string: apple
Enter a string: burger
Enter a string: band
Enter a string: bag
The strings starting with 'b' are:
burger
band
bag
1// Exercise 16.29 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6
7
8const int SIZE = 20;
9
10 int main()
11 {
12 char array[ 5 ][ SIZE ];
13 int i;
14
15 for ( i = 0; i <= 4; ++i ) {
16 cout << "Enter a string: ";
17 cin.getline( &array[ i ][ 0 ], SIZE );
18 }
19
20 cout << "The strings starting with 'b' are:\n";
21
22 for ( i = 0; i <= 4; ++i )
23 if ( array[ i ][ 0 ] == 'b' )
24 cout << &array[ i ][ 0 ] << '\n';
25
26 return 0;
27 }
Chapter 16 Bits, Characters, Strings and Structures Solutions 519
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.30 Write a program that reads a series of strings and prints only those strings that end with the letters “ED”Write a program
that inputs an ASCII code and prints the corresponding character. Modify this program so that it generates all possible three-digit
codes in the range 000 to 255 and attempts to print the corresponding characters. What happens when this program is runUsing the
ASCII character chart in Appendix B as a guide, write your own versions of the character handling functions in Fig. 16.16.
Enter a string: MOVED
Enter a string: SAW
Enter a string: RAN
Enter a string: CARVED
Enter a string: PROVED
The strings ending with "ED" are:
MOVED
CARVED
PROVED
1// Exercise 16.30 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6
7#include <cstring>
8
9const int SIZE = 20;
10
11 int main()
12 {
13 int length, i;
14 char array[ 5 ][ SIZE ];
15
16 for ( i = 0; i <= 4; ++i ) {
17 cout << "Enter a string: ";
18 cin.getline( &array[ i ][ 0 ], SIZE );
19 }
20
21 cout << "\nThe strings ending with \"ED\" are:\n";
22
23 for ( i = 0; i <= 4; ++i ) {
24 length = strlen( &array[ i ][ 0 ] );
25
26 if ( strcmp( &array[ i ][ length - 2 ], "ED" ) == 0 )
27 cout << &array[ i ][ 0 ] << '\n';
28 }
29
30 return 0;
31 }
Enter an ASCII character code (EOF to end): 44
The corresponding character is ','
Enter an ASCII character code (EOF to end): 77
The corresponding character is 'M'
Enter an ASCII character code (EOF to end): 26
The corresponding character is '
...
520 Bits, Characters, Strings and Structures Solutions Chapter 16
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.31 Write your own versions of the functions in Fig. 16.20 for converting strings to numbers.
16.32 Write your own versions of the functions in Fig. 16.27 for searching strings.
1// Exercise 16.31 Solution
2// NOTE: This solution is easily modified to print all
3// possible three digit codes.
4#include <iostream>
5
6using std::cout;
7using std::cin;
8
9
10 int main()
11 {
12 int c;
13
14 cout << "Enter an ASCII character code (EOF to end): ";
15 cin >> c;
16
17 while ( c != EOF ) {
18 if ( c >= 0 && c <= 255 )
19 cout << "The corresponding character is '"
20 << static_cast< char > ( c ) << "\'\n";
21 else
22 cout << "Invalid character code\n";
23
24 cout << "\nEnter an ASCII character code (EOF to end): ";
25 cin >> c;
26 }
27
28 return 0;
29 }
Enter an ASCII character code (EOF to end): 44
The corresponding character is ','
Enter an ASCII character code (EOF to end): 77
The corresponding character is 'M'
Enter an ASCII character code (EOF to end): 26
The corresponding character is '
...
1// Exercise 16.32 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6
7int isDigit( int );
8int isAlpha( int );
9int isAlNum( int );
10 int isLower( int );
11 int isUpper( int );
12 int isSpace( int );
13 int isPunct( int );
14 int isPrint( int );
Chapter 16 Bits, Characters, Strings and Structures Solutions 521
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
15 int isGraph( int );
16 int toLower( int );
17 int toUpper( int );
18
19 int main()
20 {
21 int v;
22 char a, header[] = "According to",
23 *names[] = { "isDigit ", "isAlpha ", "isAlNum ",
24 "isLower ", "isUpper ", "isSpace ",
25 "isPunct ", "isPrint ", "isGraph ",
26 "toLower ", "toUpper " },
27 *names2[] = { "digit", "letter", "letter/digit", "lowercase",
28 "uppercase", "space", "punctuation", "print", "graph",
29 "converted lowercase", "converted uppercase" };
30 int ( *f[] )( int ) = { isDigit, isAlpha, isAlNum, isLower,
31 isUpper, isSpace, isPunct, isPrint,
32 isGraph, toLower, toUpper };
33
34 cout << "Enter a character: ";
35 cin >> a;
36
37 for ( int k = 0; k < 11; ++k ) {
38 v = ( *f[ k ] )( static_cast< int >( a ) );
39 cout.write( header, 13 );
40 cout << names[ k ] << a << ( !v ? " is not a " : " is a " )
41 << names2[ k ] << " character\n";
42 }
43
44 return 0;
45 }
46
47 // Normally these would return bool, but int return type
48 // is consistent with the ctype library.
49 int isDigit( int c )
50 {
51 return ( c >= 48 && c <= 57 ) ? 1 : 0;
52 }
53
54 int isAlpha( int c )
55 {
56 return ( ( c >= 65 && c <= 90 ) || ( c >= 97 && c <= 122 ) ) ? 1 : 0;
57 }
58
59 int isAlNum( int c )
60 {
61 return ( isDigit( c ) == 1 || isAlpha( c ) == 1 ) ? 1 : 0;
62 }
63
64 int isLower( int c )
65 {
66 return ( c >= 97 && c <= 122 ) ? 1 : 0;
67 }
68
69 int isUpper( int c )
70 {
71 return ( c >= 65 && c <= 90 ) ? 1 : 0;
72 }
73
74 int isSpace( int c )
75 {
76 return ( ( c == 32 ) || ( c >= 9 && c <= 13 ) ) ? 1 : 0;
522 Bits, Characters, Strings and Structures Solutions Chapter 16
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16.33 Write your own versions of the functions in Fig. 16.34 for manipulating blocks of memory.
16.34 (Project: A Spelling Checker) Many popular word-processing software packages have built-in spell checkers. We used
spell-checking capabilities in preparing this book and discovered that no matter how careful we thought we were in writing a chap-
ter, the software was always able to find a few more spelling errors than we were able to catch manually.
In this project, you are asked to develop your own spell-checker utility. We make suggestions to help get you started. You
should then consider adding more capabilities. You may find it helpful to use a computerized dictionary as a source of words.
Why do we type so many words with incorrect spellings? In some cases, it is because we simply do not know the correct
spelling, so we make a “best guess.” In some cases, it is because we transpose two letters (e.g., “defualt” instead of “default”).
Sometimes we double type a letter accidentally (e.g., “hanndy” instead of “handy”). Sometimes we type a nearby key instead of
the one we intended (e.g., “biryhday” instead of “birthday”). And so on.
Design and implement a spell-checker program. Your program maintains an array wordList of character strings. You can
either enter these strings or obtain them from a computerized dictionary.
Your program asks a user to enter a word. The program then looks up that word in the wordList array. If the word is present
in the array, your program should print “Word is spelled correctly.
If the word is not present in the array, your program should print “Word is not spelled correctly.” Then your
program should try to locate other words in wordList that might be the word the user intended to type. For example, you can try
all possible single transpositions of adjacent letters to discover that the word “default” is a direct match to a word in wordList.
77 }
78
79 int isPunct( int c )
80 {
81 return ( isAlNum( c ) == 0 && isSpace( c ) == 0 ) ? 1 : 0;
82 }
83
84 int isPrint( int c )
85 {
86 return ( c >= 32 && c <= 126 ) ? 1 : 0;
87 }
88
89 int isGraph( int c )
90 {
91 return ( c >= 33 && c <= 126 ) ? 1 : 0;
92 }
93
94 int toLower( int c )
95 {
96 return ( isUpper( c ) == 1 ) ? c + 32 : c;
97 }
98
99 int toUpper( int c )
100 {
101 return ( isLower( c ) == 1 ) ? c - 32 : c;
102 }
Enter a character: U
According to isDigit U is not a digit character
According to isAlpha U is a letter character
According to isAlNum U is a letter/digit character
According to isLower U is not a lowercase character
According to isUpper U is a uppercase character
According to isSpace U is not a space character
According to isPunct U is not a punctuation character
According to isPrint U is a print character
According to isGraph U is a graph character
According to toLower U is a converted lowercase character
According to toUpper U is a converted uppercase character
Chapter 16 Bits, Characters, Strings and Structures Solutions 523
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
Of course, this implies that your program will check all other single transpositions, such as “edfault,” “dfeault,” “deafult,”
“defalut” and “defautl.” When you find a new word that matches one in wordList, print that word in a message such as “Did
you mean "default?".”
Implement other tests such as replacing each double letter with a single letter and any other tests you can develop to improve
the value of your spell checker.
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
17
The Preprocessor
Solutions
Solutions
17.4 Write a program that defines a macro with one argument to compute the volume of a sphere. The program should compute
the volume for spheres of radius 1 to 10, and print the results in tabular format. The formula for the volume of a sphere is
( 4.0 / 3 ) * π * r3
where π is 3.14159.
1// Exercise 17.4 Solution
2#include <iostream>
3
4using std::cout;
5using std::ios;
6
7
8#include <iomanip>
9
10 using std::setw;
11 using std::setprecision;
12
13 #define PI 3.14159
14
15 // define macro for sphere volume
16 #define SPHEREVOLUME( r ) ( 4.0 / 3.0 * PI * ( r ) * ( r ) * ( r ) )
17
18 int main()
19 {
20 // print header
21 cout << setw( 10 ) << "Radius" << setw( 10 ) << "Volume\n";
22
23 cout.setf( ios::fixed | ios::showpoint );
24 for ( int i = 1; i <= 10; ++i )
25 cout << setw( 10 ) << i << setw( 10 ) << setprecision( 3 )
26 << SPHEREVOLUME( i ) << '\n';
27
Chapter 17 The Preprocessor Solutions 525
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
17.5 Write a program that produces the following output:
The program should define macro SUM with two arguments, x and y, and use SUM to produce the output.
17.6 Write a program that uses macro MINIMUM2 to determine the smallest of two numeric values. Input the values from the
keyboard.
28 return 0;
29 }
Radius Volume
1 4.189
2 33.510
3 113.097
4 268.082
5 523.598
6 904.778
7 1436.754
8 2144.659
9 3053.625
10 4188.787
The sum of x and y is 13
1// Exercise 17.5 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#define SUM( x, y ) ( ( x ) + ( y ) )
8
9int main()
10 {
11 cout << "The sum of 6 and 7 is " << SUM( 6, 7 ) << endl;
12 return 0;
13 }
The sum of 6 and 7 is 13
1// Exercise 17.6 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setw;
12 using std::setprecision;
13
14 #define MINIMUM2( X, Y ) ( ( X ) < ( Y ) ? ( X ) : ( Y ) )
526 The Preprocessor Solutions Chapter 17
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
17.7 Write a program that uses macro MINIMUM3 to determine the smallest of three numeric values. Macro MINIMUM3 should
use macro MINIMUM2 defined in Exercise 17.6 to determine the smallest number. Input the values from the keyboard.
15
16 int main()
17 {
18 int a, b;
19 double c, d;
20
21 cout << "Enter two integers: ";
22 cin >> a >> b;
23 cout << "The minimum of " << a << " and " << b << " is " << MINIMUM2( a, b )
24 << "\n\n";
25
26 cout << "Enter two doubles: ";
27 cin >> c >> d;
28
29 cout.setf( ios::fixed | ios::showpoint );
30 cout << "The minimum of " << setprecision( 2 ) << c << " and " << d
31 << " is " << MINIMUM2( c, d ) << '\n';
32
33 return 0;
34 }
Enter two integers: 8 22
The minimum of 8 and 22 is 8
Enter two doubles: 73.46 22.22
The minimum of 73.46 and 22.22 is 22.22
1// Exercise 17.7 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setw;
12 using std::setprecision;
13
14 #define MINIMUM2( X, Y ) ( ( X ) < ( Y ) ? ( X ) : ( Y ) )
15 #define MINIMUM3( U, V, W ) ( MINIMUM2( W, MINIMUM2( U, V ) ) )
16
17 int main()
18 {
19 int a, b, c;
20 double d, e, f;
21
22 cout << "Enter three integers: ";
23 cin >> a >> b >> c;
24 cout << "The minimum of " << a << ", " << b << ", and " << c
25 << " is " << MINIMUM3( a, b, c ) << "\n\nEnter three doubles: ";
26
27 cin >> d >> e >> f;
28 cout.setf( ios::fixed | ios::showpoint );
29 cout << "The minimum of " << setprecision( 2 ) << d << ", "
Chapter 17 The Preprocessor Solutions 527
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
17.8 Write a program that uses macro PRINT to print a string value.
17.9 Write a program that uses macro PRINTARRAY to print an array of integers. The macro should receive the array and the
number of elements in the array as arguments.
30 << e << ", and " << f << " is " << MINIMUM3( d, e, f ) << '\n';
31
32 return 0;
33 }
Enter three integers: 44 2 55
The minimum of 44, 2, and 55 is 2
Enter three doubles: 9.5 7.3 3.22
The minimum of 9.50, 7.30, and 3.22 is 3.22
1// Exercise 17.8 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#define PRINT( s ) cout << ( s )
10 #define SIZE 20
11
12 int main()
13 {
14 char text[ SIZE ];
15
16 PRINT( "Enter a string: " );
17 cin >> text;
18
19 PRINT( "The string entered was: " );
20 PRINT( text );
21 PRINT( endl );
22
23 return 0;
24 }
Enter a string: HELLO
The string entered was: HELLO
1// Exercise 17.9 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::ios;
7
8#include <iomanip>
9
10 using std::setw;
11
12 #define PRINTARRAY( A, N ) for ( int i = 0; i < ( N ); ++i ) \
13 cout << setw( 3 ) << A[ i ]
528 The Preprocessor Solutions Chapter 17
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
17.10 Write a program that uses macro SUMARRAY to sum the values in a numeric array. The macro should receive the array and
the number of elements in the array as arguments.
17.11 Rewrite the solutions to Exercises 17.4 to 17.10 as inline functions.
14
15 #define SIZE 10
16
17 int main()
18 {
19 int b[ SIZE ] = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
20
21 cout << "The array values are:\n";
22 PRINTARRAY( b, SIZE );
23 cout << endl;
24 return 0;
25 }
The array values are:
2 4 6 8 10 12 14 16 18 20
1// Exercise 17.10 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6
7#define SUMMARRAY( A, S ) for ( int c = 0; c < S; ++c ) \
8 sum += A[ c ];
9#define SIZE 10
10
11 int main()
12 {
13 int array[ SIZE ] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, sum = 0;
14
15 SUMMARRAY( array, SIZE );
16 cout << "Sum is " << sum << endl;
17 return 0;
18 }
Sum is 55
1// Exercise 17.11 Solution
2// NOTE: Exercises 17.9 and 17.10 cannot be
3// expanded inline because they require the
4// use of for repitition structures
5#include <iostream>
6
7using std::cout;
8using std::endl;
9using std::ios;
10
11 #include <iomanip>
12
13 using std::setw;
14 using std::setprecision;
15
Chapter 17 The Preprocessor Solutions 529
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
16 #define PI 3.14159
17
18 inline double sphereVolume( int r )
19 { return 4.0 / 3.0 * PI * ( r ) * ( r ) * ( r ); }
20 inline int sum( int x, int y ) { return x + y; }
21 inline int minimum2( int x, int y ) { return x < y ? x : y; }
22 inline int minimum3( int x, int y, int z )
23 { return minimum2( z, minimum2( x, y ) ); }
24 inline void print( char const * const cPtr ) { cout << cPtr; }
25
26 int main()
27 {
28 // print header
29 cout << "Function sphereVolume as an inline function:\n"
30 << setw( 10 ) << "Radius" << setw( 10 ) << "Volume\n";
31
32 cout.setf( ios::fixed | ios::showpoint );
33 for ( int i = 1; i <= 10; ++i )
34 cout << setw( 10 ) << i << setw( 10 ) << setprecision( 3 )
35 << sphereVolume( i ) << '\n';
36
37 int x = 6, y = 7;
38 cout << "\nFunction sum as an inline function:\n"
39 << "The sum of " << x << " and " << y << " is "
40 << sum( 6, 7 ) << '\n';
41
42 cout << "\nFunction minimum2 as an inline function:\n"
43 << "The minimum of " << x << " and " << y << " is "
44 << minimum2( x, y ) << '\n';
45
46 int z = 4;
47 cout << "\nFunction minimum3 as an inline function:\n"
48 << "The minimum of " << x << ", " << y << " and " << z << " is "
49 << minimum3( x, y, z ) << '\n';
50
51 char s[] = "string...";
52 cout << "\nFunction print as an inline function:\n"
53 << "The output of print is: ";
54 print( s );
55 cout << endl;
56
57 return 0;
58 }
530 The Preprocessor Solutions Chapter 17
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
17.12 For each of the following macros, identify the possible problems (if any) when the preprocessor expands the macros:
a) #define SQR( x ) x * x
ANS: When x is an expression, such as z - y.
b) #define SQR( x ) ( x * x )
ANS: When x is an expression, such as z - y.
c) #define SQR( x ) ( x ) * ( x )
ANS: When SQR( x ) is used in an expression such as 12 / SQR( 2 ).
d) #define SQR( x ) ( ( x ) * ( x ) )
ANS: No problems.
Function sphereVolume as an inline function:
Radius Volume
1 4.189
2 33.510
3 113.097
4 268.082
5 523.598
6 904.778
7 1436.754
8 2144.659
9 3053.625
10 4188.787
Function sum as an inline function:
The sum of 6 and 7 is 13
Function minimum2 as an inline function:
The minimum of 6 and 7 is 6
Function minimum3 as an inline function:
The minimum of 6, 7 and 4 is 4
Function print as an inline function:
The output of print is: string...
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
18
C Legacy
Code Topics
Solutions
Solutions
18.2 Write a program that calculates the product of a series of integers that are passed to function product using a variable-
length argument list. Test your function with several calls, each with a different number of arguments.
1// Exercise 18.2 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <cstdarg>
10
11 int sum( int, ... );
12
13 int main()
14 {
15 int a = 1, b = 2, c = 3, d = 4, e = 5;
16
17 cout << "a = " << a << ", b = " << b << ", c = " << c << ", d = " << d
18 << ", e = " << e << "\n\n";
19
20 cout << "The sum of a and b is: " << sum( 2, a, b )
21 << "\nThe sum of a, b, and c is: " << sum( 3, a, b, c )
22 << "\nThe sum of a, b, c, and d is: " << sum( 4, a, b, c, d )
23 << "\nThe sum of a, b, c, d, and e is: " << sum( 5, a, b, c, d, e )
24 << endl;
25
26 return 0;
27 }
28
29 int sum( int i, ... )
30 {
31 int total = 0;
532 C Legacy Code Topics Solutions Chapter 18 Solutions
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
18.3 Write a program that prints the command-line arguments of the program.
18.4 Write a program that sorts an integer array into ascending order or descending order. The program should use command-
line arguments to pass either argument -a for ascending order or -d for descending order. (Note: This is the standard format for
passing options to a program in UNIX.)
32 va_list ap;
33
34 va_start( ap, i );
35
36 // calculate total
37 for ( int j = 1; j <= i; ++j )
38 total += va_arg( ap, int );
39
40 va_end( ap );
41 return total;
42 }
a = 1, b = 2, c = 3, d = 4, e = 5
The sum of a and b is: 3
The sum of a, b, and c is: 6
The sum of a, b, c, and d is: 10
The sum of a, b, c, d, and e is: 15
1// Exercise 18.3 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7
8using std::ios;
9
10 int main( int argc, char *argv[] )
11 {
12 cout << "The command line arguments are:\n";
13
14 for ( int i = 0; i < argc; ++i )
15 cout << argv[ i ] << ' ';
16
17 return 0;
18 }
c:\>p18_03.exe arg1 arg2 arg3
The command line arguments are:
p18_03.exe arg1 arg2 arg3
1// Exercise 18.4 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6
7#include <iomanip>
8using std::setw;
9
Chapter 18 Solutions C Legacy Code Topics Solutions 533
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
18.5 Read the manuals for your system to determine what signals are supported by the signal-handling library (csignal).
Write a program with signal handlers for the signals SIGABRT and SIGINT. The program should test the trapping of these signals
by calling function abort to generate a signal of type SIGABRT and by pressing Ctrl c to generate a signal of type SIGINT.
10 const int SIZE = 100;
11
12 void swap( int * const, int * const );
13
14 int main( int argc, char *argv[] )
15 {
16 int a[ SIZE ];
17 bool order;
18
19 if ( argc != 2 )
20 cout << "Usage: p18_4 -option\n";
21 else {
22 cout << "Enter up to " << SIZE << " integers (EOF to end input): ";
23
24 for ( int count = 0; !( cin.eof() ) && count < SIZE; ++count )
25 cin >> a[ count ];
26
27 // count is incremented before for loop continuation fails
28 --count;
29 order = ( argv[ 1 ][ 1 ] == 'd' ) ? true : false;
30
31 for ( int i = 1; i < count; ++i )
32 for ( int j = 0; j < count - 1; ++j )
33 if ( order ) {
34 if ( a[ i ] > a[ j ] )
35 swap( &a[ i ], &a[ j ] );
36 }
37 else if ( a[ i ] < a[ j ] )
38 swap( &a[ j ], &a[ i ] );
39
40 cout << "\n\nThe sorted array is:\n";
41
42 for ( int j = 0; j < count; ++j )
43 cout << setw( 3 ) << a[ j ];
44
45 cout << '\n';
46 }
47
48 return 0;
49 }
50
51 void swap( int * const xPtr, int * const yPtr )
52 {
53 int temp;
54
55 temp = *xPtr;
56 *xPtr = *yPtr;
57 *yPtr = temp;
58 }
c:\>p18_04.exe -d
Enter up to 100 integers (EOF to end input): 77 2 -8 9 44 8 76 41 99
The sorted array is:
99 77 76 44 41 9 8 2 -8
534 C Legacy Code Topics Solutions Chapter 18 Solutions
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
18.6 Write a program that dynamically allocates an array of integers. The size of the array should be input from the keyboard.
The elements of the array should be assigned values input from the keyboard. Print the values of the array. Next, reallocate the mem-
ory for the array to half of the current number of elements. Print the values remaining in the array to confirm that they match the
first half of the values in the original array.
1// Exercise 18.6 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10 using std::setw;
11 using std::setprecision;
12 using std::setiosflags;
13
14 #include <cstdlib>
15
16 int main()
17 {
18 int count, *array;
19
20 cout << "This program dynamically allocates an array of integers."
21 << "\nEnter the number of elements in the array: ";
22 cin >> count;
23
24 // allocate memory
25 array = static_cast< int * >( calloc( count, sizeof( int ) ) );
26
27 for ( int i = 0; i < count; ++i ) {
28 cout << "Enter an integer: ";
29 cin >> array[ i ];
30 }
31
32 cout << "\nThe elements of the array are:\n";
33
34 for ( int j = 0; j < count; ++j )
35 cout << setw( 3 ) << array[ j ];
36
37 // reallocate to half the original size
38 realloc( array, count / 2 * sizeof( int ) );
39 cout << "\n\nThe elements of the array after reallocation are:\n";
40
41 for ( int k = 0; k < count / 2; ++k )
42 cout << setw( 3 ) << array[ k ];
43
44 cout << '\n';
45
46 return 0;
47 }
Chapter 18 Solutions C Legacy Code Topics Solutions 535
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
18.7 Write a program that takes two file names as command-line arguments, reads the characters from the first file one at a time
and writes the characters in reverse order to the second file.
This program dynamically allocates an array of integers.
Enter the number of elements in the array: 5
Enter an integer: 1
Enter an integer: 2
Enter an integer: 3
Enter an integer: 4
Enter an integer: 5
The elements of the array are:
1 2 3 4 5
The elements of the array after reallocation are:
1 2
1// Exercise 18.7 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8using std::cerr;
9using std::istream;
10 using std::ostream;
11
12 #include <fstream>
13
14 using std::ofstream;
15 using std::ifstream;
16
17 void reverseFile( istream&, ostream& );
18
19 int main( int argc, char *argv[] )
20 {
21 ifstream inFile( argv[ 1 ], ios::in );
22 ofstream outFile( argv[ 2 ], ios::out );
23
24 if ( argc != 3 )
25 cout << "Usage: copy infile outfile\n";
26 else
27 if ( inFile )
28 if ( outFile )
29 reverseFile( inFile, outFile );
30 else
31 cerr << "File \"" << argv[ 2 ] << "\" could not be opened\n";
32 else
33 cerr << "File \"" << argv[ 1 ] << "\" could not be opened\n";
34
35 return 0;
36 }
37
38 void reverseFile( istream &in, ostream &out )
39 {
40 int c;
41
42 if ( ( c = in.get() ) != EOF )
43 reverseFile( in, out );
536 C Legacy Code Topics Solutions Chapter 18 Solutions
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
18.8 Write a program that uses goto statements to simulate a nested looping structure that prints a square of asterisks as follows:
The program should use only the following three output statements:
cout << '*';
cout << ' ';
cout << endl;
44 else
45 return; // do not write EOF character
46
47 out.put( static_cast< char > ( c ) );
48 }
c:\>p18_07.exe test.txt copy.txt
*****
* *
* *
* *
*****
1// Exercise 18.8 Solution
2#include <iostream>
3
4using std::cout;
5using std::cin;
6
7
8
9int main()
10 {
11 int size, row = 0, col;
12
13 cout << "Enter the side length of the square: ";
14 cin >> size;
15
16 start: // label
17 ++row;
18 cout << '\n';
19
20 if ( row > size )
21 goto end;
22
23 col = 1;
24
25 innerLoop: // label
26 if ( col > size )
27 goto start;
28
29 cout << ( row == 1 || row == size || col == 1 ||
30 col == size ? '*' : ' ' );
31
32 ++col;
33 goto innerLoop;
34
35 end: // label
Chapter 18 Solutions C Legacy Code Topics Solutions 537
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
18.9 Provide the definition for union Data containing char c, short s, long l, float f and double d.
ANS:
union Data {
char c;
short s;
long l;
float f;
double d;
};
18.10 Create union Integer with members char c, short s, int i and long l. Write a program that inputs values of
type char, short, int and long and stores the values in union variables of type union Integer. Each union variable
should be printed as a char, a short, an int and a long. Do the values always print correctly?
36
37 return 0;
38 }
Enter the side length of the square: 5
*****
* *
* *
* *
*****
1// Exercise 18.10 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9union Integer {
10 char c;
11 short s;
12 int i;
13 long l;
14 };
15
16 void printUnion( Integer );
17
18 int main()
19 {
20 Integer value;
21
22 cout << "Enter a character: ";
23 value.c = static_cast< char >( cin.get() );
24 printUnion( value );
25
26 cout << "Enter a short: ";
27 cin >> value.s;
28 printUnion( value );
29
30 cout << "Enter an int: ";
31 cin >> value.i;
32 printUnion( value );
33
538 C Legacy Code Topics Solutions Chapter 18 Solutions
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
18.11 Create union FloatingPoint with members float f, double d and long double l. Write a program that inputs
value of type float, double and long double and stores the values in union variables of type union FloatingPoint.
Each union variable should be printed as a float, a double and a long double. Do the values always print correctly?
34 cout << "Enter a long: ";
35 cin >> value.l;
36 printUnion( value );
37
38 return 0;
39 }
40
41 void printUnion( Integer x )
42 {
43 cout << "Current values in union Integer are:\n"
44 << "char c = " << x.c
45 << "\nshort s = " << x.s
46 << "\nint i = " << x.i
47 << "\nlong l = " << x.l << "\n\n";
48 }
Enter a character: w
Current values in union Integer are:
char c = w
short s = -13193
int i = -858993545
long l = -858993545
Enter a short: 5
Current values in union Integer are:
char c = ?
short s = 5
int i = -859045883
long l = -859045883
Enter an int: 9999
Current values in union Integer are:
char c = ¤
short s = 9999
int i = 9999
long l = 9999
Enter a long: 1000000
Current values in union Integer are:
char c = @
short s = 16960
int i = 1000000
long l = 1000000
1// Exercise 18.11 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9union FloatingPoint {
10 float f;
11 double d;
Chapter 18 Solutions C Legacy Code Topics Solutions 539
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
18.12 Given the union
union A {
double y;
char *z;
};
which of the following are correct statements for initializing the union?
a) A p = B; // B is of same type as A
ANS: Correct.
12 long double l;
13 };
14
15 void printUnion( FloatingPoint );
16
17 int main()
18 {
19 FloatingPoint value;
20
21 cout << "Enter a float: ";
22 cin >> value.f;
23 printUnion( value );
24
25 cout << "Enter a double: ";
26 cin >> value.d;
27 printUnion( value );
28
29 cout << "Enter a long double: ";
30 cin >> value.l;
31 printUnion( value );
32
33 return 0;
34 }
35
36 void printUnion( FloatingPoint x )
37 {
38 cout << "Current values in union Integer are:\n"
39 << "float f = " << x.f
40 << "\ndouble d = " << x.d
41 << "\nlong double l = " << x.l << "\n\n";
42 }
Enter a float: 4.567
Current values in union Integer are:
float f = 4.567
double d = -9.25596e+061
long double l = -9.25596e+061
Enter a double: 9998888.765
Current values in union Integer are:
float f = 3.24255e-024
double d = 9.99889e+006
long double l = 9.99889e+006
Enter a long double: 5e306
Current values in union Integer are:
float f = 0.0210515
double d = 5e+306
long double l = 5e+306
540 C Legacy Code Topics Solutions Chapter 18 Solutions
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
b) A q = x; // x is a double
ANS: Incorrect.
c) A r = 3.14159;
ANS: Incorrect.
d) A s = { 79.63 };
ANS: Correct.
e) A t = { "Hi There!" };
ANS: Incorrect.
f) A u = { 3.14159, "Pi" };
ANS: Incorrect.
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
19
Class string and String
Stream Processing
Solutions
Solutions
19.4 Fill in the blanks in each of the following:
a) Functions , and convert strings to C-style strings.
ANS: data, c_str, copy
b) Function is used for assignment.
ANS: assign
c) is the return type of function rbegin.
ANS: string::reverse_iterator
d) Function is used to retrieve a substring.
ANS: substr
19.5 State which of the following statements are true and which are false. If a statement is false, explain why.
a) strings are null terminated.
ANS: False. strings are not necessarily null terminated.
b) Function max_size returns the maximum size for a string.
ANS: True.
c) Function at is capable of throwing an out_of_range exception.
ANS: True.
d) Function begin returns an iterator.
ANS: True ( string::iterator is more precise).
e) strings are passed by reference by default.
ANS: False. By default, strings are passed by value.
19.6 Find any error(s) in each of the following and explain how to correct it (them):
a) std::cout << s.data() << std::endl; // s is "hello"
ANS: The array returned by data is not null terminated.
b) erase( s.rfind( "x" ), 1 ); // s is "xenon"
ANS: Function erase is a string class member function (i.e., erase must be called by an object of type string).
c) string& foo( void )
{
string s( "Hello" );
... // other statements of function
return;
}
542 Class string and String Stream Processing Solutions Chapter 19
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
ANS: A value is not being returned from the function (i.e., the return statement should be return s;). The return
type should be string not string&.
19.7 (Simple Encryption) Some information on the Internet may be encrypted with a simple algorithm known as “rot13”—which
rotates each character by 13 positions in the alphabet. Thus, 'a' corresponds to 'n', and 'x' corresponds to 'k'. rot13 is an
example of symmetric key encryption. With symmetric key encryption, both the encrypter and decrypter use the same key.
a) Write a program that encrypts a message using rot13.
b) Write a program that decrypts the scrambled message using 13 as the key.
c) After writing the programs of part (a) and part (b) briefly answer the following question: If you did not know the key
for part (b), how difficult do you think it would be to break the code using any resources available? What if you had
access to substantial computing power (e.g., Cray supercomputers)? In Exercise 19.27 we ask you to write a program
to accomplish this.
1// Execise 19.07 Part A Solution
2// When solving Part B of this exercise, you
3// might find it more convenient to only use
4// uppercase letters for you input.
5#include <iostream>
6
7using std::cout;
8using std::endl;
9using std::cin;
10 using std::ios;
11
12 #include <string>
13 using std::string;
14 using std::getline;
15
16 int main()
17 {
18 string m;
19 int key = 13; // Our key for encryption
20
21 cout << "Enter a string:";
22 getline( cin, m );
23
24 string::iterator mi = m.begin();
25
26 while ( mi != m.end() ) {
27 *mi += key;
28 ++mi;
29 }
30
31 cout << "\nEncypted string is:" << m << endl;
32
33 return 0;
34 }
Enter a string:JAMES BOND IS 007
Encypted string is:WNZR`-O\[Q-V`-==D
1// Execise 19.07 Part B Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
Chapter 19 Class string and String Stream Processing Solutions 543
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
19.8 Write a program using iterators that demonstrates the use of functions rbegin and rend.
9#include <string>
10 using std::string;
11 using std::getline;
12
13 int main()
14 {
15 string m;
16 int key = 13; // Our key for decryption
17
18 cout << "Enter encrypted string:";
19 getline( cin, m );
20
21 string::iterator mi = m.begin();
22
23 while ( mi != m.end() ) {
24 *mi -= key;
25 ++mi;
26 }
27
28 cout << "\nDecypted string is:" << m << endl;
29
30 return 0;
31 }
Enter encrypted string:WNZR`-O\[Q-V`-==D
Decypted string is:JAMES BOND IS 007
1// Exercise 19.8 Solution
2// Program demonstrates rend and rbegin.
3#include <iostream>
4
5using std::cout;
6using std::endl;
7using std::cin;
8using std::ios;
9
10 #include <string>
11 using std::string;
12
13 int main()
14 {
15 string s( "abcdefghijklmnopqrstuvwxyz" );
16 string::reverse_iterator re = s.rend(),
17 rb = s.rbegin();
18
19 cout << "Using rend() string is: ";
20 while ( re >= s.rbegin() ) {
21 cout << *re;
22 --re;
23 }
24
25 cout << "\nUsing rbegin() string is: ";
26 while ( rb != s.rend() ) {
27 cout << *rb;
28 ++rb;
29 }
30
544 Class string and String Stream Processing Solutions Chapter 19
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
19.9 Write your own versions of functions data and c_str.
19.10 Write a program that reads in several strings and prints only those ending in “ r” or “ay”. Only lowercase letters should
be considered.
19.11 Write a program that demonstrates passing a string both by reference and by value.
31 cout << endl;
32
33 return 0;
34 }
Using rend() string is: abcdefghijklmnopqrstuvwxyz
Using rbegin() string is: zyxwvutsrqponmlkjihgfedcba
1// Exercise 19.10 Solution
2// Program determines if string ends in 'r'
3// or "ay".
4#include <iostream>
5
6using std::cout;
7using std::endl;
8using std::cin;
9using std::ios;
10
11 #include <string>
12 using std::string;
13
14 int main()
15 {
16 string s[ 5 ];
17
18 for ( int i = 0; i < 5; ++i ) {
19 cout << "Enter a word: ";
20 cin >> s[ i ];
21 }
22
23 for ( int j = 0; j < 5; ++j ) {
24 if ( ( ( s[ j ].rfind( "ay" ) == s[ j ].length() - 2 ) )
25 || ( s[ j ].rfind( "r" ) == s[ j ].length() - 1 ) )
26 cout << s[ j ] << endl;
27 }
28
29 return 0;
30 }
Enter a word: bicycle
Enter a word: car
Enter a word: tree
Enter a word: canary
Enter a word: iron
car
1// Exercise 19.11 Solution
2// Program passes a string by value and
3// passes a string by reference.
4#include <iostream>
Chapter 19 Class string and String Stream Processing Solutions 545
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
19.12 Write a program that separately inputs a first name and a last name and then concatenates the two into a new string.
5
6using std::cout;
7using std::endl;
8using std::cin;
9using std::ios;
10
11 #include <string>
12 using std::string;
13
14 void byValue( string );
15 void byReference( string& );
16
17 int main()
18 {
19 string s = "Standard C++ draft standard";
20
21 cout << "Original string: " << s;
22
23 byValue( s );
24 cout << "\nAfter calling byValue: " << s;
25
26 byReference( s );
27 cout << "\nAfter calling byReference: " << s << endl;
28
29 return 0;
30 }
31
32 void byValue( string s )
33 {
34 s.erase( 0, 4 );
35 }
36
37 void byReference( string& sRef )
38 {
39 sRef.erase( 0, 9 );
40 }
Original string: Standard C++ draft standard
After calling byValue: Standard C++ draft standard
After calling byReference: C++ draft standard
1// Exercise 19.12 Solution
2// Program reads a first name and
3// last name and concatenates the two.
4#include <iostream>
5using std::cout;
6using std::endl;
7using std::cin;
8using std::ios;
9
10 #include <string>
11 using std::string;
12
13 #include <iomanip>
14
15 using std::setw;
16 using std::setprecision;
546 Class string and String Stream Processing Solutions Chapter 19
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
19.13 Write a program that plays the game of hangman. The program should pick a word (which is either coded directly into the
program or read from a text file) and display the following:
Guess the word: XXXXXX
Each X represents a letter. If the user guesses correctly, the program should display:
Congratulations!!! You guessed my word. Play again? yes/no
The appropriate response yes or no should be input. If the user guesses incorrectly, display the appropriate body part.
After seven incorrect guesses, the user should be hanged. The display should look like
O
/|\
|
/ \
After each guess you want to display all their guesses.
17 using std::setiosflags;
18
19 int main()
20 {
21 string first, last;
22
23 cout << "Enter first name: ";
24 cin >> first;
25
26 cout << "Enter last name: ";
27 cin >> last;
28
29 first.append( " " ).append( last );
30 cout << "The full name is: " << first << endl;
31
32 return 0;
33 }
Enter first name: Hans
Enter last name: Gruber
The full name is: Hans Gruber
1// Exercise 19.13 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <string>
10 using std::string;
11
12 #include <cctype>
13
14 #include <iomanip>
15
16 using std::setw;
17 using std::setprecision;
18 using std::setiosflags;
Chapter 19 Class string and String Stream Processing Solutions 547
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
19
20 #include <cstdlib>
21
22 int main()
23 {
24 string response; // "yes"/"no" input from user
25 int w = 0; // index for current word
26 const int WORDS = 4; // total number of words
27
28 do {
29 const char body[] = " o/|\\|/\\"; // body parts
30 string words[ WORDS ] = { "MACAW", "SADDLE",
31 "TOASTER", "XENOCIDE" };
32 string xword( words[ w ].length(), '?' ); // masked display
33 string::iterator i, ix = xword.begin();
34 char letters[ 26 ] = { '\0' }; // letters guessed
35 int n = 0, xcount = xword.length();
36 bool found = false, solved = false;
37 int offset = 0, bodyCount = 0;
38 bool hung = false;
39
40 // clear window; system is a stdlib function
41 system( "cls" ); // "cls" for DOS; "clear" for unix
42
43 do {
44 cout << "\n\nGuess a letter (case does"
45 << " not matter): " << xword << "\n?";
46 char temp;
47 cin >> temp; // letter guessed
48
49 if ( !isalpha( temp ) ) { // validate for letters
50 cout << "\nLETTERS ONLY PLEASE\n";
51 continue; // next iteration of do/while
52 }
53
54 letters[ n ] = toupper( temp ); // convert to uppercase
55
56 system( "cls" ); // "cls" for DOS; "clear" for unix
57
58 // seach word for letters
59 i = words[ w ].begin(); // initialize iterator to beginning
60 found = false; // assume letter is not found in word
61 offset = 0; // initial position set to 0
62
63 // replace letter in mask string in all the necessary
64 // places. decrement count of characters masked such
65 // that we know when word is solved.
66 while ( i != words[ w ].end() ) {
67
68 if ( *i == letters[ n ] ) {
69 *( ix + offset ) = *i;
70 found = true;
71
72 if ( --xcount == 0 )
73 solved = true;
74 }
75
76 ++i;
77 ++offset;
78 }
79
80 if ( !found ) // if the letter was not found
548 Class string and String Stream Processing Solutions Chapter 19
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
81 ++bodyCount; // increment our count of incorrect guesses.
82
83 // graphically draw the pieces of the body
84 // based upon the number of incorrect answers.
85 bool newline = false;
86 for ( int q = 1; q <= bodyCount; ++q ) {
87 if ( q == 1 || q == 5 || q == 7 ) {
88 newline = true;
89 cout << body[ 0 ]; // output space
90 }
91 else if ( q == 4 )
92 newline = true;
93 else
94 newline = false;
95
96 cout << body[ q ];
97
98 if ( newline )
99 cout << '\n';
100 }
101
102 // test to see if guesses were exceeded.
103 if ( bodyCount == 7 ) {
104 cout << "\n\n...GAME OVER...\n";
105 hung = true;
106 break;
107 }
108
109 // display all guesses. note we did not provide
110 // the code that would politely refuse duplicates.
111 cout << "\n\n\nYour guesses:\n";
112 for ( int k = 0; k <= n; k++ )
113 cout << setw( 2 ) << letters[ k ];
114
115 ++n;
116 } while ( !solved );
117
118 cout << "\n\nWord: " << words[ w ] << "\n\n";
119
120 if ( !hung )
121 cout << "\nCongratulations!!! You guessed "
122 << "my word.\n";
123
124 // if we are out of words, then time to exit loop
125 if ( ++w >= WORDS )
126 break;
127
128 cout << "Play again (yes/no)? ";
129 cin >> response;
130
131 } while ( !response.compare( "yes" ) );
132
133 cout << "\nThank you for playing hangman." << endl;
134
135 return 0;
136 }
Chapter 19 Class string and String Stream Processing Solutions 549
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
19.14 Write a program that inputs a string and prints the string backwards. Convert all uppercase characters to lowercase
and all lowercase characters to uppercase.
Your guesses:
M
Guess a letter (case does not matter): M????
?a
Your guesses:
M A
...
o
/|\
|
/
Your guesses:
M A E I O U N K C W
Word: MACAW
Congratulations!!! You guessed my word.
Play again (yes/no)? n
Thank you for playing hangman.
1// Exercise 19.14 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <string>
10 using std::string;
11
12 #include <cctype>
13
14 int main()
15 {
16 string s;
17
18 cout << "Enter a string: ";
19 getline( cin, s, '\n' );
20
21 string::reverse_iterator r = s.rbegin();
22
23 while ( r != s.rend() ) {
24 *r = ( isupper( *r ) ? tolower( *r ): toupper( *r ) );
25 cout << *( r++ );
26 }
27
28 cout << endl;
29
30 return 0;
550 Class string and String Stream Processing Solutions Chapter 19
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
19.15 Write a program that uses the comparison capabilities introduced in this chapter to alphabetize a series of animal names.
Only uppercase letters should be used for the comparisons.
31 }
Enter a string: The sinking of HMS Titanic
CINATIt smh FO GNIKNIS EHt
1// Exercise 19.15 Solution
2// NOTE: The problem description should have asked
3// the programmer to use a quicksort.
4#include <iostream>
5
6using std::cout;
7using std::endl;
8using std::cin;
9using std::ios;
10
11 #include <string>
12 using std::string;
13
14 void output( const string const *, const int );
15 void quickSort( string [], int, int );
16
17 int main()
18 {
19 string animals[] = { "Macaw", "Lion", "Tiger",
20 "Bear", "Toucan", "Zebra",
21 "Puma", "Cat", "Yak", "Boar",
22 "Fox", "Ferret", "Crocodile",
23 "Alligator", "Elk", "Ox",
24 "Horse", "Eagle", "Hawk" };
25
26 cout << "before:";
27 output( animals, 19 );
28
29 quickSort( animals, 0, 19 );
30
31 cout << "\nafter:";
32 output( animals, 19 );
33
34 return 0;
35 }
36
37 void output( const string * const ani, const int length )
38 {
39 for ( int j = 0; j < length; ++j )
40 cout << ( j % 10 ? ' ': '\n' ) << ani[ j ];
41
42 cout << endl;
43 }
44
45 void quickSort( string a[], int first, int last )
46 {
47 int partition( string [], int, int );
48 int currentLocation;
49
50 if ( first >= last )
51 return;
Chapter 19 Class string and String Stream Processing Solutions 551
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
19.16 Write a program that creates a cryptogram out of a string. A cryptogram is a message or word where each letter is re-
placed with another letter. For example the string
The birds name was squawk
might be scrambled to form
xms kbypo zhqs fho obrhfu
Note that spaces are not scrambled. In this particular case, ’T’ was replaced with ’x’, each ’a’ was replaced with ’h’, etc.
Uppercase letters and lowercase letters should be treated the same. Use techniques similar to those in Exercise 19.7.
52
53 currentLocation = partition( a, first, last );
54 quickSort( a, first, currentLocation - 1 );
55 quickSort( a, currentLocation + 1, last );
56 }
57
58 int partition( string b[], int left, int right )
59 {
60 int pos = left;
61
62 while ( true ) {
63
64 while ( b[ pos ] <= b[ right ] && pos != right )
65 --right;
66
67 if ( pos == right )
68 return pos;
69
70 if ( b[ pos ] > b[ right ] ) {
71 b[ pos ].swap( b[ right ] );
72 pos = right;
73 }
74
75 while ( b[ left ] <= b[ pos ] && pos != left )
76 ++left;
77
78 if ( pos == left )
79 return pos;
80
81 if ( b[ left ] > b[ pos ] ) {
82 b[ pos ].swap( b[ left ] );
83 pos = left;
84 }
85 }
86 }
before:
Macaw Lion Tiger Bear Toucan Zebra Puma Cat Yak Boar
Fox Ferret Crocodile Alligator Elk Ox Horse Eagle Hawk
after:
Alligator Bear Boar Cat Crocodile Eagle Elk Ferret Fox Hawk
Horse Lion Macaw Ox Puma Tiger Toucan Yak Zebra
552 Class string and String Stream Processing Solutions Chapter 19
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
1// Exercise 19.16 Solution
2// Program creates a cryptogram from a string.
3#include <iostream>
4
5using std::cout;
6using std::endl;
7using std::cin;
8using std::ios;
9
10 #include <string>
11 using std::string;
12 using std::getline;
13
14 #include <cstdlib>
15 #include <ctime>
16 #include <cctype>
17
18 void convertToLower( string::iterator,
19 string::iterator );
20
21 int main()
22 {
23 string s, alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
24 string::iterator is, is2, is3;
25
26 srand( time( 0 ) );
27 cout << "Enter a string: ";
28 getline( cin, s, '\n' ); // allow white space to be read
29
30 is = s.begin();
31 convertToLower( is, s.end() );
32 string s2( s ); // instantiate s2
33
34 is3 = s2.begin();
35
36 do {
37 is2 = is3; // position location on string s2
38
39 // do not change spaces
40 if ( *is == ' ' ) {
41 is++;
42 continue;
43 }
44
45 int x = rand() % alpha.length(); // pick letter
46 char c = alpha.at( x ); // get letter
47 alpha.erase( x, 1 ); // remove picked letter
48
49 // iterate along s2 doing replacement
50 while ( is2 != s2.end() ) {
51 if ( *is2 == *is )
52 *is2 = c;
53
54 ++is2;
55 }
56
57 ++is3; // position to next element
58 ++is; // position to next element
59 } while ( is != s.end() );
60
Chapter 19 Class string and String Stream Processing Solutions 553
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
19.17 Modify the previous exercise to allow a user to solve the cryptogram by inputting two characters. The first character spec-
ifies the letter in the cryptogram and the second letter specifies the user’s guess. For example, if the user inputs r g, then the user
is guessing that the letter r is really a g.
19.18 Write a program that inputs a sentence and counts the number of palindromes in the sentence. A palindrome is a word that
reads the same backwards and forwards. For example, "tree" is not a palindrome but "noon" is.
19.19 Write a program that counts the total number of vowels in a sentence. Output the frequency of each vowel.
19.20 Write a program that inserts the characters "******" in the exact middle of a string.
19.21 Write a program that erases the sequences "by" and "BY" from a string.
61 // change s2 to lowercase
62 is3 = s2.begin();
63 convertToLower( is3, s2.end() );
64
65 // output strings
66 cout << "Original string: " << s
67 << "\nCryptogram of string: " << s2 << endl;
68
69 return 0;
70 }
71
72 void convertToLower( string::iterator i,
73 string::iterator e )
74 {
75 while ( i != e ) {
76 *i = tolower( *i );
77 ++i;
78 }
79 }
Enter a string: a cold hard rain fell
Original string: a cold hard rain fell
Cryptogram of string: k yivu rkou okdj cmvv
1// Exercise 19.21 Solution
2// Program erases "by" or "BY" from strings.
3#include <iostream>
4
5using std::cout;
6using std::endl;
7using std::cin;
8using std::ios;
9
10 #include <string>
11 using std::string;
12
13 void deleteBy( string&, string );
14
15 int main()
16 {
17 string s;
18
19 cout << "Enter a word:";
20 cin >> s;
21
22 deleteBy( s, "by" );
23 deleteBy( s, "BY" );
24
554 Class string and String Stream Processing Solutions Chapter 19
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
19.22 Write a program that inputs a line of text, replaces all punctuation marks with spaces and then uses the C-string library func-
tion strtok to tokenize the string into individual words.
19.23 Write a program that inputs a line of text and prints the text backwards. Use iterators in your solution.
25 cout << s << endl;
26
27 return 0;
28 }
29
30
31 void deleteBy( string& sRef, string z )
32 {
33 int x = sRef.find( z );
34 while ( x <= sRef.length() ) {
35 sRef.erase( x, 2 );
36 x = sRef.find( z );
37 }
38 }
Enter a word:DERBY
DER
1// Exercise 19.23 Solution
2// Program prints a string backwards.
3#include <iostream>
4
5using std::cout;
6using std::endl;
7using std::cin;
8using std::ios;
9
10 #include <string>
11 using std::string;
12 using std::getline;
13
14 int main()
15 {
16 string s;
17
18 cout << "Enter a string: ";
19 getline( cin, s, '\n' );
20 string::reverse_iterator rb = s.rbegin();
21
22 while ( rb != s.rend() ) {
23 cout << *rb;
24 ++rb;
25 }
26
27 cout << endl;
28
29 return 0;
30 }
Enter a string: PRINT THIS BACKWARDS
SDRAWKCAB SIHT TNIRP
Chapter 19 Class string and String Stream Processing Solutions 555
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
19.24 Write a recursive version of Exercise 19.23.
19.25 Write a program that demonstrates the use of the erase functions that take iterator arguments.
1// Exercise 19.23 Solution
2// Program recursively prints a string backwards.
3#include <iostream>
4
5using std::cout;
6using std::endl;
7using std::cin;
8using std::ios;
9
10 #include <string>
11 using std::string;
12 using std::getline;
13
14 void printBackwards( const string::reverse_iterator,
15 string::reverse_iterator );
16
17 int main()
18 {
19 string s;
20
21 cout << "Enter a string: ";
22 getline( cin, s );
23 string::reverse_iterator r = s.rend();
24
25 printBackwards( s.rbegin(), r - 1 );
26 cout << endl;
27
28 return 0;
29 }
30
31 void printBackwards( const string::reverse_iterator s,
32 string::reverse_iterator rb )
33 {
34 if ( rb == s - 1 )
35 return;
36
37 printBackwards( s, rb - 1 );
38 cout << *rb;
39 }
Enter a string: automobile
elibomotua
556 Class string and String Stream Processing Solutions Chapter 19
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
19.26 Write a program that generates from the string "abcdefghijklmnopqrstuvwxyz{" the following:
a
bcb
cdedc
defgfed
efghihgfe
fghijkjihgf
ghijklmlkjihg
hijklmnonmlkjih
ijklmnopqponmlkji
jklmnopqrsrqponmlkj
klmnopqrstutsrqponmlk
lmnopqrstuvwvutsrqponml
mnopqrstuvwxyxwvutsrqponm
nopqrstuvwxyz{zyxwvutsrqpon
1// Exercise 19.26 Solution
2// Program prints a pyramid from a string.
3#include <iostream>
4
5using std::cout;
6using std::endl;
7using std::cin;
8using std::ios;
9
10 #include <string>
11 using std::string;
12
13 int main()
14 {
15 string alpha = "abcdefghijklmnopqrstuvwxyz{";
16 string::const_iterator x = alpha.begin(), x2;
17
18 for ( int p = 1; p <= 14; ++p ) {
19 int w, count = 0; // set to 0 each iteration
20
21 // output spaces
22 for ( int k = 13; k >= p; --k )
23 cout << ' ';
24
25 x2 = x; // set starting point
26
27 // output first half of characters
28 for ( int c = 1; c <= p; ++c ) {
29 cout << *x2;
30 x2++; // move forwards one letter
31 count++; // keep count of iterations
32 }
33
34 // output back half of characters
35 for ( w = 1, x2 -= 2; w < count; ++w ) {
36 cout << *x2;
37 --x2; // move backwards one letter
38 }
39
40 x++; // next letter
41 cout << '\n';
42 }
43
44 return 0;
Chapter 19 Class string and String Stream Processing Solutions 557
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
19.27 In Exercise 19.7 we asked you to write a simple encryption algorithm. Write a program that will attempt to decrypt a “rot13”
message using simple frequency substitution (assume you do not know the key). The most frequent letters in the encrypted phrase
should be substituted with the most commonly used English letters (a, e, i, o, u, s, t, r, etc.). Write the possibilities to a file. What
made the code breaking easy? How can the encryption mechanism be improved?
19.28 Write a version of the bubble sort routine that sorts strings. Use function swap in your solution.
45 }
a
bcb
cdedc
defgfed
efghihgfe
fghijkjihgf
ghijklmlkjihg
hijklmnonmlkjih
ijklmnopqponmlkji
jklmnopqrsrqponmlkj
klmnopqrstutsrqponmlk
lmnopqrstuvwvutsrqponml
mnopqrstuvwxyxwvutsrqponm
nopqrstuvwxyz{zyxwvutsrqpon
1// Exercise 19.28 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <string>
10 using std::string;
11
12 void output( const string const *, const int );
13 void bubbleSort( string [], const int );
14
15 int main()
16 {
17 string animals[] = { "Macaw", "Lion", "Tiger",
18 "Bear", "Toucan", "Zebra",
19 "Puma", "Cat", "Yak", "Boar",
20 "Fox", "Ferret", "Crocodile",
21 "Alligator", "Elk", "Ox",
22 "Horse", "Eagle", "Hawk" };
23
24 cout << "before:";
25 output( animals, 19 );
26
27 bubbleSort( animals, 19 );
28
29 cout << "\nafter:";
30 output( animals, 19 );
31
32 return 0;
33 }
558 Class string and String Stream Processing Solutions Chapter 19
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
34
35 void output( const string * const ani, const int length )
36 {
37 for ( int j = 0; j < length; ++j )
38 cout << ( j % 10 ? ' ': '\n' ) << ani[ j ];
39
40 cout << endl;
41 }
42
43 void bubbleSort( string mals[], const int length )
44 {
45 for ( int pass = 1; pass < length; ++pass )
46 for ( int comp = 0; comp < length - pass; ++comp )
47 if ( mals[ comp ] > mals[ comp + 1 ] )
48 mals[ comp ].swap( mals[ comp + 1 ] );
49 }
before:
Macaw Lion Tiger Bear Toucan Zebra Puma Cat Yak Boar
Fox Ferret Crocodile Alligator Elk Ox Horse Eagle Hawk
after:
Alligator Bear Boar Cat Crocodile Eagle Elk Ferret Fox Hawk
Horse Lion Macaw Ox Puma Tiger Toucan Yak Zebra
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
20
Standard Template Library
(STL)
Solutions
Solutions
20.14 Write a function template palindrome that takes as a parameter a const vector and returns true or false depend-
ing upon whether the vector does or does not read the same forwards as backwards (e.g., a vector containing 1, 2, 3, 2, 1 is a
palindrome and a vector containing 1, 2, 3, 4 is not).
1// Exercise 20.14 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::ios;
7
8#include <vector>
9
10 template < class X >
11 bool palindrome( const std::vector< X > &vec )
12 {
13 std::vector< X >::const_reverse_iterator r = vec.rbegin();
14 std::vector< X >::const_iterator i = vec.begin();
15
16 while ( r != vec.rend() && i != vec.end() ) {
17 if ( *r != *i )
18 return false;
19
20 ++r;
21 ++i;
22 }
23
24 return true;
25 }
26
27 template < class Y >
28 void printVector( const std::vector< Y > &vec )
29 {
30 std::vector< Y >::const_iterator i;
560 Standard Template Library (STL) Solutions Chapter 20
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
20.15 Modify the program of Fig. 20.29, the Sieve of Eratosthenes, so that if the number the user inputs into the program is not
prime, the program displays the prime factors of the number. Remember that a prime number’s factors are only 1 and the prime
number itself. Every number that is not prime has a unique prime factorization. For example, consider the number 54. The factors
of 54 are 2, 3, 3 and 3. When these values are multiplied together, the result is 54. For the number 54, the prime factors output should
be 2 and 3.
31
32 for ( i = vec.begin(); i != vec.end(); ++i )
33 cout << *i << ' ';
34 }
35
36 int main()
37 {
38 std::vector< int > iv;
39 std::vector< char > ic;
40 int x = 0;
41
42 for ( int i = 75; i >= 65; --i ) {
43 iv.push_back( i );
44 ic.push_back( static_cast< char > ( i + x ) );
45
46 if ( i <= 70 )
47 x += 2;
48 }
49
50 printVector( iv );
51 cout << ( palindrome( iv ) ? " is " : " is not " )
52 << "a palindrome\n";
53
54 printVector( ic );
55 cout << ( palindrome( ic ) ? " is " : " is not " )
56 << "a palindrome" << endl;
57
58 return 0;
59 }
75 74 73 72 71 70 69 68 67 66 65 is not a palindrome
K J I H G F G H I J K is a palindrome
1// Exercise 20.15 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setw;
12 using std::setprecision;
13 using std::setiosflags;
14
15 #include <bitset>
16
17 using std::bitset;
18
19 #include <cmath>
Chapter 20 Standard Template Library (STL) Solutions 561
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
20
21 int main()
22 {
23 const int size = 1024;
24 int i, value, counter;
25 bitset< size > sieve;
26
27 sieve.flip();
28
29 // perform Sieve of Eratosthenes
30 int finalBit = sqrt( sieve.size() ) + 1;
31
32 for ( i = 2; i < finalBit; ++i )
33 if ( sieve.test( i ) )
34 for ( int j = 2 * i; j < size; j += i )
35 sieve.reset( j );
36
37 cout << "The prime numbers in the range 2 to 1023 are:\n";
38
39 for ( i = 2, counter = 0; i < size; ++i )
40 if ( sieve.test( i ) ) {
41 cout << setw( 5 ) << i;
42
43 if ( ++counter % 12 == 0 )
44 cout << '\n';
45 }
46
47 cout << endl;
48
49 // get a value from the user to determine if it is prime
50 cout << "\nEnter a value from 1 to 1023 (-1 to end): ";
51 cin >> value;
52
53 while ( value != -1 ) {
54 if ( sieve[ value ] )
55 cout << value << " is a prime number\n";
56 else {
57 cout << value << " is not a prime number\n"
58 << "prime factor(s): ";
59
60 bool print = true;
61
62 for ( int f = 2; f < size; )
63 if ( sieve.test( f ) && value % f == 0 ) {
64 if ( print )
65 cout << f << ' '; // output factor
66
67 value /= f; // modify value
68
69 if ( value <= 1 ) // time to stop
70 break;
71
72 print = false;
73 }
74 else {
75 ++f; // move to next prime
76 print = true;
77 }
78
79 cout << '\n';
80 }
81
562 Standard Template Library (STL) Solutions Chapter 20
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
20.16 Modify Exercise 20.15 so that if the number the user inputs into the program is not prime, the program displays the prime
factors of the number and the number of times that prime factor appears in the unique prime factorization. For example, the output
for the number 54 should be The unique prime factorization of 54 is: 2 * 3 * 3 * 3
82 cout << "\nEnter a value from 2 to 1023 (-1 to end): ";
83 cin >> value;
84 }
85
86 return 0;
87 }
The prime numbers in the range 2 to 1023 are:
2 3 5 7 11 13 17 19 23 29 31 37
41 43 47 53 59 61 67 71 73 79 83 89
97 101 103 107 109 113 127 131 137 139 149 151
157 163 167 173 179 181 191 193 197 199 211 223
227 229 233 239 241 251 257 263 269 271 277 281
283 293 307 311 313 317 331 337 347 349 353 359
367 373 379 383 389 397 401 409 419 421 431 433
439 443 449 457 461 463 467 479 487 491 499 503
509 521 523 541 547 557 563 569 571 577 587 593
599 601 607 613 617 619 631 641 643 647 653 659
661 673 677 683 691 701 709 719 727 733 739 743
751 757 761 769 773 787 797 809 811 821 823 827
829 839 853 857 859 863 877 881 883 887 907 911
919 929 937 941 947 953 967 971 977 983 991 997
1009 1013 1019 1021
Enter a value from 1 to 1023 (-1 to end): 8
8 is not a prime number
prime factor(s): 2
Enter a value from 2 to 1023 (-1 to end): 444
444 is not a prime number
prime factor(s): 2 3 37
Enter a value from 2 to 1023 (-1 to end): -1
1// Exercise 20.16 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9#include <iomanip>
10
11 using std::setw;
12 using std::setprecision;
13 using std::setiosflags;
14
15 #include <bitset>
16
17 using std::bitset;
18
19 #include <cmath>
20
21
Chapter 20 Standard Template Library (STL) Solutions 563
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
22 int main()
23 {
24 const int size = 1024;
25 int i, value, counter;
26 bitset< size > sieve;
27
28 sieve.flip();
29
30 // perform Sieve of Eratosthenes
31 int finalBit = sqrt( sieve.size() ) + 1;
32
33 for ( i = 2; i < finalBit; ++i )
34 if ( sieve.test( i ) )
35 for ( int j = 2 * i; j < size; j += i )
36 sieve.reset( j );
37
38 cout << "The prime numbers in the range 2 to 1023 are:\n";
39
40 for ( i = 2, counter = 0; i < size; ++i )
41 if ( sieve.test( i ) ) {
42 cout << setw( 5 ) << i;
43
44 if ( ++counter % 12 == 0 )
45 cout << '\n';
46 }
47
48 cout << endl;
49
50 // get a value from the user to determine if it is prime
51 cout << "\nEnter a value from 1 to 1023 (-1 to end): ";
52 cin >> value;
53
54 while ( value != -1 ) {
55 if ( sieve[ value ] )
56 cout << value << " is a prime number\n";
57 else {
58 cout << value << " is not a prime number\n"
59 << "prime factor(s): ";
60
61 for ( int f = 2; f < size; )
62 if ( sieve.test( f ) && value % f == 0 ) {
63 cout << f << ' '; // output factor
64 value /= f; // modify value
65
66 if ( value <= 1 ) // time to stop
67 break;
68 }
69 else
70 ++f; // move to next prime
71
72 cout << '\n';
73 }
74
75 cout << "\nEnter a value from 2 to 1023 (-1 to end): ";
76 cin >> value;
77 }
78
79 return 0;
80 }
564 Standard Template Library (STL) Solutions Chapter 20
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
The prime numbers in the range 2 to 1023 are:
2 3 5 7 11 13 17 19 23 29 31 37
41 43 47 53 59 61 67 71 73 79 83 89
97 101 103 107 109 113 127 131 137 139 149 151
157 163 167 173 179 181 191 193 197 199 211 223
227 229 233 239 241 251 257 263 269 271 277 281
283 293 307 311 313 317 331 337 347 349 353 359
367 373 379 383 389 397 401 409 419 421 431 433
439 443 449 457 461 463 467 479 487 491 499 503
509 521 523 541 547 557 563 569 571 577 587 593
599 601 607 613 617 619 631 641 643 647 653 659
661 673 677 683 691 701 709 719 727 733 739 743
751 757 761 769 773 787 797 809 811 821 823 827
829 839 853 857 859 863 877 881 883 887 907 911
919 929 937 941 947 953 967 971 977 983 991 997
1009 1013 1019 1021
Enter a value from 1 to 1023 (-1 to end): 99
99 is not a prime number
prime factor(s): 3 3 11
Enter a value from 2 to 1023 (-1 to end): 888
888 is not a prime number
prime factor(s): 2 2 2 3 37
Enter a value from 2 to 1023 (-1 to end): -1
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
21
Standard C++ Language
Additions
Solutions
Solutions
21.3 Fill in the blanks for each of the following:
a) Operator is used to determine an object’s type at run-time.
ANS: typeid or dynamic_cast
b) Keyword specifies that a namespace or namespace member is being used.
ANS: using
c) Operator is the operator keyword for logical OR.
ANS: or
d) Storage specifier allows a member of a const object to be modified.
ANS: mutable
21.4 State which of the following are true and which are false. If a statement is false, explain why.
a) The validity of a static_cast operation is checked at compile-time.
ANS: True.
b) The validity of a dynamic_cast operation is checked at run-time.
ANS: True.
c) The name typeid is a keyword.
ANS: True.
d) Keyword explicit may be applied to constructors, member functions and data members.
ANS: False. Keyword explicit can only be used with constructors.
21.5 What does each expression evaluate to? (Note: Some expressions may generate errors; if so, say what the cause of the error
is.)
a) cout << false;
ANS: 0 is output.
b) cout << ( bool b = 8 );
ANS: Error. Most compilers will not allow a variable to be declared in this manner. If the compiler permits the expression,
1 is output.
c) cout << ( a = true ); // a is of type int
ANS: 1 is output.
d) cout << ( *ptr + true && p ); // *ptr is 10 and p is 8.88
ANS: 1 is output.
e) // *ptr is 0 and m is false
bool k = ( *ptr * 2 || ( true + 24 ) );
566 Standard C++ Language Additions Solutions Chapter 21
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
ANS: k is assigned 1.
f) bool s = true + false;
ANS: true is assigned to s.
g) cout << boolalpha << false << setw( 3 ) << true;
ANS: falsetrue is output.
21.6 Write a namespace Currency which defines constant members ONE, TWO, FIVE, TEN, TWENTY, FIFTY and HUN-
DRED. Write two short programs that use Currency. One program should make all constants available and the other program
should only make FIVE available.
1// Exercise 21.6 Part A Solution
2// Program makes namespace members accessible.
3#include <iostream>
4
5using std::cout;
6using std::endl;
7using std::cin;
8using std::ios;
9
10 namespace Currency {
11 enum Money { ONE = 1, TWO, FIVE = 5, TEN = 10,
12 TWENTY = 20, FIFTY = 50,
13 HUNDRED = 100 };
14 }
15
16 int main()
17 {
18 using namespace Currency;
19
20 cout << "TWO's value is: " << TWO
21 << "\nTEN's value is: " << TEN << endl;
22
23 return 0;
24 }
TWO's value is: 2
TEN's value is: 10
1// Exercise 21.6 Part B Solution
2// Program makes one namespace member accessible.
3#include <iostream>
4
5using std::cout;
6using std::endl;
7using std::cin;
8using std::ios;
9
10 namespace Currency {
11 enum Money { ONE = 1, TWO, FIVE = 5, TEN = 10,
12 TWENTY = 20, FIFTY = 50,
13 HUNDRED = 100 };
14 }
15
16 int main()
17 {
18 using Currency::FIVE;
19
20 cout << "FIVE's value is: " << FIVE << endl;
21
Chapter 21 Standard C++ Language Additions Solutions 567
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
21.7 Write a program that uses the reinterpret_cast operator to cast different pointer types to int. Do any conversions
result in syntax errors?
22 return 0;
23 }
FIVE's value is: 5
1// Exercise 21.7 Solution
2// Program exercises reinterpret cast
3#include <iostream>
4
5using std::cout;
6using std::endl;
7using std::cin;
8using std::ios;
9
10 #include <string>
11 using std::string;
12
13 int main()
14 {
15 // declare variables
16 int x;
17 double d;
18 float f;
19 long l;
20 short s;
21 string z;
22 char c;
23
24 // declare and initialize pointers
25 int *xPtr = &x;
26 double *dPtr = &d;
27 float *fPtr = &f;
28 long *lPtr = &l;
29 short *sPtr = &s;
30 string *zPtr = &z;
31 char *cPtr = &c;
32 void *vPtr = &z;
33
34 // test reinterpret_cast
35 cout << "reinterpret_cast< int > ( xPtr ) = "
36 << reinterpret_cast< int > ( xPtr )
37 << "\nreinterpret_cast< int > ( dPtr ) = "
38 << reinterpret_cast< int > ( dPtr )
39 << "\nreinterpret_cast< int > ( fPtr ) = "
40 << reinterpret_cast< int > ( fPtr ) ;
41
42 cout << "\nreinterpret_cast< int > ( lPtr ) = "
43 << reinterpret_cast< int > ( lPtr )
44 << "\nreinterpret_cast< int > ( sPtr ) = "
45 << reinterpret_cast< int > ( sPtr )
46 << "\nreinterpret_cast< int > ( zPtr ) = "
47 << reinterpret_cast< int > ( zPtr )
48 << "\nreinterpret_cast< int > ( cPtr ) = "
49 << reinterpret_cast< int > ( cPtr )
50 << "\nreinterpret_cast< int > ( vPtr ) = "
51 << reinterpret_cast< int > ( vPtr ) << endl;
568 Standard C++ Language Additions Solutions Chapter 21
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
21.8 Write a program that uses the static_cast operator to cast some fundamental data types to int. Does the compiler
allow the casts to int?
52
53 return 0;
54 }
reinterpret_cast< int > ( xPtr ) = 1245040
reinterpret_cast< int > ( dPtr ) = 1245032
reinterpret_cast< int > ( fPtr ) = 1245024
reinterpret_cast< int > ( lPtr ) = 1245020
reinterpret_cast< int > ( sPtr ) = 1245016
reinterpret_cast< int > ( zPtr ) = 1245000
reinterpret_cast< int > ( cPtr ) = 1244996
reinterpret_cast< int > ( vPtr ) = 1245000
1// Exercise 21.8 Solution
2// Program exercises static casting.
3#include <iostream>
4
5using std::cout;
6using std::endl;
7using std::cin;
8using std::ios;
9
10 int main()
11 {
12 // declare variables
13 int x = 8;
14 double d = 22.22;
15 float f = 33.33f; // floating point representation
16 long l = 888888;
17 short s = 32000;
18 unsigned u = 65000;
19 char c = 'U'; // ascii of 85
20 long double ld = 999999999.00;
21 unsigned char uc = 250;
22 unsigned long ul = 777777;
23 unsigned short us = 55555;
24
25 // test static_cast
26 cout << "static_cast< int > ( x ) = "
27 << static_cast< int > ( x )
28 << "\nstatic_cast< int > ( d ) = "
29 << static_cast< int > ( d )
30 << "\nstatic_cast< int > ( f ) = "
31 << static_cast< int > ( f );
32
33 cout << "\nstatic_cast< int > ( l ) = "
34 << static_cast< int > ( l )
35 << "\nstatic_cast< int > ( s ) = "
36 << static_cast< int > ( s )
37 << "\nstatic_cast< int > ( u ) = "
38 << static_cast< int > ( u );
39
40 cout << "\nstatic_cast< int > ( c ) = "
41 << static_cast< int > ( c )
42 << "\nstatic_cast< int > ( ld ) = "
43 << static_cast< int > ( ld )
Chapter 21 Standard C++ Language Additions Solutions 569
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
21.9 Write a program that demonstrates upcasting from a derived class to a base class. Use the static_cast operator to per-
form the upcast.
44 << "\nstatic_cast< int > ( uc ) = "
45 << static_cast< int > ( uc );
46
47 cout << "\nstatic_cast< int > ( ul ) = "
48 << static_cast< int > ( ul )
49 << "\nstatic_cast< int > ( us ) = "
50 << static_cast< int > ( us ) << endl;
51
52 return 0;
53 }
static_cast< int > ( x ) = 8
static_cast< int > ( d ) = 22
static_cast< int > ( f ) = 33
static_cast< int > ( l ) = 888888
static_cast< int > ( s ) = 32000
static_cast< int > ( u ) = 65000
static_cast< int > ( c ) = 85
static_cast< int > ( ld ) = 999999999
static_cast< int > ( uc ) = 250
static_cast< int > ( ul ) = 777777
static_cast< int > ( us ) = 55555
1// Exercise 21.9 Solution
2// Program upcasts with static_cast.
3#include <iostream>
4
5using std::cout;
6using std::endl;
7using std::cin;
8using std::ios;
9
10 class Base {
11 public:
12 void print() const { cout << "BASE"; }
13 };
14
15 class Derived : public Base {
16 public:
17 void print() const { cout << "DERIVED"; }
18 };
19
20 int main()
21 {
22 Base *bPtr; // base class pointer
23 Derived d, *dPtr;
24
25 dPtr = &d; // point to d
26
27 // upcast from Derived * to Base *
28 bPtr = static_cast< Base * > ( dPtr );
29 bPtr -> print(); // invoke function print
30
31 cout << endl;
32
33 return 0;
570 Standard C++ Language Additions Solutions Chapter 21
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
21.10 Write a program that creates an explicit constructor that takes two arguments. Does the compiler permit this? Remove
explicit and attempt an implicit conversion. Does the compiler permit this?
21.11 What is the benefit of an explicit constructor?
ANS: An explicit constructor prevents arguments from being implicitly converted.
21.12 Write a program that creates a class containing two constructors. One constructor should take a single int argument. The
second constructor should take one char * argument. Write a driver program that constructs several different objects, each object
having a different type passed into the constructor. Do not use explicit. What happens? Now use explicit only for the con-
structor that takes one int. What happens?
21.13 Given the following namespaces, answer whether or not each statement is true or false. Explain any false answers.
a) Variable y is accessible within namespace ABC.
ANS: True.
b) Object s is accessible within namespace Temp.
ANS: True.
c) Constant POLAND is not accessible within namespace Temp.
ANS: False.
d) Constant GERMANY is accessible within namespace ABC.
ANS: False.
e) Function function is accessible to namespace Temp.
ANS: False.
f) Namespace ABC is accessible to Misc.
ANS: False.
g) Object car is accessible to Misc.
ANS: True.
21.14 Compare and contrast mutable and const_cast. Give at least one example of when one might be preferred over the
other. Note: This exercise does not require any code to be written.
ANS: Operator const_cast is used to cast away const or volatile qualifications. Users of a class usually will not
be aware of const_cast operations, because this implementation is typically hidden. Storage class specifier mutable
allows a variable to be modified even if the object is const. Users of the class are not likely to be aware of a mutable
member. Members that are mutable usually correspond to some "secret" implementation. mutable members are always
modifiable, whereas const_cast operations are confined to the line where the cast is performed.
34 }
BASE
1#include <string>
2namespace Misc {
3 using namespace std;
4 enum Countries { POLAND, SWITZERLAND, GERMANY,
5 AUSTRIA, CZECH_REPUBLIC };
6 int kilometers;
7 string s;
8
9 namespace Temp {
10 short y = 77;
11 Car car; // assume definition exists
12 }
13 }
14
15 namespace ABC {
16 using namespace Misc::Temp;
17 void *function( void *, int );
18 }
Chapter 21 Standard C++ Language Additions Solutions 571
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
21.15 Write a program that uses const_cast to modify a const variable. (Hint: Use a pointer in your solution to point to the
const identifier.)
21.16 What problem does virtual base classes solve?
ANS: virtual base classes solve the problem of "diamond inheritance" where a derived class recieves duplicate subob-
jects from its base classes. With virtual base classes, only one copy of the subobject is inherited into the derived class
(at the bottom of the diamond).
21.17 Write a program that uses virtual base classes. The class at the top of the hierarchy should provide a constructor that
takes at least one argument (i.e., do not provide a default constructor). What challenges does this present for the inheritance hierar-
chy?
1// Exercise 21.15 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9int main()
10 {
11 const char c = 'A';
12 const char *ptr = &c;
13
14 cout << "c is " << *ptr;
15
16 *const_cast< char * > ( ptr ) = 'Z';
17
18 cout << "\nc is " << *ptr << endl;
19
20 return 0;
21 }
c is A
c is Z
1// Exercise 21.17 Solution
2#include <iostream>
3
4using std::cout;
5using std::endl;
6using std::cin;
7using std::ios;
8
9class Base {
10 public:
11 Base( int n ) { num = n; }
12 void print() const { cout << num; }
13 private:
14 int num;
15 };
16
17 class D1 : virtual public Base {
18 public:
19 D1(): Base( 3 ) {}
20 };
21
572 Standard C++ Language Additions Solutions Chapter 21
©2000. Deitel & Associates, Inc. and Prentice Hall. All Rights Reserved.
21.18 Find the error(s) in each of the following. When possible, explain how to correct each error.
a) namespace Name {
int x, y;
mutable int z;
};
ANS: A mutable member can only belong to a class.
b) int integer = const_cast< int >( double );
ANS: Operator const_cast cannot be used to convert a float to an int. Either static_cast or
reinterpret_cast should be used. Note: The keyword double in parentheses should be a floating-point value.
c) namespace PCM( 111, "hello" ); // construct namespace
ANS: A namespace cannot be constructed, because it only defines a scope.
d) explicit int x = 99;
ANS: Keyword explicit can only be applied to a constructor definition.
22 class D2 : virtual public Base {
23 public:
24 D2(): Base( 5 ) {}
25 };
26
27 class Multi : public D1, D2 {
28 public:
29 Multi( int a ): Base( a ) {}
30 };
31
32 int main()
33 {
34 Multi m( 9 );
35
36 m.print();
37
38 cout << endl;
39
40 return 0;
41 }
9
©2000. Deitel & Associates, Inc. & Prentice Hall. All Rights Reserved.
Appendix
C++ Multimedia Cyber Classroom:
Solutions Provided on CD
This appendix contains the complete list of solutions provided on the C++ Multimedia Cyber Classroom CD-
ROM. This will help instructors avoid the exercises for which students have solutions if they purchase the Cyber
Classroom product. Note that key exercises like the Simpletron Simulator (Chapter 5) and the compiler (Chapter
15) are not provided on the CD.
Chapter 1: 1.11, 1.13, 1.16, 1.19, 1.21, 1.24, 1.25, 1.30, 1.31, 1.34, 1.37
Chapter 2: 2.14, 2.16, 2.18, 2.20, 2.24, 2.26, 2.29, 2.31, 2.33, 2.37a/b, 2.40, 2.43, 2.45, 2.48, 2.49, 2.54,
2.58, 2.60, 2.63
Chapter 3: 3.12, 3.13, 3.16, 3.18, 3.20, 3.22, 3.27, 3.29, 3.33, 3.35, 3.38, 3.40, 3.44, 3.48, 3.53, 3.56, 3.58
Chapter 4: 4.10, 4.12, 4.15, 4.20, 4.23, 4.29, 4.30, 4.33, 4.36, 4.38
Chapter 5: 5.9, 5.12, 5.22, 5.25, 5.26, 5.27, 5.30, 5.31, 5.33, 5.37, 5.42a/b/c, 5.46
Chapter 6: 6.5, 6.7, 6.8, 6.12, 6.16
Chapter 7: 7.7, 7.8
Chapter 8: 8.12, 8.15, 8.19
Chapter 9: 9.10, 9.12
Chapter 10: 10.6, 10.7, 10.14
Chapter 11: 11.7, 11.9, 11.10, 11.12, 11.15, 11.18
Chapter 12: 12.3, 12.7, 12.9, 12.14, 12.15, 12.19, 12.23
Chapter 13: 13.21, 13.27, 13.29, 13.31, 13.34, 13.42, 13.43
Chapter 14: 14.7, 14.12, 14.14
Chapter 15: 15.6, 15.8, 15.10, 15.11, 15.17, 15.20, 15.24
Chapter 16: 16.9, 16.12, 16.21, 16.22, 16.26, 16.30
Chapter 17: 17.4, 17.6, 17.8 ,17.10
Chapter 18: 18.3, 18.8, 18.10
Chapter 19: 19.4, 19.5, 19.8, 19.11, 19.12, 19.21, 19.23
Chapter 20: 20.15
Chapter 21: 21.3, 21.4, 21.7, 21.8, 21.13, 21.15

Navigation menu