IRM Chapter 6e 07

103
1 Copyright © 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley 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.

Transcript of IRM Chapter 6e 07

Page 1: IRM Chapter 6e 07

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

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.

Page 2: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

//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

Page 3: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

{

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;

Page 4: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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;

}

Page 5: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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;

Page 6: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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);

Page 7: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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;

Page 8: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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 << " |";

Page 9: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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";

Page 10: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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;

Page 11: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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 << '*';

Page 12: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

}

//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)";

Page 13: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 14: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 15: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 16: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

. . . .

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 ***************************************************

Page 17: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 18: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

. . . .

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.

Page 19: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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:

Page 20: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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. //

Page 21: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

#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]; }

Page 22: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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 " ; }

Page 23: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

// 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; } /*

Page 24: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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 ------------

Page 25: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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[]);

Page 26: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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++)

Page 27: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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.

Page 28: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

// 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: "

Page 29: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

<< 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.

Page 30: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 31: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

//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;

Page 32: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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);

Page 33: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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 )

{

Page 34: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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;

Page 35: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 36: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 37: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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.

Page 38: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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>

Page 39: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

#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;

Page 40: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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) )

{

Page 41: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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-- )

Page 42: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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;

Page 43: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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.

Page 44: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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>

Page 45: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

#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);

Page 46: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

//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

Page 47: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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)

{

Page 48: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 49: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 50: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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.

Page 51: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

//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

Page 52: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

//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,

Page 53: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

// 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,

Page 54: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

// 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

Page 55: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

//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;

Page 56: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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";

Page 57: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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[] )

Page 58: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

{

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;

Page 59: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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 )

Page 60: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

{

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);

}

}

Page 61: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

//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);

Page 62: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

}

}

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[])

{

Page 63: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

//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

Page 64: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

&&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.

Page 65: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

//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

Page 66: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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>

Page 67: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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)

Page 68: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

{

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;

Page 69: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 70: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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:

Page 71: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 72: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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.

Page 73: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 74: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 75: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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++)

Page 76: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

{ 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

Page 77: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

// . // . // 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;

Page 78: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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"

Page 79: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

<< "****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.

Page 80: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 81: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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 ";

Page 82: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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[]);

Page 83: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

// ====================== // 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);

Page 84: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

} // 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++;

Page 85: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

} 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;

Page 86: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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 // ======================

Page 87: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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;

Page 88: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 89: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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.

Page 90: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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,

Page 91: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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.

Page 92: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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:

Page 93: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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.

Page 94: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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.

Page 95: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 96: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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.

Page 97: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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.

Page 98: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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)

Page 99: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

{

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() << " ";

Page 100: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

}

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() << " ";

Page 101: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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>

Page 102: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

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

Page 103: IRM Chapter 6e 07

Savitch Instructor’s Resource Guide Problem Solving w/ C++, 6e Chapter 7

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

}

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;

}