Vous êtes sur la page 1sur 103

Chapter 7

ARRAYS

1. Solutions to and Remarks on Selected Programming Problems

Regarding the solutions presented here.: C++ leaves many options on how to do a problem,
and any book will necessarily choose a subset to present. It is necessary to read the text, as
that is what the student has to work with. I am striving to produce a complementary
document to the text, a document for the instructor. Most of the time, will use the
initialization list style for constructors. If you present the code using the initializer list,
you should also assign Appendix 7 on constructor initialization.

1. Rainfall

Here, I have done the interactive version only. The solution is broken into two files. The
source for each is listed, along with test data, command generating the output and the
output.

I have done the solution using structs here. The enhancement of adding the choice of
graphical output is provided. I have done only the interactive version here. The variation
using file i/o is left to the reader. Notes will be supplied for doing this without the struct.

//File Ch10Prg1.cpp

//Author indicates that this may be done without structs or


//classes. This is a solution using structs.

//Program is to
//1)read in long term month by month average rain fall
// averages
//2)read in the previous year's month by month actual rain
// fall.

1
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

//Output:
//'nicely' formatted table showing rainfall for each of the
// previous
//12 months as well as how much above or below the monthly
// average the rainfall is for each month. The output
// should correctly label months.
//
//Month name handling: code months as integers and do a
//conversion at output. Any input scheme acceptable as long
//as the user interface is relatively easy to use.

//Remarks: If the current month is April, we don't have


//April's rainfall figure yet, so we go back to April of the
//previous year, to March of this year.

//Enhanced version:
//Add capability to print two bar graphs for each month,
//showing the average rainfall and the actual rainfall for
//each of the previous 12 months. Ask the user's preference:
//a table or a graph, and display the format requested.
//
//Provide a loop to repeat the process at the user's request.

//Command line compile, where g++ is replaced by BCC32


//or CL –GX or CC depending on which compiler you use.
//g++ Ch10Prg1.cpp Ch10Prg1.bargraph.cpp

#include <iostream>
#include <cstring>
#include <cstdlib>

struct monthly_rain

2
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

{
int month;
double rain_fall;
double avg_rain_fall;
};

//declaration of function from file Ch10Prg1.bargraph.cpp


void output_bargraph( monthly_rain rainfall[],
int current_month );
//output: scale and bargraph of month by month average and
//actual rainfall.

void input( monthly_rain rainfall[], int& year );


//precondition:
//routine called correctly, with variable arguments
//postcondition:
//User is asked for current month, then is asked for
//the average and actual rainfall for each of the
//preceding 12 months.

void output_table( monthly_rain rainfall[], int& year );


//Precondition:
//input is array of size 12 of monthly_rain structs.
//Postcondition: output to screen is formatted table showing
//rainfall for each of the previous 12 months as well as how
//much above or below the monthly average the rainfall
//for each month. The output should correctly label months.

int main()
{
using namespace std;
int current_month;

3
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

monthly_rain rainfall[12];
char ans;
char tg;
do
{
input( rainfall, current_month);
cout << "Please choose between g)raphical and t)abular "
<< "output" << endl;
cin >> tg; //tg means table/graphics choice :)

if ( 't' == tg || 'T' == tg )
{
cout << "You chose the tabular output." << endl;
output_table( rainfall, current_month );
}
else if ( 'g' == tg || 'G' == tg )
{
cout << "You chose the graphical output" << endl;
output_bargraph( rainfall, current_month);
}
else
{
cout << "You typed neither of the choices. "
<< "Defaulting to graphical output." << endl;
output_bargraph( rainfall, current_month );
}
cout << "Y/y continues, any thing else quits";
cin >> ans;
}while( 'y' == ans || 'Y' == ans );
return 0;
}

4
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

void full_month_name(int);

void input( monthly_rain rainfall[], int& current_month)


{
using namespace std;
int i;
cout << "\nMonthly rainfall input routine."
<< endl << endl
<< "Please enter the average rainfall for each month "
<< endl;

cout << " Average rainfall: " << endl;


for ( i = 0; i < 12; i++)
{
cout << "For month ";
full_month_name(i);
cout << ' ';
cin >> rainfall[i].avg_rain_fall;
cout << " \t Avg Rainfall: "
<< rainfall[i].avg_rain_fall;
rainfall[i].month = i;
cout << endl;
}

cout << endl << "The actual rainfall: " << endl;
cout << "What is the current month? Please give the "
<< "number of the month (Jan = 0, etc." << endl;

cin >> current_month;


cout << " The current month is: " ;
full_month_name(current_month);
cout << endl;

5
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

cout << "Please enter the actual rainfall for "


<< "each month, as prompted, First for the\n"
<< "months in the previous year: "
<< endl;

for ( i = current_month; i < 12; i++)


{
cout << "For month ";
full_month_name(i);
cout << " ";
cin >> rainfall[i].rain_fall;
cout << "\tRainfall: " << rainfall[i].rain_fall;
cout << endl;
}
cout << "Now for the months in this year: " << endl;
for ( i = 0; i < current_month; i++)
{
cout << "For month ";
full_month_name(i);
cout << ' ';
cin >> rainfall[i].rain_fall;
cout << "\tRainfall: " << rainfall[i].rain_fall;
cout << endl;
}

} //end of input routine

//helping routines for output_table, defined at the end of


//this file.
void month_name( int month );
void full_month_name( int month);

6
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

void output_table(monthly_rain rainfall[],


int& current_month)
{
using namespace std;
int i;
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(1);
//heading: Monthly Rainfall
// For the 12 Months Preceding .....
// Actual, Average, and Difference (= Actual - Average)

cout << "\t\t\t\t Monthly Rainfall " << endl;


cout << "\t\t\tFor the 12 Months Preceding ";
full_month_name( current_month );
cout << endl;
cout << "\t\tActual, Average, and Difference "
<< " (= Actual - Average)" << endl;

cout << "\t-----+-----+-----+-----+-----+-----+-----"


<< "+-----+-----+-----+-----+----" << endl << "\t ";

for ( i = 0; i < 11; i++ )


{
month_name(rainfall[i].month);
cout << " | ";
}
month_name( rainfall[i].month );
cout << endl
<< "\t-----+-----+-----+-----+-----+-----+-----+"
<< "-----+-----+-----+-----+----"<< endl;

7
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

cout << "average\t";


for ( i = 0; i < 11; i++ )
{
cout.width(4);
cout << rainfall[i].rain_fall << " |";
}
cout.width(4);
cout << rainfall[i].rain_fall << endl;
cout << "actual\t";
for ( i = 0; i < 11; i++ )
{
cout.width(4);
cout << rainfall[i].avg_rain_fall << " |";
}
cout.width(4);
cout << rainfall[i].avg_rain_fall << endl;

cout << "diffs\t";


for ( i = 0; i < 11; i++ )
{
cout.width(4);
cout << rainfall[i].rain_fall - rainfall[i].avg_rain_fall
<< " |";
}
cout.width(4);
cout << rainfall[i].rain_fall - rainfall[i].avg_rain_fall
<< endl;

cout << "P)rev yr";


for ( i = 0; i < current_month; i++)
cout << " |";

8
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

for ( i = current_month; i < 11; i++)


cout << " P |" ;
cout << " P" << endl << endl;
}

void month_name( int month )


{
switch (month)
{
case 0: cout << "Jan";
break;
case 1: cout << "Feb";
break;
case 2: cout << "Mar";
break;
case 3: cout << "Apr";
break;
case 4: cout << "May";
break;
case 5: cout << "Jun";
break;
case 6: cout << "Jul";
break;
case 7: cout << "Aug";
break;
case 8: cout << "Sep";
break;
case 9: cout << "Oct";
break;
case 10: cout << "Nov";
break;
case 11: cout << "Dec";

9
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

break;
default: cout << "NO SUCH MONTH " << month << endl;
exit(1);
}
}

void full_month_name( int month )


{
switch (month)
{
case 0: cout << "January "; //strings padded to 9 spaces
break; //for output formatting
case 1: cout << "February";
break;
case 2: cout << "March " ;
break;
case 3: cout << "April ";
break;
case 4: cout << "May ";
break;
case 5: cout << "June ";
break;
case 6: cout << "July ";
break;
case 7: cout << "August ";
break;
case 8: cout << "September";
break;
case 9: cout << "October ";
break;
case 10: cout << "November";
break;

10
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

case 11: cout << "December";


break;
default: cout << "NO SUCH MONTH " << month << endl;
exit(1);
}
}

//file: Ch10Prg1.bargraph.cpp
//
//to print two bargraphs for each month, showing average and
//actual rainfall each month.

#include <iostream>

struct monthly_rain
{
int month;
double rain_fall;
double avg_rain_fall;
};

void full_month_name( int );


void month_name( int );

//outputs x asterisks, no <cr>


void bargraph( double x )
{
using namespace std;
cout << " ";
for (int i = 0; i < x*10; i++)
cout << '*';

11
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

//output scale followed by <cr>


//
void output_scale()
{
using namespace std;
cout << "\nRainfall ";
for ( int i = 0; i < 14; i++)
{
double j = i/2.0;
cout.setf(ios::showpoint);
cout.setf(ios::fixed);
cout.precision(1);
cout << j << " ";
}
cout << endl << "\t ";
for (i = 0; i < 14; i++)
cout << "|****";
cout << endl;
}

void output_bargraph( monthly_rain rainfall[],


int current_month )
{
using namespace std;
output_scale();
for ( int i = 0; i < 12; i++ )
{
full_month_name( i );
if ( i >= current_month )
cout << "(Previous year)";

12
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

cout << "\naverage\t ";


bargraph( rainfall[i].avg_rain_fall );
cout << "\nactual\t ";
bargraph( rainfall[i].rain_fall );
cout << endl;

if ( 5 == i )
{
output_scale();
}
}
output_scale();
}

The rainfall averages in the data come from The World Almanac and Book of Facts 1993,
published by the World Almanac. (C) Phaos Books,1992. The rainfall numbers presented
here are made-up.

This is the 'data file' used to test this program:

$cat data
3.7 3.6 5.1 3.8 4.2 4.2 4.4 4.8 4.0 3.3 3.3 3.5
4
4.3 3.2 5.5 5.1 4.0 2.2 2.0 1.1 4.1 3.3 3.9 3.7
t
y
3.7 3.6 5.1 3.8 4.2 4.2 4.4 4.8 4.0 3.3 3.3 3.5
4
4.3 3.2 5.5 5.1 4.0 2.2 2.0 1.1 4.1 3.3 3.9 3.7
g
y
3.7 3.6 5.1 3.8 4.2 4.2 4.4 4.8 4.0 3.3 3.3 3.5
4
4.3 3.2 5.5 5.1 4.0 2.2 2.0 1.1 4.1 3.3 3.9 3.7

13
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

h
n

The command used to run the program and the output is:
17:19:43:~/AW$ a.out < data > ch7prb2.out

There follows edited output obtained from this run. I have 'redacted' the input and the
output where either is identical for all three runs and after it has been seen.

$cat ch7prb2.out
Monthly rainfall input routine.

Please enter the average rainfall for each month


Average rainfall:
For month January Avg Rainfall: 3.7
For month February Avg Rainfall: 3.6
For month March Avg Rainfall: 5.1
For month April Avg Rainfall: 3.8
For month May Avg Rainfall: 4.2
For month June Avg Rainfall: 4.2
For month July Avg Rainfall: 4.4
For month August Avg Rainfall: 4.8
For month September Avg Rainfall: 4
For month October Avg Rainfall: 3.3
For month November Avg Rainfall: 3.3
For month December Avg Rainfall: 3.5

The actual rainfall:


What is the current month? Please give the number of the month (Jan = 0,
etc.
The current month is: May
Please enter the actual rainfall for each month, as prompted, First for
the
months in the previous year:
For month May Rainfall: 4.3
For month June Rainfall: 3.2
For month July Rainfall: 5.5

14
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

For month August Rainfall: 5.1


For month September Rainfall: 4
For month October Rainfall: 2.2
For month November Rainfall: 2
For month December Rainfall: 1.1
Now for the months in this year:
For month January Rainfall: 4.1
For month February Rainfall: 3.3
For month March Rainfall: 3.9
For month April Rainfall: 3.7
Please choose between g)raphical and t)abular output
You chose the tabular output.
Monthly Rainfall
For the 12 Months Preceding May
Actual, Average, and Difference (= Actual - Average)
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----
Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+----
average 4.1 | 3.3 | 3.9 | 3.7 | 4.3 | 3.2 | 5.5 | 5.1 | 4.0 | 2.2 | 2.0 | 1.1
actual 3.7 | 3.6 | 5.1 | 3.8 | 4.2 | 4.2 | 4.4 | 4.8 | 4.0 | 3.3 | 3.3 | 3.5
diffs 0.4 |-0.3 |-1.2 |-0.1 | 0.1 |-1.0 | 1.1 | 0.3 | 0.0 |-1.1 |-1.3 |-2.4
P)rev yr | | | | P | P | P | P | P | P | P | P

Y/y continues, any thing else quits


Monthly rainfall input routine.

Please enter the average rainfall for each month


Average rainfall:
For month January Avg Rainfall: 3.7
. . . .
For month December Avg Rainfall: 3.5

The actual rainfall:


What is the current month? Please give the number of the month (Jan = 0, etc.
The current month is: May
Please enter the actual rainfall for each month, as prompted, First for the
months in the previous year:
For month May Rainfall: 4.3

15
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

. . . .
For month December Rainfall: 1.1
Now for the months in this year:
For month January Rainfall: 4.1
. . . .
For month April Rainfall: 3.7
Please choose between g)raphical and t)abular output
You chose the graphical output

Rainfall 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5
|****|****|****|****|****|****|****|****|****|****|****|****|****|****
January
average **************************************
actual *****************************************
February
average *************************************
actual *********************************
March
average ***************************************************
actual ***************************************
April
average **************************************
actual **************************************
May (Previous year)
average *******************************************
actual *******************************************
June (Previous year)
average *******************************************
actual *********************************

Rainfall 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5
|****|****|****|****|****|****|****|****|****|****|****|****|****|****
July (Previous year)
average *********************************************
actual *******************************************************
August (Previous year)
average ************************************************
actual ***************************************************

16
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

September(Previous year)
average ****************************************
actual ****************************************
October (Previous year)
average *********************************
actual ***********************
November(Previous year)
average *********************************
actual ********************
December(Previous year)
average ***********************************
actual ************

Rainfall 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5
|****|****|****|****|****|****|****|****|****|****|****|****|****|****
Y/y continues, any thing else quits
Monthly rainfall input routine.

Please enter the average rainfall for each month


Average rainfall:
For month January Avg Rainfall: 3.7

. . . .

For month December Avg Rainfall: 3.5

The actual rainfall:


What is the current month? Please give the number of the month (Jan = 0, etc.
The current month is: May
Please enter the actual rainfall for each month, as prompted, First for the
months in the previous year:
For month May Rainfall: 4.3

. . . .

For month December Rainfall: 1.1


Now for the months in this year:
For month January Rainfall: 4.1

17
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

. . . .
For month April Rainfall: 3.7
Please choose between g)raphical and t)abular output
You typed neither of the choices. Defaulting to graphical output.

Rainfall 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5
|****|****|****|****|****|****|****|****|****|****|****|****|****|****
January
average **************************************
actual *****************************************

. . . .

April
average **************************************
actual **************************************
May (Previous year)
average *******************************************
actual *******************************************

. . . .

December(Previous year)
average ***********************************
actual ************

Rainfall 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5
|****|****|****|****|****|****|****|****|****|****|****|****|****|****
Y/y continues, any thing else quits

Notes On transforming this into a structure free program.

Much of the program with structs will be identical to the version without. This makes
transforming one into the other easy. This is particularly true when we are moving from
using structs to not using structs.

18
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

First, declare local variables in main:

int month;
double rain_fall[12];
double avg_rain_fall[12];

Pass these to each function called from main, and modify each function to access these
rather than the structure, for example, the input routine would have declaration:

void input ( double rain_fall[], double avg_rain_fall[],


int current_month );

and the two output routines would have the same sort of declaration:

void output_bargraph ( double rain_fall[],


double avg_rain_fall[],
int current_month );
void output_table ( double rain_fall[],
double avg_rain_fall[],
int current_month );

The changes necessary internal to the routines is illustrated here. We replace this following
loop from the input routine,

for ( i = current_month; i < 12; i++)


{
cout << "For month ";
full_month_name(i);
cout << " ";
cin >> rainfall[i].rain_fall;
cout << "\tRainfall: " << rainfall[i].rain_fall;
cout << endl;
}

with this:

19
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

for ( i = current_month; i < 12; i++)


{
cout << "For month ";
full_month_name(i);
cout << " ";
cin >> rain_fall[i];
cout << "\tRainfall: " << rain_fall[i];
cout << endl;
}

These changes will produce the required struct free solution.

2. Hexadecimal Addition
Problem statement and my commentary are in comments in the following source.

// Chapter 7 Savitch Programming and Problem Solving with C++ 5th ed


// File: Ch7.2.cpp

// This program is to accept two hexadecimal numbers, to be stored as


// arrays of up to 10 characters. The program should add these numbers.
//
// If the sum can be contained in 10 digits, output the sum
// otherwise output an indication of overflow error.
//
// Provide a loop to repeat the action until user wants to end program.
//
// Note on overflow detection. Overflow occurs when the carry bits into
// and out of the highest digit are both set. This condition is is
// equivalent to the text's "when the result will not fit in 10
hexadecimal
// digits", and is easy to test.
//
// My solution requires that the Hex digits A-F be entered upper case.
// A nice enhancement would be to allow either case.
//
// Finally, debugging this was a bear. I have left a some of my test
// code (but by no means all) for (what I hope will be) the student's
// edification.
//
// Be certain that the student tests the program with single digit, two
// digit and with all numbers of data all the way to 10 hex digits, in
all
// combinations in each of the two input positions, and test with short
// data before and after many digit data and conversely.
//

20
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

#include <iostream>

void input(char num[])


{
using std::cout;
using std::cin;
using std::endl;

cout << "Enter a hexadecimal number of 10 or fewer hex digits\n"


<< "Hex digits are 0-9A-F Code requires uppercase A through F\n"
<< "Press lower case q to stop entry of the hex digits\n";

int i = 0;
char c = '0';
while(c != 'q')
{
cin >> c;
num[i] = c;
i++;
}
num[--i] = '0';

// cout << " i " << i << endl;

// cout << "num[" << i << "] is " << num[i] << endl << endl;
// i is the of the last number entered
// reverse segment [0, i), that is 0<= k < i
// to put the least significant digit in the
// index 0 position.

char tmp;
for(int k = 0; k < i/2; k++)
{
tmp = num[k];
num[k] = num[i-1-k ];
num[i-1-k]=tmp;
}
}

// internal to the program, hex numbers are stored


// with least significant digit first we output
// most significant to least significant
void output(char num[])
{
using std::cout;

for(int i = 9; i >=0; i--)


cout << num[i];
}

21
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

void hexSum(char num1[], char num2[], char sum[])


{
using std::cout;
using std::endl;

int x, y, s, carry = 0, nextCarry = 0;

for(int i = 0; i < 10; i++)


{
if('0' <= num1[i] && num1[i] < '0' + 10)
{
// cout << "decimal digit" << endl;
x = num1[i] - '0';
}
else
{
// cout<< "hex digit\n";
x = num1[i] - 'A' + 10;
// cout << "value of num1[" << i << "] is " << x << endl;
}

if('0' <=num2[i] && num2[i] < '0'+ 10)


{
// cout << "num2 is digit 0-9" << endl;
y = num2[i] - '0';
// cout << "value of num2[" << i << "] is " << x << endl;
}
else
{
// cout<< "hex digit" << nuum2[i] << endl;
y = num2[i] - 'A' + 10;
// cout << "value of num2[" << i << "] is " << x << endl;

carry = nextCarry;
s = (x + y + carry)%16; // digit value
// cout << "s " << s << endl;

nextCarry = (x + y + carry)/16; // nextCarry is carry for next digit

// cout << "carry " << carry << endl;


//convert back to hex.
if(0 <= s && s < 10)
{
sum[i] = char('0' + s);
}
else if(10 <= s && s < 16)
sum[i] = char('A' + s - 10);
else
{
cout <<"bad values " ;
}

22
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

// cout << sum[i] << endl;


}
// cout << endl;
if(1 == carry && 1 == nextCarry)
cout << "\n\n*********Overflow Error ***********\n\n";
}

int main()
{
using std::cout;
using std::cin;
using std::endl;

char ans = 'y';


while (ans == 'y')
{
// put definitions and initialization here so each time through
// variables get initialized.
char num1[10] = {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0'};
char num2[10] = {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0'};
char sum[10] = {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0'};
char temp[10] = {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0'};

input(num1);
cout << endl;
output(num1);
cout << endl;
input(num2);
cout << endl;
output(num2);
cout << endl << endl;

hexSum(num1, num2, sum);

cout << " "; // for alignment


output(num1);
cout << " \n";
cout << "+";
output(num2);
cout << "\n------------\n "; // space at end for alignment
output(sum);

cout << endl;


cout << "y continues\n\n";
cin >> ans;
}

return 0;
}

/*

23
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

Typical run using the data in data7.2.txt:

FEDCBA9876q
123456789Aq
y
CEDCBA9876q
123456789Aq
y
DEDCBA9876q
123456789Aq
n

The first line here is the command line to execute this


program with the data specified.

ch7.2.exe < data7.2.txt


Enter a hexadecimal number of 10 or fewer hex digits
Hex digits are 0-9A-F Code requires uppercase A through F
Press lower case q to stop entry of the hex digits

FEDCBA9876
Enter a hexadecimal number of 10 or fewer hex digits
Hex digits are 0-9A-F Code requires uppercase A through F
Press lower case q to stop entry of the hex digits

123456789A

*********Overflow Error ***********

FEDCBA9876
+123456789A
------------
1111111110
y continues

Enter a hexadecimal number of 10 or fewer hex digits


Hex digits are 0-9A-F Code requires uppercase A through F
Press lower case q to stop entry of the hex digits

CEDCBA9876
Enter a hexadecimal number of 10 or fewer hex digits
Hex digits are 0-9A-F Code requires uppercase A through F
Press lower case q to stop entry of the hex digits

123456789A

CEDCBA9876
+123456789A
------------

24
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

E111111110
y continues

Enter a hexadecimal number of 10 or fewer hex digits


Hex digits are 0-9A-F Code requires uppercase A through F
Press lower case q to stop entry of the hex digits

DEDCBA9876
Enter a hexadecimal number of 10 or fewer hex digits
Hex digits are 0-9A-F Code requires uppercase A through F
Press lower case q to stop entry of the hex digits

123456789A

DEDCBA9876
+123456789A
------------
F111111110
y continues

*/

3. Delete Repeats
//File: ch7prb3.cpp
//
//Problem: to write (and test) a function that has a
//partially filled array of characters as a formal parameter.
//A partially filled array requires two parameters, the array
//itself and a size parameter. The function deletes all
//repeated letters from the array, and close up the 'empty'
//positions, then decrease the size parameter.
//Test this function.

//The main program generates test data.

#include <iostream>

//modifies ‘array’ to delete all instances of any duplicates


//of characters found in ‘array’
void delete_duplicates( char array[], int& size );

//returns number of characters up to the null terminator, \0


int length( char array[]);

25
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

int main()
{
using namespace std;
char array[81]
= "mary had a little lamb. its fleece was white as snow.";
cout << array << endl;
int size;
size = length(array);
cout << "size = " << size << endl;

delete_duplicates( array, size);

cout << "reduced array = " << array << endl;


cout << "reduced array size = " << size << endl;

char array1[81]
="Now is the time for all good men to come to the aid of the country.";

cout << array1 << endl;


size = length(array1);
cout << "size = " << size << endl;

delete_duplicates( array1, size);

cout << "reduced array = " << array1 << endl;


cout << "reduced array size = " << size << endl;
}

void delete_duplicates( char array[], int& size )


{
for ( int i = 0; i < size ; i++)
{
for ( int j = i+1; j < size; j++ )
if ( array[j] == array[i] )
{
//close up array, overwriting array[j]
for ( int k = j; k < size; k++)

26
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

array[k] = array[k+1];
j--; //backup, look at this character again!
size--;
}
}
}

int length( char array[])


{
for ( int i=0; '\0' != array[i]; i++) //strings are terminated by a \0
{ //length is the position of '\0'
//body deliberately empty
}
return i;
}

A test run:
22:24:31:~/AW$ a.out
mary had a little lamb. its fleece was white as snow.
size = 53
reduced array = mary hdliteb.sfwno
reduced array size = 18
Now is the time for all good men to come to the aid of the country.
size = 67
reduced array = Now isthemfralgdncuy.
reduced array size = 21

I found it interesting to do this by hand and compare to the program output.

4. Standard Deviation

// Ch7Prob4.cpp
//
// Define a function that takes a partially filled array of doubles
// as one of two arguments (the other is the size), and returns the
// standard deviation of the numbers in the partially filled array.

27
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

// Embed in a program and test.

#include <iostream>
#include <cmath>
using namespace std;

const int MAX_SIZE = 10;

// Pre: size <= declared size of the array argument


// Post: return the standard deviation first size array elements
// Note: The divisor is the size, not size - 1 as some
// formuals call for.
double stdDev(double s[], int size);

// Pre: size <= declared size of the array argument


// Post: return the mean of the first size array elements
double average(double s[], int size);

int main()
{
double s[MAX_SIZE];
double stdDeviation, avg;
char ans;
do
{
cout << "Enter " << MAX_SIZE << " values, separated by\n"
<< " white space, Terminated each with <cr>. \n"
<< "I will compute the standard deviation.\n";

for(int i = 0; i < MAX_SIZE; i++)


cin >> s[i];

stdDeviation = stdDev(s, MAX_SIZE);

cout << "The Standard Deviation is: "

28
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

<< stdDeviation << endl;


cout << "Y/y continues, any other quits.\n";
cin >> ans;
} while(ans == 'y' || ans == 'Y');

return 0;
}

double stdDev(double s[], int size)


{
double sumSquares = 0;
double avg = average(s, size);

for(int i = 0; i < size; i++)


sumSquares += (s[i] - avg) * (s[i] - avg);

return sqrt(sumSquares / size);


}

double average(double s[], int size)


{
double sum = 0;

for(int i = 0; i < size; i++)


sum += s[i];

return sum / size;


}

5. Count distinct entries

Count distinct entries in an array of user determined size. Maximum size is 50. No solution
is provided to this problem.

29
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

6. Insertion Sort

No solution is provided.

7. a Long integer Adder:

I emphasize strongly that divide and conquer is the secret to successful programming,
regardless of the paradigm. This is why object oriented programming, object based
programming, and procedure oriented programming are effective. Each of these techniques
has its collection of problems for which that particular technique works best. The idea that
is common to these techniques on is the encapsulation of commonalties, the separation of
issues, and the hiding of detail.

//File: ch7prg7.cpp
//Purpose: to sum two large integers (up to 20 digits each).
//
//Input: digits of two integers
//It appears that a "partially filled array structure" is of
//use here.
//
//Output: the sum of the two large integers is written to the
//screen
//
//algorithm: computer version of the traditional paper and pencil
//algorithm.

//Add low order digits, record carry


//while digits remain,
// add next higher order digits and the carry, recording
// the carry
//If the sum is beyond the capacity of a 20 digit array to

30
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

//represent, the program is to report overflow.

#include <iostream>
#include <cstdlib>
#include <cctype>

const int MAX_DIGITS = 20;

struct Large_integer //Design decision: lower indices


correspond
{ //to lower order digits
int digit[MAX_DIGITS+1]; //Making room for the null terminator.
int size; //number of digits
};

//fetches a sequence of digits from the input,


//converts to integer values, records size
void input( Large_integer& number );

//displays the Large_integer's digits in correct order


//on the screen
void output( Large_integer number );

//input: two large integers


//output: a large integer that is the sum of the inputs
void add ( Large_integer first, Large_integer second,
Large_integer& sum);

int main()
{
using namespace std;

31
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

Large_integer first, second, sum;


cout << "Large integer summing program " << endl;
cout << "Please enter an integer, 20 digits or less "
<< endl;
input( first );
cout << "you entered " << endl;
output (first);
cout << endl;
cout << "Enter another integer, 20 digits or less" << endl;
input( second );
cout << "you entered " << endl;
output (second); cout << endl << endl;

cout << "The sum is: " << endl;


output(first);
cout << endl;
output(second);
cout << endl;
cout << "----------------------" << endl;
add (first, second, sum );
output( sum );
cout << endl;

void input( Large_integer& number )


{
using namespace std;
char ch;
int i = 0;
number.size = 0;
cin.get(ch);

32
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

while( '\n' != ch ) //This error handling is too drastic.


{ //Error handling should allow user to
//reenter the number.
if ( !isdigit(ch) )
{
cout << "non digit entered. Aborting. " << endl;
exit(1);
}
number.digit[i] = ch - '0'; //chars are automatically
number.size++; //promoted to integers.
i++;
cin.get(ch);
}

//more draconian error control!


if (number.size > 20 )
{
cout << "Input number size too large. Aborting." <<endl;
exit(1);
}

//Reverse array
for ( int k = 0; k < number.size/2; k++ )
{
int temp = number.digit[k];
number.digit[ k ] = number.digit[ number.size - 1 - k ];
number.digit[ number.size - 1 - k ] = temp;
}
}

void output( Large_integer number )


{

33
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

using namespace std;


//lead spaces to visually align the output.
for ( int i = 20; i >= number.size; i--)
cout << " ";
for ( i = number.size - 1; i >= 0; i-- )
cout << number.digit[i];
}

void add ( Large_integer first,


Large_integer second, Large_integer& sum)
{
int carry = 0;
int larger_size;
//pad the input with the smaller number of digits to the
//size of the larger with zeros.
if ( first.size > second.size )
{
for( int i = second.size; i < first.size; i++)
second.digit[i] = 0;
larger_size = first.size;
}
else
{
for( int i = first.size; i < second.size; i++)
first.digit[i] = 0;
larger_size = second.size;
}

//code to do the addition ...


for ( int i = 0; i < larger_size; i++)
{
sum.digit[i] = first.digit[i] + second.digit[i] + carry;

34
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

if (sum.digit[i] > 9 )
{
carry = 1;
sum.digit[i] = sum.digit[i] - 10;
}
else
carry = 0;
}
if ( 1 == carry )
{
if( larger_size == 20) //the carry is out of digit 20
{
cout << "An overflow has occurred. "
<< "Result is set to 0" << endl;
sum.size = 1;
sum.digit[0] = 0;
}
else //the result is legal.
{
sum.digit[larger_size] = carry;
sum.size = larger_size + 1;
}
}
else //no carry, no problem
sum.size = larger_size;
}

A typical run follows:

$:~/AW$ a.out
Large integer summing program
Please enter an integer, 20 digits or less
2345676543456312987

35
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

you entered
2345676543456312987
Enter another integer, 20 digits or less
432256456785678689
you entered
432256456785678689

The sum is:


2345676543456312987
432256456785678689
----------------------
2777933000241991676
15:28:11:~/AW$

Some of the error checking is tested here:

15:28:49:~/AW$ a.out
Large integer summing program
Please enter an integer, 20 digits or less
9898987656545434334445546
Input number size too large. Aborting.
15:28:57:~/AW$

If the input number is too long, the program aborts:

15:29:22:~/AW$ a.out
Large integer summing program
Please enter an integer, 20 digits or less
98765432101234567890
you entered
98765432101234567890
Enter another integer, 20 digits or less

36
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

234567890987654321123
Input number size too large. Aborting.

Finally, the overflow error test:

15:31:49:~/AW$a.out
Large integer summing program
Please enter an integer, 20 digits or less
98765432109876543210
you entered
98765432109876543210
Enter another integer, 20 digits or less
56789012345678901234
you entered
56789012345678901234

The sum is:


98765432109876543210
56789012345678901234
----------------------
An overflow has occurred. Result is set to 0
0

7. b Adder without structures.

It took about 15 minutes to convert from the struct solution to this non-struct solution. A
reason why the conversion is easy is the structure (pun intended) imposed on the
programming by the use of the struct to relay the information to and from the functions.
Going the other direction is harder.

37
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

I changed the functions declarations (prototypes) to eliminate the struct, then I changed the
main program to agree with the function declarations (prototypes). Then the code in the
input, output, and add functions had to be changed. This amounted to doing a query-
replace of .digit by the empty string, and replacing first.size, second.size, sum.size,
number.size with the . replaced by an underscore.

The result compiles and runs with exactly the same user interface.

Here is the result:

//File: ch7prg7b.cpp
//The Adder problem without structures.
//Purpose: to sum two large integers (up to 20 digits each).
//
//Input: digits of two integers
// It appears that a "partially filled array structure"
//from the text will be of value here.
//Output: the sum of the two large integers is written to the
//screen
//
//algorithm: computer version of the traditional paper and
// pencil algorithm.

//add low order digits, record carry.


//while digits remain,
// add next higher order digits and the carry, recording
// the carry
//If the sum is beyond the capacity of a 20 digit array to
//represent, the program, then report overflow.

#include <iostream>
#include <cstdlib>

38
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

#include <cctype>

const int MAX_DIGITS = 20;

//fetches a sequence of digits from the input,


//converts to integer values, records size
void input( int number[], int& size);

//displays the Large_integer's digits in correct order


//on the screen
void output( const int number[], int size);

//input: two large integers


//output: a large integer that is the sum of the inputs
void add ( int first[], int first_size, int second[],
int second_size, int sum[], int& sum_size);

int main()
{
//Design decision: lower indices correspond
//to lower order digits
using namespace std;
int first[MAX_DIGITS+1];
int first_size; //number of digits first_sizE
int second[MAX_DIGITS +1];
int second_size;
int sum[MAX_DIGITS +1];
int sum_size;

cout << "Large integer summing program " << endl;


cout << "Please enter an integer, 20 digits or less "
<< endl;

39
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

input( first, first_size );


cout << "you entered " << endl;
output (first, first_size);
cout << endl;
cout << "Enter another integer, 20 digits or less" << endl;
input( second, second_size );
cout << "you entered " << endl;
output (second, second_size); cout << endl << endl;

cout << "The sum is: " << endl;


output(first, first_size);
cout << endl;
output(second, second_size);
cout << endl;
cout << "----------------------" << endl;
add(first, first_size, second,
second_size, sum, sum_size );
output( sum, sum_size );
cout << endl;
}

void input( int number[], int& number_size )


{
using namespace std;
char ch;
int i = 0;
number_size = 0;
cin.get(ch);
while( '\n' != ch ) //This error handling is too drastic.
{ //Error handling should allow user to reenter the number.
if ( !isdigit(ch) )
{

40
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

cout << "non digit entered. Aborting. " << endl;


exit(1);
}
number[i] = int(ch) - int('0');
number_size++;
i++;
cin.get(ch);
}

//more draconian error control!


if (number_size > 20 )
{
cout << "Input number size too large. Aborting." <<endl;
exit(1);
}

//Reverse array
for ( int k = 0; k < number_size/2; k++ )
{
int temp = number[k];
number[ k ] = number[ number_size - 1 - k ];
number[ number_size - 1 - k ] = temp;
}
}

void output( const int number[], int number_size )


{
using namespace std;
//lead spaces to visually align the output.
for ( int i = 20; i >= number_size; i--)
cout << " ";
for ( i = number_size - 1; i >= 0; i-- )

41
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

cout << number[i];


}

void add ( int first[], int first_size,


int second[], int second_size,
int sum[], int& sum_size)
{
using namespace std;
int carry = 0;
int larger_size;
//pad the input with the smaller number of digits to the
//size of the larger with zeros.
if ( first_size > second_size )
{
for( int i = second_size; i < first_size; i++)
second[i] = 0;
larger_size = first_size;
}
else
{
for( int i = first_size; i < second_size; i++)
first[i] = 0;
larger_size = second_size;
}

//code to do the addition ...


for ( int i = 0; i < larger_size; i++)
{
sum[i] = first[i] + second[i] + carry;
if (sum[i] > 9 )
{
carry = 1;

42
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

sum[i] = sum[i] - 10;


}
else
carry = 0;
}
if ( 1 == carry )
{
if( larger_size == 20) //the carry is out of digit 20
{
cout << "An overflow has occurred. "
<< "Result is set to 0" << endl;
sum_size = 1;
sum[0] = 0;
}
else //the result is legal.
{
sum[larger_size] = carry;
sum_size = larger_size + 1;
}
}
else //no carry, no problem
sum_size = larger_size;
}

8. Letter Frequency

A note on programming principles recalled while doing this problem:

Students should NOT ATTEMPT to do TOO MUCH in any one function! This leads to
code that is impossible to understand, even for the author of the code. There will be no end
of trouble debugging such code.

43
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

The principle of cohesiveness of a module (whether the module is a function, a class or a


file of functions) states that a module should do one task or a collection of closely related
tasks. A programmer violates this rule at considerable peril.

Urge the students to get one function running first. I usually try to get main running with
stubs, but debugging functions with drivers helps. Then the student should try to get the
whole program running by adding functions to the main one at a time.

This pays off when the programmer discovers that a design error has been made. The
principle of doing a small number of connected things in a function tends to confine the
necessary repairs to one or at most a very few modules, functions, or class member
functions.

//8. Letter Frequency


//
//Input: a line of text terminated with a period, which serves as
//sentinel.
//Output: a list of letters sorted into decreasing order by
//frequency.
//
//Data Structure: array of struct, struct holds a char and int
//(the count).
//
//Algorithm:
//The text is scanned a character at a time, if the character
//is present in the data structure, then update the count, if
//not present insert the new character in the data structure,
//update the count to 1. The array of structs is sorted on
//the count key.

#include <iostream>
#include <cassert>

44
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

#include <cctype>

struct char_freq
{
char ch;
int count;
};

//NOTE that all that is necessary in the headers is to


//replace int with char_freq

void sort(char_freq a[], int number_used);


//Precondition: number_used <= declared size of the array a.
//The array elements a[0] through a[number_used - 1] have
//values.
//Postcondition: The values of a[0] through
//a[number_used - 1] have been rearranged so that
//a[0] <= a[1] <= ... <= a[number_used - 1].

void swap_values(char_freq& v1, char_freq& v2);


//Interchanges the values of v1 and v2.

int index_of_smallest(const char_freq a[],


int start_index, int number_used);
//Precondition: 0 <= start_index < number_used.
//Referenced array elements have values.
//Returns the index i such that a[i].count is the smallest of
//the values
//a[start_index].count, a[start_index + 1].count, ...,
//a[number_used - 1].count

void input( char_freq list[], int& size);

45
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

//list is an array of char_freq structs.


//reads input, period is sentinel. Sets the char members of the
//char_freq struct elements of list to newly occurring characters,
// otherwise, if the struct already has the character, this routine
// increments the count for that character.

void output( char_freq list[], int size );


//lists Letter, Number of Occurrences in columns

int main()
{
char_freq list[50] ={0,0}; //we are going to pick up
//punctuation, etc.
int list_size = 0;
input( list, list_size );
sort( list, list_size );
output( list, list_size);
return 0;
}

//traverses the elements of list through size elements


//if an element containing c is found,
// increment count in the list member for that character
// returns true (1) (c is in the list)
//else
// returns false(0) (c is not in the list)
bool lookup( char c, char_freq list[], int& size );

//precondition: c is not in the list


//post condition: c has been added in position size,
//size has been incremented.
//size <= 26

46
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

void insert( char c, char_freq list[], int& size );

void input(char_freq list[], int& size)


{
using namespace std;
char ch;
cin >> ch; //we want to ignore blanks, so we use cin >>...
ch = tolower(ch); // Push everything to lowercase.
while('.' != ch)
{
if (!lookup(ch, list, size))
insert(ch, list, size);
cin >> ch;
}
}

void insert(char c, char_freq list[], int& size)


{
list[size].count=1;
list[size].ch = c;
size ++;
assert( size <= 26);
}

bool lookup(char c, char_freq list[], int& size)


{
int i = 0;
bool success = false;
do
{
if (c == list[i].ch)
{

47
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

list[i].count++;
success = true;
return success;
}
i++;
} while(i <= size);
assert(i <= 27); //Debugging aid, see the Text’sAppendix
//for the details of the Assert macro.
return success;
}

void output( char_freq list[], int size )


{
using namespace std;
cout << "Letter:\tNumber of Occurrences." << endl;
for ( int i = 0; i < size; i++)
cout << list[i].ch << '\t' << list[i].count << endl;
}

A data file

21:55:53:~/AW$ cat file1


Now is the time for all good men to come to the aid of the
country for if they do not, the whole thing may break up and
go down the drain.
21:55:56:~/AW$

Output generated before sorting.

21:55:10:~/AW$ a.out < file1


Letter: Number of Occurrences.
n 8

48
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

o 15
w 3
i 6
s 1
t 12
h 8
e 11
m 4
f 4
r 5
a 6
l 3
g 3
d 6
c 2
u 2
y 3
, 1
b 1
k 1
p 1
21:55:15:~/AW$

Here is some output after the sort routine was modified for use here. See that file for some
suggestions on how to modify it.

23:44:52:~/AW$ a.out
Mary had a little lamb Its fleece was white as snow.
Letter: Number of Occurrences.
a 6
e 5
s 5
l 4

49
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

t 4
w 3
i 2
h 2
m 2
y 1
b 1
I 1
r 1
f 1
d 1
n 1
o 1

9. Poker Hand Evaluator

//File: ch7prg9.cpp
//
//9. Score a five-card poker hand into one of the following
// categories:
// nothing
// one pair
// two pairs
// three of a kind
// straight (in order, no gaps)
// flush ( all same suite, for example, all spades)
// full house (one pair and three of a kind)
// four of a kind
// straight flush (hand is both a straight and flush)

//Use array of struct to store the hand. Structure will have


//two member variables: one for the value of the card and one
//for the suit.

50
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

//Include a loop that allows the user to continue to score more


//hands until the user says the program should end.

//Programming note:
//I made a design error that I did not discover until the program
//was in final testing. Because the problem had been written using
//the principle "one function does one thing", the changes needed
//were confined to just a few functions.
//
//I had used a char for the face value, using 2 - 9 and the 't'
//'j' 'q' 'k' and 'a' for ten through ace. For test data that was
//a digit, the sort routine for the struct from an earlier problem
//(modified to sort small to large) worked fine. Once a test was
//made using any of the "face cards" ten, jack, queen, king, ace.
//It was found that the sort routine worked. BUT NOT correctly.

//In this problem, ten < jack < queen < king < ace. BUT the
//order using the ASCII encoding is 'a' < 'k' < 'q' < 't'
//which is not at all what we need. The use of the enum for the
//face value of the card with the few changes this necessitated
//was the necessary repair. This should be no problem for the
//student, since the enum is dealt with in the text with
//considerable care in Chapter 3, page 354 and following.

//If you have not done the enum data type, I have presented, but
//have commented out, declarations that can be used to side step
//this problem, and have added (also commented out) const int
//declarations for the enum constants along with suggestions for
//replacing the three enum tags with int.

//Compile command: (Use the appropriate command for your

51
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

//system – BCC32, CL –GX, CC etc.)


//g++ ch7prg8.cpp sort_hand.cpp

#include <iostream>
#include <cstdlib>
#include <cctype>

enum Hand_Value { NOTHING, ONE_PAIR, TWO_PAIRS, THREE_OF_KIND,


STRAIGHT, FLUSH,FULL_HOUSE, FOUR_OF_KIND,
STRAIGHT_FLUSH};

//Remark: It is recommended that enum constants be upper case.


//I violated this with the word flush, and got the very unclear
//error message: '5' redeclared as different kind of symbol.
//The error occurs because flush is already declared in the
//iostream library.

enum Card_Suite { CLUBS, DIAMONDS, HEARTS, SPADES };


enum Face_Value { TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT,
NINE, TEN, JACK, QUEEN, KING, ACE };

//If you have not done enums, the following declarations enable
//this code to run correctly without the enum declarations. You
//may wish to do a global search and replace instead of using
//these typedef statements, since typedef has not yet been
//treated in the text. There is a short discussion of typedef
//in the text. See the box, Type Definitions.
//typedef int Card_suite;
//typedef int Face_Value;
//typedef int Hand_Value;
//const int NOTHING =0 , ONE_PAIR= 1, TWO_PAIRS=3,
// THREE_OF_KIND=4, STRAIGHT=5, FLUSH=6,FULL_HOUSE=7,

52
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

// FOUR_OF_KIND=8, STRAIGHT_FLUSH=9;
//const int CLUBS=0, DIAMONDS=1, HEARTS=2, SPADES=3;
//const int TWO=0 , THREE=1, FOUR=2, FIVE=3, SIX=4, SEVEN=5,
// EIGHT=6, NINE=7, TEN=8, JACK=9, QUEEN=10, KING=11,
// ACE=12;
//
//I tested these changes.

struct Card
{
Card_Suite suite;
Face_Value face;
};

//this will be in main


//Card hand[5];

//Helping function for input routine


//This greatly simplifies the work in the rest of the program.
//Postcondition: The Card hand[] array is sorted on value
//The student should modify sort from the previous problem.
void sort_hand ( Card hand[], int number_used );

//Prompts for and fetches a hand from standard input


void input ( Card hand[] );

//Helping functions for evaluate( Card hand[] );

int has_four(Card hand[]);


//Precondition: function is called
//Postcondition:
//if there are 4 equal values in the hand,

53
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

// returns true
//else
// returns false

int has_three (Card hand[]);


//Precondition: has_four returns false when called on this hand
//Postcondition:
//if there are 3 of a kind,
// returns true,
//else
// returns false

int is_full_house ( Card hand[] );


//Postcondition:
//if the two cards other than the three of a kind are equal,
// return true
//else
// return false

int has_two_pair( Card hand[]);


//precondition: has_four returns false.
//if two pair are in the hand, returns true
//else returns false

int has_one_pair( Card hand[]);


//Precondition: has_four, has_three, has_two_pair all return
//false if one pair are in the hand, returns true else returns
//false

int is_straight (Card hand[]);


//Precondition: function has been called

54
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

//Postcondition:
//if the cards are in sequence,
// return true
//else
// return false

int is_flush( Card hand[] );


//Precondition: function is called
//Postcondition:
//if all cards have same suite,
// return true
//else
// return false

Hand_Value evaluate(Card hand[]);


//Precondition: function is called with a poker hand array of
// Cards
//Postcondition: hand is evaluated and an appropriate value
//from enum Hand_Value is returned

//lists hand in format suite, value


void output_hand( Card hand[] );

//calls evaluate then outputs translation of enum Hand_Value


void report_hand_value( Card hand[]);

//reports hand in human readable form


void output_hand( Card hand[] );

int main()
{
using namespace std;

55
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

char ans;
Card hand[5];
cout << "Poker Hand Evaluation Program - " << endl
<< "Please Enter a 5 card poker hand, "
<<"I'll evaluate this "
<< "hand as one of " << endl
<< "NOTHING, ONE_PAIR, TWO_PAIRS, THREE_OF_KIND, "
<< "STRAIGHT FLUSH, FULL_HOUSE" << endl
<< "FOUR_OF_KIND, or STRAIGHT_FLUSH" << endl << endl
<< "Encode Clubs as c, Diamonds as d, Hearts as h, "
<< " Spades as s" << endl
<< "Enter the value as 2-9, t, j, q, k a, "
<< " Upper case OK " << endl << endl;
do
{
input ( hand );
cout << "\nSorted hand is: " << endl;
output_hand( hand );
cout << "value of hand is: " ;
report_hand_value( hand );
cout << endl << endl;
cout << "Y/y continues, other halts." << endl << endl;
cin >> ans;
}while ( 'Y' == ans || 'y' == ans );
}

void report_hand_value( Card hand[])


{
switch( evaluate( hand ) )
{
case NOTHING:
cout << "Nothing";

56
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

break;
case ONE_PAIR:
cout << "One Pair";
break;
case TWO_PAIRS:
cout << "Two Pair";
break;
case THREE_OF_KIND:
cout << "Three of a Kind";
break;
case STRAIGHT:
cout << "Straight";
break;
case FLUSH:
cout << "Flush";
break;
case FULL_HOUSE:
cout << "Full House";
break;
case FOUR_OF_KIND:
cout << "Four of a Kind";
break;
case STRAIGHT_FLUSH:
cout << "Straight Flush";
break;
default:
cout << " Something is very wrong. Bad value ";
break;
}
}

Hand_Value evaluate( Card hand[] )

57
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

{
Hand_Value value;
if ( is_straight(hand) )
if (is_flush( hand ))
return STRAIGHT_FLUSH;
if ( has_four(hand) )
return FOUR_OF_KIND;
if (is_full_house(hand) )
return FULL_HOUSE;
if (is_flush(hand) )
return FLUSH;
if (is_straight(hand) )
return STRAIGHT;
if ( has_three(hand) )
return THREE_OF_KIND;
else if ( has_two_pair(hand) )
return TWO_PAIRS;
else if ( has_one_pair(hand) )
return ONE_PAIR;
else return NOTHING;
}

void get_face ( Face_Value & value)


{
using namespace std;
char ch;
cin >> ch;
switch( ch )
{
case '2': value = TWO;
break;
case '3': value = THREE;

58
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

break;
case '4': value = FOUR;
break;
case '5': value = FIVE;
break;
case '6': value = SIX;
break;
case '7': value = SEVEN;
break;
case '8': value = EIGHT;
break;
case '9': value = NINE;
break;
case 't': value = TEN;
break;
case 'j': value = JACK;
break;
case 'q': value = QUEEN;
break;
case 'k': value = KING;
break;
case 'a': value = ACE;
break;
default: cout << "Bad face value. Aborting!";
exit(1);
}
}

void put_face ( Face_Value& face)


{
using namespace std;
switch ( face )

59
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

{
case TWO: cout << 2;
break;
case THREE: cout << 3;
break;
case FOUR: cout << 4;
break;
case FIVE: cout << 5;
break;
case SIX: cout << 6;
break;
case SEVEN: cout << 7;
break;
case EIGHT: cout << 8;
break;
case NINE: cout << 9;
break;
case TEN: cout << 10;
break;
case JACK: cout << "Jack";
break;
case QUEEN: cout << "Queen";
break;
case KING: cout << "King";
break;
case ACE: cout << "Ace";
break;
default: cout << "Bad card face Aborting";
exit(2);
}
}

60
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

//Prompts for and fetches a hand from standard input


//returns hand sorted by value
void input ( Card hand[] )
{
using namespace std;
char suite;
Face_Value face;
for( int i = 0; i <= 4; i++)
{
cout << "Card " << i+1 << " suite: ";
cin >> suite;
cout << " " << "suite entered: " << suite << " " ;
cout << ", face: " ;
get_face( face );
cout << " face entered: ";
put_face( face );
cout << endl;
suite = tolower( suite );
hand[i].face = face;

switch ( suite )
{
case 'c': hand[i].suite = Card_Suite(0);
break;
case 'd': hand[i].suite = Card_Suite(1);
break;
case 'h': hand[i].suite = Card_Suite(2);
break;
case 's': hand[i].suite = Card_Suite(3);
break;
default: cout << "bad suite, aborting" << endl;
exit(1);

61
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

}
}
sort_hand( hand, 5 );
}

//returns true if the card values are in sequence


int is_straight (Card hand[])
{

if(hand[0].face + 1 == hand[1].face
&& hand[0].face + 2 == hand[2].face
&& hand[0].face + 3 == hand[3].face
&& hand[0].face + 4 == hand[4].face )
return 1;
else
return 0;
}

int is_flush( Card hand[] )


{
if(hand[0].suite == hand[1].suite
&& hand[1].suite == hand[2].suite
&& hand[2].suite == hand[3].suite
&& hand[3].suite == hand[4].suite )
return 1;
else
return 0;
}

int has_four(Card hand[])


{

62
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

//The values are sorted, so 4 of a kind is either at the start


or the
//end of the hand!

if(hand[0].face == hand[1].face
&&hand[1].face == hand[2].face
&&hand[2].face == hand[3].face
||
hand[1].face == hand[2].face
&&hand[2].face == hand[3].face
&&hand[3].face == hand[4].face )
return 1;
else
return 0;
}

int has_three (Card hand[])


//Precondition: has_four returns false when called on this hand
//Postcondition:
//if there are 3 of a kind,
// returns true,
//else
// returns false
{

if(hand[0].face == hand[1].face
&&hand[1].face == hand[2].face
||
hand[1].face == hand[2].face
&&hand[2].face == hand[3].face
||
hand[2].face == hand[3].face

63
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

&&hand[3].face == hand[4].face )
return 1;
else
return 0;
}

//Precondition:
//Postcondition:
//if the two cards other than the three of a kind are equal,
// return true
//else
// return false

int is_full_house ( Card hand[] )


{
//Either the first three are the same and the last two are the
//same or the last three are same, and the first two are the
//same

if(hand[0].face == hand[1].face
&&hand[1].face == hand[2].face
&&hand[3].face == hand[4].face
||
hand[0].face == hand[1].face
&&hand[2].face == hand[3].face
&&hand[3].face == hand[4].face )
return 1;
else
return 0;
}

//precondition: has_four returns false.

64
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

//if two pair are in the hand, returns true


//else returns false
int has_two_pair( Card hand[])
{
if(hand[0].face == hand[1].face && //odd card is [4]
hand[2].face == hand[3].face
||
hand[0].face == hand[1].face && //odd card is [2]
hand[3].face == hand[4].face
||
hand[1].face == hand[2].face && //odd card is [0]
hand[3].face == hand[4].face )
return 1;
else
return 0;
}

//Precondition: has_four, has_three, has_two_pair all return


false
//if one pair are in the hand, returns true
//else returns false
int has_one_pair( Card hand[])
{
if ( hand[0].face == hand[1].face ||
hand[1].face == hand[2].face ||
hand[3].face == hand[4].face )
return 1;
else
return 0;
}

//lists hand in format suite, value

65
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

void output_hand( Card hand[] )


{
using namespace std;
for (int i = 0; i < 5; i++ )
{
switch( hand[i].suite )
{
case CLUBS: cout << "Clubs ";
break;
case DIAMONDS: cout << "Diamonds";
break;
case HEARTS: cout << "Hearts ";
break;
case SPADES: cout << "Spades ";
break;
default: cout << "something is WRONG - no such suite"
<< endl;
exit(1);
}
cout << '\t';
put_face( hand[i].face );
cout << endl;
}
}

//File: sort_hand.cpp
//
//Most of the changes were made with a query-search command.
//

#include <iostream.h>

66
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

enum Card_Suite { CLUBS, DIAMONDS, HEARTS, SPADES };


enum Face_Value { TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT,
NINE, TEN, JACK, QUEEN, KING, ACE };

struct Card
{
Card_Suite suite;
Face_Value face;
};

void sort_hand(Card a[], int number_used);


//Precondition: number_used <= declared size of the array a.
//The array elements a[0] through a[number_used - 1] have
//values.
//Postcondition: The values of a[0] through a[number_used - 1]
// have been rearranged so that
//a[0].value <= a[1].value <= ... <= a[number_used - 1].value.

void swap_values(Card& v1, Card& v2);


//Interchanges the values of v1 and v2.

int index_of_smallest(const Card a[], int start_index,


int number_used);
//Precondition: 0 <= start_index < number_used.
//Referenced array elements have values.
//Returns the index i such that a[i].value is the smallest of
//the values
//a[start_index].value, a[star_index + 1].value, ...,
// a[number_used - 1].value.

//Sorts on the value key


void sort_hand(Card a[], int number_used)

67
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

{
int index_of_next_smallest;
for (int index = 0; index < number_used - 1; index++)
{//Place the correct value in a[index]:

index_of_next_smallest =
index_of_smallest(a, index, number_used);
swap_values(a[index], a[index_of_next_smallest]);
//a[0] <= a[1] <=...<= a[index] are smallest of original
//array elements. The rest of the elements are in the
//remaining positions.
}
}

void swap_values(Card& v1, Card& v2)


{
Card temp;
temp = v1;
v1 = v2;
v2 = temp;
}

int index_of_smallest(const Card a[], int start_index,


int number_used)
{
Face_Value min = a[start_index].face;
int index_of_min = start_index;
for (int index = start_index + 1; index < number_used;
index++)
if (a[index].face < min)
{
min = a[index].face;

68
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

index_of_min = index;
//Assert: min is the smallest of a[start_index].face
//through a[index].face
}
return index_of_min;
}

I am including more test data than for some other problems since I discovered errors in my
code with many of these cases. In the interest of space, I am presenting only part of the output.

Data for a run to test various aspects of the program follow:


21:28:39:~/AW$ cat card_data
c k c 9 c t c j s 2
y
c 5 s a c 2 d 2 c 4
y
s 3 c k c 2 d 2 h 3
y
c t s 3 s t d t c 4
y
s k c 9 s j c q d t
y
c 2 c 8 c 7 c 3 c 5
y
h 3 s 3 c 2 d 2 c 3
y
h q c a d q c q s q
y
s a s q s k s t s j
n

The compile command used to generate the executatable is:

21:24:28:~/AW$ g++ sort_hand.cpp ch7prg8.cpp

69
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

A command that runs the program after compilation, with the above data.

21:27:30:~/AW$ a.out < card_data > card_output

Note that the output is a little nicer than the interactive run:

21:44:33:~/AW$ cat card_output


Poker Hand Evaluation Program -
Please Enter a 5 card poker hand, I'll evaluate this hand as one of
NOTHING, ONE_PAIR, TWO_PAIRS, THREE_OF_KIND, STRAIGHT FLUSH, FULL_HOUSE
FOUR_OF_KIND, or STRAIGHT_FLUSH

Encode Clubs as c, Diamonds as d, Hearts as h, Spades as s


Enter the value as 2-9, t, j, q, k a, Upper case OK

Card 1 suite: suite entered: c , face: face entered: King


Card 2 suite: suite entered: c , face: face entered: 9
Card 3 suite: suite entered: c , face: face entered: 10
Card 4 suite: suite entered: c , face: face entered: Jack
Card 5 suite: suite entered: s , face: face entered: 2

Sorted hand is:


Spades 2
Clubs 9
Clubs 10
Clubs Jack
Clubs King
value of hand is: Nothing

Y/y continues, other halts.

Card 1 suite: suite entered: c , face: face entered: 5


Card 2 suite: suite entered: s , face: face entered: Ace
Card 3 suite: suite entered: c , face: face entered: 2
Card 4 suite: suite entered: d , face: face entered: 2
Card 5 suite: suite entered: c , face: face entered: 4

Sorted hand is:

70
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

Clubs 2
Diamonds 2
Clubs 4
Clubs 5
Spades Ace
value of hand is: One Pair

Y/y continues, other halts.

Card 1 suite: suite entered: s , face: face entered: 3


Card 2 suite: suite entered: c , face: face entered: King
Card 3 suite: suite entered: c , face: face entered: 2
Card 4 suite: suite entered: d , face: face entered: 2
Card 5 suite: suite entered: h , face: face entered: 3

Sorted hand is:


Clubs 2
Diamonds 2
Spades 3
Hearts 3
Clubs King
value of hand is: Two Pair

Y/y continues, other halts.

Card 1 suite: suite entered: c , face: face entered: 10


Card 2 suite: suite entered: s , face: face entered: 3
Card 3 suite: suite entered: s , face: face entered: 10
Card 4 suite: suite entered: d , face: face entered: 10
Card 5 suite: suite entered: c , face: face entered: 4

Sorted hand is:


Spades 3
Clubs 4
Spades 10
Diamonds 10
Clubs 10
value of hand is: Three of a Kind

71
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

Y/y continues, other halts.

. . .

Y/y continues, other halts.

Card 1 suite: suite entered: h , face: face entered: Queen


Card 2 suite: suite entered: c , face: face entered: Ace
Card 3 suite: suite entered: d , face: face entered: Queen
Card 4 suite: suite entered: c , face: face entered: Queen
Card 5 suite: suite entered: s , face: face entered: Queen

Sorted hand is:


Hearts Queen
Diamonds Queen
Clubs Queen
Spades Queen
Clubs Ace
value of hand is: Four of a Kind

Y/y continues, other halts.

Card 1 suite: suite entered: s , face: face entered: Ace


Card 2 suite: suite entered: s , face: face entered: Queen
Card 3 suite: suite entered: s , face: face entered: King
Card 4 suite: suite entered: s , face: face entered: 10
Card 5 suite: suite entered: s , face: face entered: Jack

Sorted hand is:


Spades 10
Spades Jack
Spades Queen
Spades King
Spades Ace
value of hand is: Straight Flush

Y/y continues, other halts.

72
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

10. tic-tac-toe

This program is to ask for moves alternately from players X and O. The display should be
board-like:

1 2 3
4 5 6
7 8 9

The players enter their moves by entering a number corresponding to the place to be
marked. After each move, the program displays the changed board. After several moves
the board may appear:

X X O
4 5 6
O 8 9

Planning:

Input,
Play
Output

This can be done with a simple one dimension array to hold the game, a play function, a
display function and a scoring function, which can be called by the play function.

The way I approached this is to have a Game class. This class has a constructor and a
play member having a char parameter, 'X' and 'O' for permissible arguments. The
class has private functions score() and display(), and a char array as a data
member.

Main declares game to be a Game object, and calls game_play(). The game_play()
function alternately calls play('X') and play('O'), the function play prompts

73
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

players for input, modifies the data in array, calls display_array(), then runs the
score() member which returns 'X' if player X wins, 'O' if player O wins, 'T' for
tie, or '\0' (NULL) for no winners.

I have a line of code that reports the number of plays remaining.

There is one additional wrinkle that is not covered in the text, but works on all systems
having a standard C/C++ library. The library call int system( char [] str )
function executes any shell command the user puts into its argument.

(A shell command is any command you use to do something at the system's prompt, $,
such as dir, ls, clear or cls, etc.)

Here I use system("clear") since most Unix systems respond to that by clearing
the screen and placing the cursor in the upper left hand position of the screen. If you are
using MS DOS you should use system("cls"), since the MS DOS command to clear
the screen is "cls".

I was pleased and surprised with the ease of initialization of the array data member in the

constructor:

Game::Game():array("123456789")
{
}

I was disappointed to find this does NOT WORK with BC++! (It is one of the g++
extensions to the language. I warn my students about these and in the interest of
portability, and I do not allow their use.) I replaced this nonstandard initialization with a
standard array initialization using a loop in this constructor in the program.

Take care not to allow the overwriting of a position already occupied by an opponent with
one of your own. This again points out the necessity for complete testing. I finished this
problem and would have left it, were it not for my accidentally using a cell that was

74
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

already occupied. It worked. I fixed that with a loop that required the location being used
to still have a digit in it.

Take care to make your program robust. I found and fixed a couple of loops in my code
that bad input caused to go infinite.
// ********************************************************************
// Ch7Proj10.cpp
//
// This program plays tic-tac-toe using a 1D array to represent
// the board.
// It does not check for a win, only an end of game.
// ********************************************************************

#include <iostream>

using namespace std;

// Prototype
void showBoard(char board[]);

// This function displays a board


// on the screen. It outputs each
// character in the array, putting a newline
// every three characters.
void showBoard(char board[])
{
cout << endl;
for (int i=0; i<9;i++)
{
cout << board[i] << " ";
if (((i+1) % 3) == 0) cout << endl;
}
cout << endl;
}

// ====================
// main function
// ====================

int main()
{
char board[9]; // Holds digits, X, or O
int i;
int numMoves = 0; // Number of moves
char whoseTurn = 'X'; // Current player's move
int move;

// Initialize board to character digits 1-9


for (i=0; i<9; i++)

75
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

{
board[i] = '1' + i;
}

// Get a move until all 9 moves used


while (numMoves < 9)
{
showBoard(board);
cout << "Enter move: " << endl;
cin >> move;
if ((move <1) || (move>9))
{
cout << "Invalid move, try again." << endl;
}
else
{
move--; // Our array is 0 based, not 1 based
if ((board[move]=='X') || (board[move]=='O'))
{
cout << "That space is taken. " << endl;
}
else
{
board[move] = whoseTurn;
// Switch turns
if (whoseTurn == 'X')
whoseTurn = 'O';
else
whoseTurn = 'X';
numMoves++;
}
}
}
showBoard(board);
cout << endl << "Game over!" << endl;
return 0;

11. Airline Seating Program.

// Airline Seating Program


// File: ch7.13.cpp

// Chapter 7 # 13: Assign Passenger seating. Assume 7 rows 4 wide with


// seats assigned in this manner
//
// 1 A B D C
// 2 A B D C
// 3 A B D C
// 4 A B D C
// .
// .
// N A B D C

76
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

// .
// .
// last A B D C
//
// Program requests number of rows.the displays the seating pattern
// with an X for occupied rows
//
// 1 X B C D
// 2 A X C D
// 3 A B C D
// 4 A B X D
// .
// .
// .
// k A B C D
// .
// .
// .
// n-1 A B C D
// n A B C D
//
// The program then requests a choice of seat.
// If the seat if availabler, then the seating display is updated.
// otherwise, the program requests another choice of seat.
//
// KNOWN BUGS:
// If the user incorrectly enters the seat letter for the row
// designation, the program goes into a continuing loop. Control C
// under most operating systems stops the program. It would be a
// nice enhancement to make the input more robust.

#include <iostream>
#include <cstdlib>
#include <cstddef>

//typedef char* CharArrayPtr;


//CharArrayPtr a;
//a = new char[number_of_rows];

const int NO_ROWS = 7;

typedef char SeatRow[4];

typedef SeatRow Seating[NO_ROWS];

Seating seatAssignment;

int main()
{
using std::cout;
using std::cin;

77
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

using std::endl;

Seating plan;

int row;
char seat;
int seatNo;
int r;
int s;

//Initialize seating to empty


for(r = 0; r < NO_ROWS; r++)
for (s = 0; s < 4; s++)
plan[r][s] = char ('A' + s);

cout << "Savitch Airlines\n"


<< "Seat Reservation Program.\n"
<< "Reserved seats are marked 'X'. Others are available.\n";

// Display seats
for(r = 1; r < NO_ROWS; r++)
{
for (s = 0; s < 4; s++)
{
cout << plan[r][s] << " ";
if(s == 1 )
cout << " ";
}
cout << endl;
}

char ans = 'a';


while(ans != 'n' && ans != 'N')
{
cout << "Savitch Airlines\n"
<< "Seat Reservation Program.\n"
<< "Reserved seats are marked 'X'. Others are available.\n";

cout << "Please enter your requst in the form \"3 C\" for Row 3, Seat
C\n"
<< "There are " << NO_ROWS << " rows. Seats are A, B, C, D.\n";
cin >> row >> seat;
seatNo = seat - 'A';

if('X' != plan[row][seatNo])
plan[row][seatNo] = 'X';
else
cout << "****That seat is taken****.\n****No assignment
made****.\n"

78
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

<< "****Please make another request****\n";

//Display current seating


for(r = 1; r < NO_ROWS; r++)
{
for (s = 0; s < 4; s++)
{
cout << plan[r][s] << " ";
if(s == 1 )
cout << " ";
}
cout << endl;
}
cout << "N or n quits, anyting else continues\n";
cin >> ans;

return 0;
}

/*

Typical run

Savitch Airlines
Seat Reservation Program.
Reserved seats are marked 'X'. Others are available.
A B C D
A B C D
A B C D
A B C D
A B C D
A B C D
Savitch Airlines
Seat Reservation Program.
Reserved seats are marked 'X'. Others are available.
Please enter your requst in the form "3 C" for Row 3, Seat C
There are 7 rows. Seats are A, B, C, D.
3D
A B C D
A B C D
A B C X
A B C D
A B C D
A B C D
N or n quits, anyting else continues
y
Savitch Airlines
Seat Reservation Program.
Reserved seats are marked 'X'. Others are available.

79
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

Please enter your requst in the form "3 C" for Row 3, Seat C
There are 7 rows. Seats are A, B, C, D.
3D
****That seat is taken****.
****No assignment made****.
****Please make another request****
A B C D
A B C D
A B C X
A B C D
A B C D
A B C D
N or n quits, anyting else continues
n
Press any key to continue

*/

12. No Solution Provided.

13. No Solution Provided.

14.
//
***********************************************************************
// Ch7Proj14.cpp
//
// This program searches a list of the top 1000 most popular
// Baby Names from the year 2004 and outputs the popularity rank.
// It uses arrays to store the list of names.
//
//
***********************************************************************

#include <iostream>
#include <fstream>
#include <cstdlib>

using namespace std;


const int NUMNAMES=1000; // Number of names in the
file

// ======================
// main function
// ======================
int main()
{
string targetName; // Target name
string boyName, girlName; // Temp boy/girl name

80
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

int popularity; // Temp popularity


string boyNames[NUMNAMES]; // Array of boy names
string girlNames[NUMNAMES]; // Array of girl names
int boyPopularity, girlPopularity; // Popularity of match
ifstream in_stream;
int i;

// First load the names from the file into the arrays.
// Assumes the file "babynames2004.txt" is in the current directory
in_stream.open("babynames2004.txt");
if (in_stream.fail())
{
cout << "Input file opening failed." << endl;
exit(-1);
}

// Read each name from the file along with the popularity
for (i=0; i < NUMNAMES; i++)
{
// Input popularity, boy name, and girl name
in_stream >> popularity >> boyName >> girlName;
// Store in array
boyNames[i] = boyName;
girlNames[i] = girlName;
}
in_stream.close();

// Input target name


cout << "Enter the first name that you would like to find the " <<
endl;
cout << "popularity of from baby names in 2004." << endl;
cout << "Be sure to capitalize the first letter of the name." <<
endl;
cin >> targetName;
cout << endl;

// Search for name in arrays


boyPopularity = -1;
girlPopularity = -1;
for (i=0; i < NUMNAMES; i++)
{
if (boyNames[i] == targetName)
{
boyPopularity = i+1;
}
if (girlNames[i] == targetName)
{
girlPopularity = i+1;
}
}

// Output results
cout << targetName << " is ";

81
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

if (boyPopularity > 0)
{
cout << "ranked " << boyPopularity << " in popularity among
boys.\n";
}
else
{
cout << "not ranked among the top 1000 boy names.\n";
}
cout << targetName << " is ";
if (girlPopularity > 0)
{
cout << "ranked " << girlPopularity << " in popularity among
girls.\n";
}
else
{
cout << "not ranked among the top 1000 girl names.\n";
}
return 0;
}

15.
//
***********************************************************************
// Ch7Proj15.cpp
//
// This program draws a bar chart using the SVG file format.
// It uses an input array with value of -1 to signal the end of
// values to graph. It supports up to 100 entries.
//
//
***********************************************************************

#include <iostream>
#include <fstream>
#include <cstdlib>

using namespace std;

const double MAXHEIGHT = 400; // Maximum height in


pixels
const int MAXSIZE = 100; // Maximum size of
the array

// Function prototypes
int findMax(const int a[]);
void saveSVG(int a[]);

82
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

// ======================
// findMax:
// Scans through the array and returns
// the largest value in the array.
// ======================
int findMax(const int a[])
{
int i, biggestBar, curValue;

i = 0;
curValue = 0;
biggestBar = -1;
while ((curValue != -1) && (i < MAXSIZE))
{
curValue = a[i];
if (curValue > biggestBar)
{
biggestBar = a[i];
}
i++;
}
return biggestBar;
}

// ======================
// saveSVG:
// Saves the graph as an SVG file.
// ======================
void saveSVG(int bars[])
{
int i;
ofstream out_stream;
int biggestBar;
double scale;

// Find size of biggest bar


biggestBar = findMax(bars);

// Scaling factor is maxheight / biggest bar


scale = MAXHEIGHT / static_cast<double>(biggestBar);

// Multiply each bar by the scale and cast back to an Integer


for (i=0; ((i<MAXSIZE) && (bars[i]!=-1)); i++)
{
bars[i] = static_cast<int>(bars[i] * scale);
}

out_stream.open("Ch7Proj15.svg");
if (out_stream.fail())
{
cout << "Output file opening failed." << endl;
exit(-1);

83
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

}
// Output "boilerplate" for SVG files
out_stream << "<?xml version=\"1.0\" standalone=\"no\"?>" << endl;
out_stream << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"" <<
endl;
out_stream <<
"\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"> " << endl;
out_stream << "<svg width=\"500\" height=\"500\"
xmlns=\"http://www.w3.org/2000/svg\">" << endl;

// Draw axis
out_stream << "<line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"" <<
MAXHEIGHT-1 << "\" " << endl;
out_stream << "style=\"stroke:purple;stroke-width:2\"/>" << endl;
out_stream << "<line x1=\"0\" y1=\"" << MAXHEIGHT-1 << "\" x2=\""
<< MAXHEIGHT-1 << "\" y2=\"" << MAXHEIGHT-1 << "\" " << endl;
out_stream << "style=\"stroke:purple;stroke-width:2\"/>" << endl;

// Draw each bar with a width of 2 so we can fit up to 100 bars.


// A nicer output would be to compute the number of bars and scale
// the width of each bar so together all of them draw in a width of
400 pixels.
for (i=0; ((i<MAXSIZE) && (bars[i]!=-1)); i++)
{
out_stream << "<rect x=\"" << (i*4)+1 << "\" y=\"" <<
MAXHEIGHT-1-bars[i] <<"\" width=\"2\" height=\"" << bars[i] << "\"" <<
endl;
out_stream << " style=\"fill:blue;\"/>";
}

// End SVG file and close


out_stream << "</svg>" << endl;
out_stream.close();
}

// ======================
// main function
// ======================
int main()
{
int bars[MAXSIZE]; // Values for bar chart
int i = 0, temp = 0;

while (temp != -1)


{
// Input bar values
cout << "Enter non-negative value for bar " << i+1 << ", -1
to exit." << endl;
cin >> temp;
bars[i] = temp;
i++;

84
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

}
saveSVG(bars);

return 0;
}

16.

// ****************************************************************
//
// Ch7Proj16.cpp
//
// This program implements a memory matching game.
//
// It uses a 2D array to store the cards (pairs of numbers 1-8)
// and randomly shuffles them through repeated swaps. It uses a
// second 2D array to record whether or not a card is face up or
// face down.
//
// ****************************************************************

#include <iostream>
#include <cstdlib>

const int LENGTH = 4;


const int NUM_TRIALS = 10000;

using namespace std;

// Function prototypes
void InitializeCards(int cards[][LENGTH]);
void ShowCards(int cards[][LENGTH], bool faceup[][LENGTH]);

// ======================
// InitializeCards
// Places pairs of numbers in the 2D array and then
// randomly shuffles them.
// ======================
void InitializeCards(int cards[][LENGTH])
{
int x1,y1,x2,y2;
int i;
int temp;

// Place pairs in known locations


cards[0][0]=1; cards[0][1]=1;
cards[0][2]=2; cards[0][3]=2;
cards[1][0]=3; cards[1][1]=3;
cards[1][2]=4; cards[1][3]=4;

85
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

cards[2][0]=5; cards[2][1]=5;
cards[2][2]=6; cards[2][3]=6;
cards[3][0]=7; cards[3][1]=7;
cards[3][2]=8; cards[3][3]=8;

// Randomly swap pairs 10000 times to shuffle


for (i=0; i<NUM_TRIALS; i++)
{
x1 = rand() % LENGTH;
y1 = rand() % LENGTH;
x2 = rand() % LENGTH;
y2 = rand() % LENGTH;
temp = cards[x1][y1];
cards[x1][y1]=cards[x2][y2];
cards[x2][y2] = temp;
}
}

// ======================
// ShowCards
// Generates a display on the screen. If faceup=false,
// an * is output, otherwise the card in that slot is output.
// ======================
void ShowCards(int cards[][LENGTH], bool faceup[][LENGTH])
{
int x,y;

cout << " 1 2 3 4" << endl;


cout << " =========" << endl;
for (y=0; y < LENGTH; y++)
{
cout << y+1 << " | ";
for (x=0; x< LENGTH; x++)
{
if (faceup[x][y])
{
cout << cards[x][y] << " ";
}
else
{
cout << "* ";
}
}
cout << "|" << endl;
}
cout << " =========" << endl;
}

// ======================
// main function
// ======================

86
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

int main()
{
// Variable declarations
int cards[LENGTH][LENGTH];
bool faceup[LENGTH][LENGTH];
int x,y, temp;
int x1,y1,x2,y2;
int pairsleft = 8;

cout << "Find all the matching pairs on the board." << endl;

// Initialize faceup boolean array


for (y=0; y<LENGTH; y++)
for (x=0; x<LENGTH;x++)
{
faceup[x][y]=false;
}

// Initialize and shuffle cards on the board


InitializeCards(cards);

// Main loop, show the board


while (pairsleft > 0)
{
ShowCards(cards,faceup);
cout << "Enter an x and y position of the first card to flip." <<
endl;
cin >> x1;
cin >> y1;
cout << "Enter an x and y position of the second card to flip." <<
endl;
cin >> x2;
cin >> y2;
// Subtract one from the input, since our arrays start at 0
// but the board displays start at 1
x1--; y1--;
x2--; y2--;

// Check if we found a match


if (cards[x1][y1]==cards[x2][y2])
{
cout << "Match found!" << endl;
faceup[x1][y1]=true;
faceup[x2][y2]=true;
pairsleft--;
}
else
{
// No match, but temporarily show the cards
faceup[x1][y1]=true;
faceup[x2][y2]=true;
ShowCards(cards,faceup);
cout << "Enter any number to continue." << endl;

87
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

cin >> temp;


// Hide the revealed board by scrolling it off
faceup[x1][y1]=false;
faceup[x2][y2]=false;
for (temp=0; temp<30; temp++)
{
cout << endl;
}
}
}
cout << "You found all the matching pairs! Game over." << endl;
ShowCards(cards,faceup);
}

2. Outline of Topics in the Chapter

7.1 Introduction to Arrays


Declaring and Referencing Arrays
Arrays in Memory
Initializing Arrays

7.2 Arrays in Functions


Indexed Variables as Function Arguments
Entire Arrays as Function Arguments
The const Parameter Modifier
Functions that Return an Array

7.3 Programming with Arrays


Partially Filled Arrays

7.4 Arrays and Classes


Arrays of Classes
Arrays of Class Members

7.5 Multidimensional Arrays


Multidimensional Array Basics

88
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

Multidimensional Array Parameters

3. General Remarks on the Chapter

It should be noted at this point that I have assumed g++ with Linux, specifically g++ 3.0.x
under Debian Linux as the programming environment. I have tested much of this under the
MS VC++ 6 and Borland 5.5 command compilers. Borland C++, VC++ 6.0 (and most
other compilers) give very much the same behavior as g++ and Linux for the programs
presented here.

Students that come to C++ from one of the more protective languages such as Pascal or
Java will find the low level, non-protective C/C++ array notion to be a concern at the least.
I list here are some of these concerns, and present a bit of the reasoning behind them. I
usually discuss these ideas in my class room presentation of the array concept.

7.1 Introduction to Arrays

C++ has adopted the notion of array from the C language without change. In C++ the
notion of array is quite 'low level'. By this, I mean that in C++, arrays, along with pointers
and the notion of conversion of an array name to a pointer, provide a mechanism that
closely models memory and address concepts in traditional computer hardware. The
concept is both simple and general, and has the potential to be quite efficient -- and, in
careless hands, quite dangerous.

Unlike Java and Pascal, the C++ array mechanism provides no protection against abuse
and error. Ellis and Stroustrup (ARM page 137) point out the low-level nature of C++
arrays result in the following major limitations:

1) An array is of fixed size, with the size specified at compile time.


2) An array is one dimensional; talking about multidimensional arrays in C/C++ [only
refers] to arrays of arrays.

89
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

3) An array is not self-describing. Given a pointer to an array, there is no information


to determine the size of an array.

This last property means that passing an array as a function parameter is inherently
dangerous.

If any of the properties mentioned are a problem in programming, the programmer always
has the option to create an ADT by embedding the array in a class that overloads the
indexing [] operator to provide array bounds checking, variable array size, or otherwise
addresses the above properties that are seen as shortcomings in a given setting.

Declaring and Referencing Arrays

Be careful with the terminology. The text points out that there is much terminology
associated with the array concept, and it varies greatly from author to author. The problems
will usually be with students who have some programming experience, but not enough to
allow them to be comfortable with a change in the words used to describe these ideas.

Students who have studied languages that provide both start and ending array indices,
where both ends are usable have a particular problem with the asymmetric array bounds.
With Pascal, for example, unless a problem calls for the array indices to start at some value
other than 1, Pascal arrays traditionally start at 1 and run to the given size. On the other
hand, C/C++ arrays run from 0 to one less than the array size. The starting index is not
mentioned in the declaration, and the number that is mentioned, the size of the array, is not
a usable index value.

My students tend to confuse the use of x[4] in a declaration, as in int x[4]; with
the use of x[3] in an access to the array. I think the problem should be mentioned to
your classes. This chapter of the text discusses this idea.

As mentioned in the opening paragraph, C/C++ arrays do not provide array bounds
checking, so if array bounds are exceeded, strange results may occur. If a Windows, DOS,

90
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

or Mac platform is used, the potential for hanging the machine by overwriting a return
address for a function exists.

If you are using an operating system that runs with protected memory, such as Sun, a Unix
flavor, Linux, BSD, Windows NT, 2000, and XP or one of the (few) other fully protected
mode operating systems, an array index very far out-of-bounds can cause a run time error
(reported by Linux and a few other systems as a segmentation violation). Sun, HP, VAX,
and many other workstations run fully protected mode operating systems. Note that
Microsoft Windows 9x and Me do not protect against much of anything. Upgrade now if
you are afflicted with 9x or Me. Windows 2000 and XP are significantly better, but not
perfect in this regard.

You will hear students say "With a bad write to memory, you can cause the hard disk to be
reformatted." This isn't going to happen, especially in systems with memory protection..
My students appreciated being told this comforting bit of information. Most PCs today
have IDE controllers. These controllers do not have the capability to low-level format a
hard disk without a utility from the manufacturer. The few SCSI controllers that exist in
PCs may have disk utilities in ROM. An inadvertent write to certain addresses could
possibly start a disk utilities menu on a machine with an operating system that does not
protect memory. This is in fact unlikely, and if it did happen, it is unlikely to cause
unintended mischief.

Finally, an understanding of what happens when you index into an array based on the
memory model presented in the text is of great importance.

7.2 Arrays in Functions

Indexed Variables as Function Arguments.

91
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

An indexed array variable is just a variable having the array's base type. Hence there is
nothing special about sending it to any function that accepts such argument, except that it
looks unfamiliar.

For my students, I emphasize that the whole array is not being sent to the function, just the
element of the array indicated by the index.

PITFALL: Declaring an Array with a Non-Constant Size.

If you wanted to have an array whose size you could set at runtime, you might write the
following code. Unfortunately, this is illegal, though some compilers (including g++)
allow it.

//File: array_bounds.cpp
//To test behavior when array bounds are set, used, and
//violated
#include <iostream>
int main()
{
using namespace std;
int x[10] = {0, 1,2,3,4,5,6,7,8,9};//Ok, size is an
//int constant
int n;
cin >> n;
int y[n]; //Line 12 - Here we have (illegally) declared
//an array of non-constant size
for( int i = 0; i < n; i++)
cout << (y[i] = x[i]) << " " ;
cout<< endl;
return 0;
}

Error messages from the compiler:

92
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

g++ --pedantic array_bounds.cpp


array_bounds.cpp: In function `int main()':
array_bounds.cpp:12: warning: ANSI C++ forbids variable-size
array `y'

Borland C++ 5.5 gives the message “a constant expression is required”


and aborts compilation.

The C++ Standard says that the index expression must be a constant expression. The
Standard says further that a constant expression can involve only literals (such as 937,
true, or 1.23), enumerators (enum identifiers) and const values of integral types
initialized with constant expressions, sizeof expressions. We violate the rule that we must
have const integral values initialized by const expressions.

The bottom line is that array size must be known at compile time. The alternative is to
dynamically allocate space on the heap. That is treated later in the text.

Entire Arrays as Function Arguments

When passing arrays, the array name is converted to a pointer to the first array element,
hence all that the function receives is the address of the first array element. All the function
can know is the type as specified in the function declaration and the starting address of the
array but not the array size. This is sometimes referred to as “array type deterioration”.

The consequence is that passing an array parameter is not pass-by-value, since changing
the array element in the function changes the argument array element. In spite of the fact
that changing the parameter changes the caller’s argument, this is not precisely pass-by-
reference either, because the called function doesn't know the size of the array. We call this
parameter passing mechanism "passing an array parameter."

Precisely, array parameters pass the address of the first element of the array, by value.
Having the address enables the called function to change the argument by indexing the
formal parameter and making an assignment.

93
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

There are only two places in C++ where the empty array index operator may be used: one,
where an array is declared with initializers, and in an array parameter for a function:1

int x[] = { 1, 2, 3, 4, 5}; //array has 5 int elements.


void f( int formal[], int size );

The const Parameter Modifier

A reminder: A use of the const keyword is both a promise by the programmer to the
compiler and a request that the compiler hold the programmer to the promise. The
promise is that the programmer will not write code that can change variables affected by
the const.

The case of a class member function that is declared with the const keyword is still a
promise, but is slightly different:

int Class_name::member_function( arg_list ) const;

Here the promise is that the programmer will not to write code in this member function
that could change the calling object.

The following member declaration promises not to write code in the definition of this
function that will change the value of the parameter x in the function, which would
consequently change the caller’s argument.

int Class_name::func ( const int & x );

It is possible to return a reference from a function. This allows the function to be used as
an l-value, i.e., the function call can be assigned. If the function is declared to return a
const reference, this use of const promises not to use the function call as an l-value.

1
There is one other place: the delete operator applied to an array allocated on the free-
store uses empty [] indexing punctuators, but the student knows nothing of this until the
pointers chapter.

94
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

We will treat this when we deal with operator overloading, and only mention it here for
completeness.

Functions that Return an Array

Plainly put, a function cannot return an array, not really, any more than a function can
receive an array as a parameter. The parallel is exact. If we build an array inside a function
then return the array as a function value, the only thing that is returned is a pointer to a
base type object that points to the first array element. We will deal with pointers in Chapter
9.

It is worthwhile to mention to the instructor at this point that there is great danger in
returning an array from a function. There is the temptation to declare a local array in a
function, then to return a pointer to the array as the value of a function. When the function
returns, all local variables, in particular, local arrays go away. The consequence is that
memory is being referred to that is no longer allocated, indeed, may be allocated to some
other use. The problem is that if it works, then it can work for some time, only changing
when some other change is made in the code. Then subtle changes in the operation of the
program can drive someone crazy.

7.3 Programming with Arrays

The programming examples and the Case Study from the text provide more than just
illustrations of the uses of arrays as data types and as function parameters. These case
studies give examples of program design, testing, and several important algorithms of
important categories.

Case Studies and Programming Examples

Production Graph Case Study

This case illustrates top-down design, array use and array parameters, and testing. The
production array introduces the notion that it isn't necessary to use the actual numbers in a

95
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

problem as indices into arrays. Rather, this problem uses shifted plant numbers for indices.
The testing of the components of this program is an interesting study. Both top-down and
bottom-up testing are illustrated here. The all important boundary cases are tested, as well
as in-the-middle values. Boundary testing helps find off-by-one errors.

Programming Example: Partially Filled Arrays; Searching and Sorting.

This is an important section. The examples here introduce the notions of partially filled
arrays, searching and sorting. Frequently, we will know something about the largest
number of data we will need to manage, but much of the time the number of data will be
less than the maximum. We do not want to have to write a version of our analysis program
for every size of data. The tool we need is the partially filled array.

Searching and sorting are very important topics in Computer Science. Donald Knuth said
that much of computer science was encompassed by searching and sorting.

The algorithms presented are insertion sort and linear search. In my opinion, the simplest
reasonable algorithms ought to be the introductory examples, and this is the text’s method.
In fact, the programmer should always design for correctness and clarity first, and worry
about efficiency after it is determined by testing that the simplest solution is deficient in
speed or some other way.

"The fastest algorithm can frequently be replaced with one that is almost as fast and
much easier to understand,"

--Douglas W. Jones, University of Iowa,

Quoted in More Programming Pearls, p61, Jon Bentley, Addison Wesley,


1988.

96
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

7.4 Arrays and Classes

Arrays can have any C++ type for its base type. A class or struct can have any C++ type
for members. There are unlimited combinations of arrays of classes and classes with array
members.

Arrays of Classes

Here the student must do the Self-Test exercises, and the code fragments should be tested
by embedding them in small programs as suggested in the exercises. This stuff isn't
difficult, but it does require substantial exposure over a period of time to internalize the
ideas.

I suggest the instructor strongly encourage students to create many examples for
themselves, making inquiry of the compiler about language details. While the language
Standard is the ultimate authority about what the C++ language should be, and the text
lucidly explains the details, it is the compiler that you are using that is the authority on
what C++ language your compiler accepts. This is important whether the questions
concern syntax or the meaning of a code segment.

Teach your students to ask the compiler what works.

Here is an example of the many small programs asking the compiler about details of the
language that should be written in the learning of this language. I am inquiring about use
of constructor lists for initializing arrays of class objects. You may wish to mention that
many programmers use this style of initialization in constructors.

The text points out that declaration of an array of class objects

Money difference[5];

invokes the default constructor for each of the 5 array elements.

97
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

You can use a list of constructor calls to initialize an array of objects. In fact, if a
parameterized constructor of the appropriate type is present, you may use lists of objects of
any type that the constructors can use to initialize an array of class objects. The constructor
will be automatically called. As we shall see in the example, grouping the values is
sometimes necessary.

//File Z.cpp
//to test initializing arrays of class objects with a
//non-constructor list
#include <iostream.h>

class Z
{
public:
Z();
Z(int x);
Z(int x, int y );
int get_i();
int get_j();
//other public members
private:
int i;
int j;
};

Z::Z():i(0),j(0)
{
cout << "default constructor called" << endl;
}

Z::Z(int x):i(x),j(0)

98
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

{
cout << "one parameter constructor called" << endl;
}

Z(int x, int y):i(x),j(y)


{
cout << "two parameter constructor called" << endl;
}

int get_i()
{
return i;
}

int get_j()
{
return j;
}

int main()
{
int k;
//Here we call the one parameter constructor, the default
constructor,
//and the two parameter constructor.

Z z[] = {Z(17), Z(), Z(1,2)};

for ( k = 0; k < 3; k++)


{
cout << z[k].get_i() << " "
<< z[k].get_j() << " ";

99
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

}
cout << endl;

Here is an alternative. Notice that you MUST have a default constructor for this to compile. Here,
two constructors are called for each element in the array: default constructor is called
implicitly(meaning the compiler generates the call) and the one parameter constructor is called
explicitly.

Z y[3];

for ( k = 0; k < 3; k++)


y[k] = Z(k);

for ( k = 0; k < 3; k++)


cout << y[k].get_i() << " ";
cout << endl;

This causes the automatic calling of the Z(int) constructor for each initializer in the list.

Z x[] = { 0, 1, 2, };

for ( k = 0; k < 3; k++)


cout << x[k].get_i() << " ";
cout << endl;

Here the two parameter constructor is called. The grouping of the initializers is necessary
in order to have the two parameter constructor called.

Z zz[] = { {0,1},{2,3},{4,5}};

for ( k = 0; k < 3; k++)


{
cout << zz[k].get_i() << " ";
cout << zz[k].get_j() << " ";

100
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

cout << endl;


}

To get two parameter constructors called, you must group the initializers:

Z ww[3] = { 0,1,2,3,4,5}; //6 initializers ...

//Z.cpp: warning: excess elements in aggregate initializer

Here we mix things a bit. Two calls to the int parameter constructor, and two calls to the
two parameter constructor.

Z xx[4] = { 0,1,{2,3},{4,5}};

for ( k = 0; k < 4; k++)


{
cout << xx[k].get_i() << " "
<< xx[k].get_j() << " " << endl;
}
cout << endl;
}

Arrays as Class Members

The text points out that arrays are eligible to be members of a class. Initialization of
array data members must be done within a constructor, in much the same way arrays
outside the class are initialized from variable data.

Here is one additional example that uses a slightly different partially filled array with fixed
maximum size:

//File: array-as-class-members.cpp
//to investigate the initialization of array members of a
//class
#include <iostream>

101
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

using namespace std;


const int MAX_SIZE = 5;

class Has_array
{
public:
Has_array()
{
size = 0;
}
Has_array( int arr[], int s )
{
for ( int i = 0; i < s; i++)
x[i] = arr[i];
size = s;
}
friend ostream& operator << ( ostream& outs,
const Has_array & obj )
{
for ( int i = 0; i < obj.size; i++)
{
cout << obj.x[i] << " ";
}
return outs;
}
friend istream& operator >> ( istream& ins, Has_array & obj )
{
int i = 0;
while ( i < MAX_SIZE && ins >> obj.x[i] )
i++;
obj.size = i; //i should be the number of objects
transferred

102
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley
Savitch Instructor’s Resource Guide
Problem Solving w/ C++, 6e Chapter 7

int sizeOfIt()
{
return size;
}

private:
int x[MAX_SIZE];
int size;
};

int main()
{
int a[] = {1,2,3,4};
int size = 4;
Has_array u;
Has_array v( a, siz);
cout << "Enter up to 5 integers, <CR> after each. "
<< "<EOF> to terminate input. " << endl;
cin >> u;
cout << "you entered " << u.sizeOfIt()
<< " integers, which are: "
<< u << endl;

cout << "here is the array built into the program: "
<< endl << "its size is " << v.sizeOfIt() << endl;
cout << v << endl;
}

103
Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

Vous aimerez peut-être aussi