© 2005 Pearson Education, Inc., Upper Saddle River, NJ. All rights reserved. This material is protected under all copyright laws as they currently exist. No portion of this material may be reproduced, in any form or by any means, without permission in writing from the publisher. For the exclusive use of adopters of the book C++ How to Program, 5th Edition, by Deitel and Deitel. ISBN 0-13-185757-6.
9 Classes: A Deeper Lo Look, Part 1 My object all sublime I shall achieve in time. —W. S. Gilbert
OBJECTIVES
Is it a world to hide virtues in?
In this chapter you will learn:
—William Shakespeare
■
■
■
■
■
■
■
How to use a preprocessor wrapper to prevent multiple definition errors caused by including more than one copy of a header file in a source-code file. To understand class scope and accessing class members via the name of an object, a reference to an object or a pointer to an object. To define constructors with default arguments.
Don’t be “consistent,” Don’t “consist ent,” but be simply true. —Oliver Wendell Holmes, Jr.
This above all: to thine own self be true. —William Shakespeare
How destructors are used to perform per form “termination housekeeping” on an object before it is destroyed. When constructors and destructors are called. The logic errors that may occur when a public member function of a class returns a reference to private data. To assign the data members of one object to those of another object by default memberwise assignment.
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
481
Self-Review Exercises 9.1
Fill in the blanks in each of the following: fo llowing: a) Class members members are accessed accessed via the operator operator in conjunction conjunction with the name of an object (or reference to an object) of the class or via the operator in conjunction with a pointer to an object of the class. ANS : dot (.), arrow (->). b) Class members members specified specified as are accessible accessible only to member member functions functions of the class and friends of the class. ANS : private. c) Class members members specified specified as are accessible accessible anywhere anywhere an object object of the class is in scope. ANS : public. d) can be used to assign an object of a class to another object of the same class. ANS : Default memberwise assignment (performed by the assignment operator).
9.2
Find the error(s) in each of the following and explain how to correct it (them): a) Assume Assume the the following following prototype prototype is declared declared in class Time: void ~Time( int );
Error: Destructors are not allowed to return values (or even specify a return type) or take arguments. Correction: Remove the return type void and the parameter int from the declaration. b) The followi following ng is a partial partial definit definition ion of class class Time:
ANS :
class Time
{ public: // function prototypes private: int hour = 0; int minute = 0; int second = 0; }; // end class Time
Error: Members cannot be explicitly initialized in the class definition. Correction: Remove the explicit initialization from the class definition and initialize the data members in a constructor. c) Assume Assume the the following following prototype prototype is declared declared in class Employee:
ANS :
int Employee( const char *, const char * ); ANS :
Error: Constructors are not allowed to return values. Correction: Remove the return type int from the declaration.
Solutions 9.3
What is the purpose of the scope resolution operator? ANS : The scope resolution operator is used to specify the class to which a function belongs. It also resolves the ambiguity caused by multiple classes having member functions of the same name. It also associates a member function in a .cpp file with a class definition in a .h file.
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
482
Chap Ch apte terr 9
Clas Cl asse ses: s: A De Deep eper er Lo Look ok,, Part Part 1
(Enhancing Class Time ) Provide ) Provide a constructor that is capable cap able of using the current time from the time() function—declared in the C++ Standard Library header —to initialize an object of the Time class. Note: We provide two solutions. The first one only uses function time. The second ANS : [Note: We one uses several other data member and functions in header.] 9.4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
// Exercis Exercise e 9.4 Soluti Solution: on: Time. Time.h h #ifndef TIME_H #ifndef TIME_H #define TIME_H #define TIME_H class Time class Time { public: public : Time(); // constructor void setTime( void setTime( int int, , int int, , int int ); ); // set hour, minute and second void printUniversal(); void printUniversal(); // print time in universal-time format void printStandard(); void printStandard(); // print time in standard-time format private: private : int hour; int hour; // 0 - 23 (24-hour clock format) int minute; int minute; // 0 - 59 int second; int second; // // 0 - 59 bool isLeapYear( bool isLeapYear( int int ); ); // check if input is a leap year }; // }; // end class Time #endif
// Exercise 9.4 Solution: Time.cpp // Member-function definitions for class Time. #include #include using std::cout; using std::cout; #include #include using std::setfill; using std::setfill; using std::setw; using std::setw; #include #include using std::time; using std::time; #include "Time.h" // include definition of class Time from Time.h Time::Time() { const int CURRENT_YEAR int CURRENT_YEAR = 2004 2004; ; const int START_YEAR int START_YEAR = 1970 1970; ; const int HOURS_IN_A_DAY int HOURS_IN_A_DAY = 24 24; ; const int int MINUTES_IN_AN_HOUR MINUTES_IN_AN_HOUR = 60 60; ; const int SECONDS_IN_A_MINUTE int SECONDS_IN_A_MINUTE = 60 60; ; const int DAYS_IN_A_YEAR int DAYS_IN_A_YEAR = 365 365; ; const int DAYS_IN_A_LEAPYEAR int DAYS_IN_A_LEAPYEAR = 366 366; ; const int TIMEZONE_DIFFERENCE int TIMEZONE_DIFFERENCE = 5; int leapYear int leapYear = 0; int days; int days;
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
// calculate leap year for ( int for ( int y y = START_YEAR; y <= CURRENT_YEAR; y++ ) { if ( if ( isLeapYear( y ) ) leapYear++; } // end for int dayTimeInSeconds = time( 0 ) - HOURS_IN_A_DAY * int dayTimeInSeconds MINUTES_IN_AN_HOUR * SECONDS_IN_A_MINUTE * ( DAYS_IN_A_YEAR * ( CURRENT_YEAR - START_YEAR ) + leapYear ); // calculate current second, minute and hour for ( for ( int int s s = 0; s < SECONDS_IN_A_MINUTE; s++ ) { for ( for ( int int m m = 0; m < MINUTES_IN_AN_HOUR; m++ ) { for ( for ( int int h h = 0; h <= HOURS_IN_A_DAY; h++ ) { if ( if ( isLeapYear( CURRENT_YEAR ) ) days = DAYS_IN_A_LEAPYEAR; else days = DAYS_IN_A_YEAR;
for ( int for ( int d d = 0; d <= days; d++ ) { if ( if ( s + m * SECONDS_IN_A_MINUTE + h * MINUTES_IN_AN_HOUR * SECONDS_IN_A_MINUTE + d * HOURS_IN_A_DAY * MINUTES_IN_AN_HOUR * SECONDS_IN_A_MINUTE == dayTimeInSeconds ) { setTime( h-TIMEZONE_DIFFERENC h-TIMEZONE_DIFFERENCE, E, m, s ); } // end if } // end for } // end for } // end for } // end for } // end Time constructor // set new Time value using universal time; ensure that // the data remains consistent by setting invalid values to zero void Time::setTime( void Time::setTime( int int h, h, int int m, m, int int s s ) { hour = ( h >= 0 && h < 24 ) ? h : 0; // validate hour minute = ( m >= 0 && m < 60 ) ? m : 0; // validate minute second = ( s >= 0 && s < 60 ) ? s : 0; // validate second } // end function setTime // print Time in universal-time format (HH:MM:SS) void Time::printUniversal() { cout << setfill( '0' '0' ) ) << setw( 2 ) << hour << ":" << setw( 2 ) << minute << ":" ":" << << setw( 2 ) << second; } // end function printUniversal // print Time in standard-time format (HH:MM:SS AM or PM)
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
483
484
Chap Ch apte terr 9
Clas Cl asse ses: s: A De Deep eper er Lo Look ok,, Part Part 1
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
void Time::printStandard() void Time::printStandard() { cout << ( ( hour == 0 || hour == 12 12 ) ) ? 12 12 : : hour % 12 12 ) ) << ":" << setfill( '0' '0' ) ) << setw( 2 ) << minute << ":" ":" << << setw( 2 ) << second << ( hour < 12 12 ? ? " AM" : AM" : " PM" ); PM" ); } // end function printStandard
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// Exercise Exercise 9.4 Solutio Solution: n: Ex09_04 Ex09_04.cpp .cpp #include #include using std::cout; using std::cout; using std::endl; using std::endl;
// check if a year is a leap year bool Time::isLeapYear( bool Time::isLeapYear( int int y y ) { if ( if ( ( y % 400 400 == == 0 ) || ( ( y % 4 == 0 ) && ( y % 100 100 != != 0 ) ) ) return true; true; else return false; false; } // end function isLeapYear
#include "Time.h" int main() int main() { Time t; // create Time object // display current time cout << "The universal time is "; "; t.printUniversal(); cout << "\nThe standard time is "; "; t.printStandard(); cout << endl; return 0; } // end main
The universal time is 14:54:06 The standard time is 2:54:06 PM
1 2 3 4 5 6 7 8 9 10
// Exercis Exercise e 9.4 Soluti Solution: on: Time. Time.h h #ifndef TIME_H #ifndef TIME_H #define TIME_H #define TIME_H class Time class Time { public: public : Time(); // constructor void setTime( void setTime( int int, , int int, , int int ); ); // set hour, minute and second void printUniversal(); void printUniversal(); // print time in universal-time format
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
11 12 13 14 15 16 17 18
void printStandard(); // print time in standard-time format private: int hour; // 0 - 23 (24-hour clock format) int minute; // 0 - 59 int second; // 0 - 59 }; // end class Time
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
// Exercise 9.4 Solution: Time.cpp // Member-function definitions for class Time. #include using std::cout;
485
#endif
#include using std::setfill; using std::setw; #include using std::localtime; using std::time; using std::time_t; #include "Time.h" // include definition of class Time from Time.h Time::Time() { const time_t currentTime = time( 0 ); const tm *localTime = localtime( ¤tTime ); setTime( localTime->tm_hour, localTime->tm_min, localTime->tm_sec ); } // end Time constructor // set new Time value using universal time; ensure that // the data remains consistent by setting invalid values to zero void Time::setTime( int h, int m, int s ) { hour = ( h >= 0 && h < 24 ) ? h : 0; // validate hour minute = ( m >= 0 && m < 60 ) ? m : 0; // validate minute second = ( s >= 0 && s < 60 ) ? s : 0; // validate second } // end function setTime // print Time in universal-time format (HH:MM:SS) void Time::printUniversal() { cout << setfill( '0' ) << setw( 2 ) << hour << ":" << setw( 2 ) << minute << ":" << setw( 2 ) << second; } // end function printUniversal // print Time in standard-time format (HH:MM:SS AM or PM) void Time::printStandard() { cout << ( ( hour == 0 || hour == 12 ) ? 12 : hour % 12 ) << ":" << setfill( '0' ) << setw( 2 ) << minute << ":" << setw( 2 ) << second << ( hour < 12 ? " AM" : " PM" );
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Chapter 9
486
46
Classes: A Deeper Look, Part 1
} // end function printStandard
( Complex Class) Create a class called Complex for performing arithmetic with complex numbers. Write a program to test your class. Complex numbers have the form 9.5
realPart + imaginaryPart *
i
where i is –1 Use double variables to represent the private data of the class. Provide a constructor that enables an object of this class to be initialized when it is declared. The constructor should contain default values in case no initializers are provided. Provide public member functions that perform the following tasks: a) Adding two Complex numbers: The real parts are added together and the imaginary parts are added together. b) Subtracting two Complex numbers: The real part of the right operand is subtracted from the real part of the left operand, and the imaginary part of the right operand is subtracted from the imaginary part of the left operand. c) Printing Complex numbers in the form (a, b), where a is the real part and b is the imaginary part. ANS :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
1 2 3 4 5 6 7 8 9
// Exercise 9.5 Solution: Complex.h #ifndef COMPLEX_H #define COMPLEX_H class Complex { public: Complex( double = 0.0, double = 0.0 ); // default constructor Complex add( const Complex & ); // function add Complex subtract( const Complex & ); // function subtract void printComplex(); // print complex number format void setComplexNumber( double, double ); // set complex number private: double realPart; double imaginaryPart; }; // end class Complex #endif
// Exercise 9.5 Solution: Complex.cpp // Member-function definitions for class Complex. #include using std::cout; #include "Complex.h" Complex::Complex( double real, double imaginary ) {
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
setComplexNumber( real, imaginary ); } // end Complex constructor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
// Exercise 9.5 Solution: Ex09_05.cpp #include using std::cout; using std::endl;
487
Complex Complex::add( const Complex &right ) { return Complex( realPart + right.realPart, imaginaryPart + right.imaginaryPart ); } // end function add Complex Complex::subtract( const Complex &right ) { return Complex( realPart - right.realPart, imaginaryPart - right.imaginaryPart ); } // end function subtract void Complex::printComplex() { cout << '(' << realPart << ", " << imaginaryPart << ')'; } // end function printComplex void Complex::setComplexNumber( double rp, double ip ) { realPart = rp; imaginaryPart = ip; } // end function setComplexNumber
#include "Complex.h" int main() { Complex a( 1, 7 ), b( 9, 2 ), c; // create three Complex objects
a.printComplex(); // output object a cout << " + "; b.printComplex(); // output object b cout << " = "; c = a.add( b ); // invoke add function and assign to object c c.printComplex(); // output object c cout << '\n'; a.setComplexNumber( 10, 1 ); // reset realPart and b.setComplexNumber( 11, 5 ); // and imaginaryPart a.printComplex(); // output object a cout << " - "; b.printComplex(); // output object b cout << " = "; c = a.subtract( b ); // invoke add function and assign to object c c.printComplex(); // output object c cout << endl;
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
488
29 30
Chapter 9
Classes: A Deeper Look, Part 1
return 0; } // end main
(1, 7) + (9, 2) = (10, 9) (10, 1) - (11, 5) = (-1, -4)
( Rational Class) Create a class called Rational for performing arithmetic with fractions. Write a program to test your class. Use integer variables to represent the private data of the class—the numerator and the denominator. Provide a constructor that enables an object of this class to be initialized when it is declared. The constructor should contain default values in case no initializers are provided and should store the fraction in reduced form. For example, the fraction 2 --4 would be stored in the object as 1 in the numerator and 2 in the denominator. Provide public member functions that perform each of the following tasks: a) Adding two Rational numbers. The result should be stored in reduced form. b) Subtracting two Rational numbers. The result should be stored in reduced form. c) Multiplying two Rational numbers. The result should be stored in reduced form. d) Dividing two Rational numbers. The result should be stored in reduced form. e) Printing Rational numbers in the form a/b, where a is the numerator and b is the denominator. f) Printing Rational numbers in floating-point format. 9.6
ANS :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
1 2 3
// Exercise 9.6 Solution: Rational.h #ifndef RATIONAL_H #define RATIONAL_H class Rational { public: Rational( int = 0, int = 1 ); // default constructor Rational addition( const Rational & ); // function addition Rational subtraction( const Rational & ); // function subtraction Rational multiplication( const Rational & ); // function multi. Rational division( const Rational & ); // function division void printRational (); // print rational format void printRationalAsDouble(); // print rational as double format private: int numerator; // integer numerator int denominator; // integer denominator void reduction(); // utility function }; // end class Rational #endif
// Exercise 9.6 Solution: Rational.cpp // Member-function definitions for class Rational. #include
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
using std::cout; #include "Rational.h" // include definition of class Rational Rational::Rational( int n, int d ) { numerator = n; // sets numerator denominator = d; // sets denominator reduction(); // store the fraction in reduced form } // end Rational constructor Rational Rational::addition( const Rational &a ) { Rational t; // creates Rational object t.numerator = a.numerator * denominator; t.numerator += a.denominator * numerator; t.denominator = a.denominator * denominator; t.reduction(); // store the fraction in reduced form return t; } // end function addition Rational Rational::subtraction( const Rational &s ) { Rational t; // creates Rational object t.numerator = s.denominator * numerator; t.numerator -= denominator * s.numerator; t.denominator = s.denominator * denominator; t.reduction(); // store the fraction in reduced form return t; } // end function subtraction Rational Rational::multiplication( const Rational &m ) { Rational t; // creates Rational object t.numerator = m.numerator * numerator; t.denominator = m.denominator * denominator; t.reduction(); // store the fraction in reduced form return t; } // end function multiplication Rational Rational::division( const Rational &v ) { Rational t; // creates Rational object t.numerator = v.denominator * numerator; t.denominator = denominator * v.numerator; t.reduction(); // store the fraction in reduced form return t; } // end function division void Rational::printRational () {
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
489
490
Chapter 9
Classes: A Deeper Look, Part 1
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
if ( denominator == 0 ) // validates denominator cout << "\nDIVIDE BY ZERO ERROR!!!" << '\n'; else if ( numerator == 0 ) // validates numerator cout << 0; else cout << numerator << '/' << denominator; } // end function printRational
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// Exercise 9.6 Solution: Ex09_06.cpp #include using std::cout; using std::endl;
void Rational::printRationalAsDouble() { cout << static_cast< double >( numerator ) / denominator; } // end function printRationalAsDouble void Rational::reduction() { int largest; largest = numerator > denominator ? numerator : denominator; int gcd = 0; // greatest common divisor for ( int loop = 2; loop <= largest; loop++ ) if ( numerator % loop == 0 && denominator % loop == 0 ) gcd = loop; if (gcd != 0) { numerator /= gcd; denominator /= gcd; } // end if } // end function reduction
#include "Rational.h" // include definition of class Rational int main() { Rational c( 2, 6 ), d( 7, 8 ), x; // creates three rational objects
c.printRational(); // prints rational object c cout << " + "; d.printRational(); // prints rational object d x = c.addition( d ); // adds object c and d; sets the value to x cout << " = "; x.printRational(); // prints rational object x cout << '\n'; x.printRational(); // prints rational object x cout << " = "; x.printRationalAsDouble(); // prints rational object x as double
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
cout << "\n\n";
c.printRational(); // prints rational object c cout << " - "; d.printRational(); // prints rational object d x = c.subtraction( d ); // subtracts object c and d cout << " = "; x.printRational(); // prints rational object x cout << '\n'; x.printRational(); // prints rational object x cout << " = "; x.printRationalAsDouble(); // prints rational object x as double cout << "\n\n"; c.printRational(); // prints rational object c cout << " x "; d.printRational(); // prints rational object d x = c.multiplication( d ); // multiplies object c and d cout << " = "; x.printRational(); // prints rational object x cout << '\n'; x.printRational(); // prints rational object x cout << " = "; x.printRationalAsDouble(); // prints rational object x as double cout << "\n\n"; c.printRational(); // prints rational object c cout << " / "; d.printRational(); // prints rational object d x = c.division( d ); // divides object c and d
cout << " = "; x.printRational(); // prints rational object x cout << '\n'; x.printRational(); // prints rational object x cout << " = "; x.printRationalAsDouble(); // prints rational object x as double cout << endl; return 0; } // end main
1/3 + 7/8 = 29/24 29/24 = 1.20833 1/3 - 7/8 = -13/24 -13/24 = -0.541667 1/3 x 7/8 = 7/24 7/24 = 0.291667 1/3 / 7/8 = 8/21 8/21 = 0.380952
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
491
492
Chapter 9
Classes: A Deeper Look, Part 1
(Enhancing Class Time ) Modify the Time class of Figs. 9.8–9.9 to include a tick member function that increments the time stored in a Time object by one second. The Time object should always remain in a consistent state. Write a program that tests the tick member function in a loop that prints the time in standard format during each iteration of the loop to illustrate that the tick member function works correctly. Be sure to test the following cases: a) Incrementing into the next minute. b) Incrementing into the next hour. c) Incrementing into the next day (i.e., 11:59:59 PM to 12:00:00 AM). 9.7
ANS :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
// Exercise 9.7 Solution: Time.h #ifndef TIME_H #define TIME_H
1 2 3 4 5 6 7 8 9 10
// Exercise 9.7: Time.cpp // Member-function definitions for class Time. #include using std::cout;
class Time { public: public: Time( int = 0, int = 0, int = 0 ); // default constructor // set functions void setTime( int, int, int ); // set hour, minute, second void setHour( int ); // set hour (after validation) void setMinute( int ); // set minute (after validation) void setSecond( int ); // set second (after validation) // get functions int getHour(); // return hour int getMinute(); // return minute int getSecond(); // return second void tick(); // increment one second void printUniversal(); // output time in universal-time format void printStandard(); // output time in standard-time format private: int hour; // 0 - 23 (24-hour clock format) int minute; // 0 - 59 int second; // 0 - 59 }; // end class Time #endif
#include using std::setfill; using std::setw; #include "Time.h" // include definition of class Time from Time.h
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
// Time constructor initializes each data member to zero; // ensures that Time objects start in a consistent state Time::Time( int hr, int min, int sec ) { setTime( hr, min, sec ); // validate and set time } // end Time constructor // set new Time value using universal time; ensure that // the data remains consistent by setting invalid values to zero void Time::setTime( int h, int m, int s ) { setHour( h ); // set private field hour setMinute( m ); // set private field minute setSecond( s ); // set private field second } // end function setTime // set hour value void Time::setHour( int h ) { hour = ( h >= 0 && h < 24 ) ? h : 0; // validate hour } // end function setHour // set minute value void Time::setMinute( int m ) { minute = ( m >= 0 && m < 60 ) ? m : 0; // validate minute } // end function setMinute // set second value void Time::setSecond( int s ) { second = ( s >= 0 && s < 60 ) ? s : 0; // validate second } // end function setSecond // return hour value int Time::getHour() { return hour; } // end function getHour // return minute value int Time::getMinute() { return minute; } // end function getMinute // return second value int Time::getSecond() { return second; } // end function getSecond // increment one second void Time::tick()
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
493
494
Chapter 9
Classes: A Deeper Look, Part 1
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
{
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
// Exercise 9.7: Ex09_07.cpp #include using std::cout; using std::endl;
setSecond( getSecond() + 1 ); // increment second by 1 if ( getSecond() == 0 ) { setMinute( getMinute() + 1 ); // increment minute by 1 if ( getMinute() == 0 ) setHour( getHour() + 1 ); // increment hour by 1 } // end if } // end function tick // print Time in universal-time format (HH:MM:SS) void Time::printUniversal() { cout << setfill( '0' ) << setw( 2 ) << getHour() << ":" << setw( 2 ) << getMinute() << ":" << setw( 2 ) << getSecond(); } // end function printUniversal // print Time in standard-time format (HH:MM:SS AM or PM) void Time::printStandard() { cout << ( ( getHour() == 0 || getHour() == 12 ) ? 12 : getHour() % 12 ) << ":" << setfill( '0' ) << setw( 2 ) << getMinute() << ":" << setw( 2 ) << getSecond() << ( hour < 12 ? " AM" : " PM" ); } // end function printStandard
#include "Time.h" // include definition of class Time const int MAX_TICKS = 30; int main() { Time t; // instantiate object t of class Time
t.setTime( 23, 59, 57 ); // set time
// output Time object t's values for ( int ticks = 1; ticks < MAX_TICKS; ++ticks ) { t.printStandard(); // invokes function printStandard cout << endl; t.tick(); // invokes function tick } // end for
return 0; } // end main
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
11:59:57 11:59:58 11:59:59 12:00:00 12:00:01 . . .
495
PM PM PM AM AM
(Enhancing Class Date ) Modify the Date class of Fig. 9.17 to perform error checking on the initializer values for data members month, day and year. Also, provide a member function nextDay to increment the day by one. The Date object should always remain in a consistent state. Write a program that tests function nextDay in a loop that prints the date during each iteration to illustrate that nextDay works correctly. Be sure to test the following cases: a) Incrementing into the next month. b) Incrementing into the next year. 9.8
ANS :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
1 2 3 4 5 6
// Exercise 9.8 Solution: Date.h #ifndef DATE_H #define DATE_H class Date { public: Date( int = 1, int = 1, int = 1900 ); // default constructor void print(); // print function void setDate( int, int, int ); // set month, day, year void setMonth( int ); // set month void setDay( int ); // set day void setYear( int ); // set year int getMonth(); // get month int getDay(); // get day int getYear(); // get year void nextDay(); // next day private: int month; // 1-12 int day; // 1-31 (except February(leap year), April, June, Sept, Nov) int year; // 1900+ bool leapYear(); // leap year int monthDays(); // days in month }; // end class Date #endif
// Exercise 9.8 Solution: Date.cpp // Member-function definitions for class Date. #include using std::cout; #include "Date.h" // include definition of class Date
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
496
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
Chapter 9
Classes: A Deeper Look, Part 1
Date::Date( int m, int d, int y ) { setDate( m, d, y ); // sets date } // end Date constructor void Date::setDate( int mo, int dy, int yr ) { setMonth( mo ); // invokes function setMonth setDay( dy ); // invokes function setDay setYear( yr ); // invokes function setYear } // end function setDate void Date::setDay( int d ) { if ( month == 2 && leapYear() ) day = ( d <= 29 && d >= 1 ) ? d : 1; else day = ( d <= monthDays() && d >= 1 ) ? d : 1; } // end function setDay void Date::setMonth( int m ) { month = m <= 12 && m >= 1 ? m : 1; // sets month } // end function setMonth void Date::setYear( int y ) { year = y >= 1900 ? y : 1900; // sets year } // end function setYear int Date::getDay() { return day; } // end function getDay int Date::getMonth() { return month; } // end function getMonth int Date::getYear() { return year; } // end function getYear void Date::print() { cout << month << '-' << day << '-' << year << '\n'; // outputs date } // end function print void Date::nextDay() { setDay( day + 1 ); // increments day by 1
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
if ( day == 1 ) { setMonth( month + 1 ); // increments month by 1 if ( month == 1 ) setYear( year + 1 ); // increments year by 1 } // end if statement } // end function nextDay bool Date::leapYear() { if ( year % 400 == 0 || ( year % 4 == 0 && year % 100 != 0 ) ) return true; // is a leap year else return false; // is not a leap year } // end function leapYear int Date::monthDays() { const int days[ 12 ] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; return month == 2 && leapYear() ? 29 : days[ month - 1 ]; } // end function monthDays
// Exercise 9.8 Solution: Ex09_08.cpp #include using std::cout; using std::endl; #include "Date.h" // include definitions of class Date int main() { const int MAXDAYS = 16; Date d( 12, 24, 2004 ); // instantiate object d of class Date
// output Date object d's value for ( int loop = 1; loop <= MAXDAYS; ++loop ) { d.print(); // invokes function print d.nextDay(); // invokes function next day } // end for
cout << endl; return 0; } // end main
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
497
498
Chapter 9
Classes: A Deeper Look, Part 1
12-24-2004 12-25-2004 12-26-2004 12-27-2004 12-28-2004 12-29-2004 12-30-2004 12-31-2004 1-1-2005 1-2-2005 1-3-2005 1-4-2005 1-5-2005 1-6-2005 1-7-2005 1-8-2005
(Combining Class Time and Class Date ) Combine the modified Time class of Exercise 9.7 and the modified Date class of Exercise 9.8 into one class called DateAndTime. (In Chapter 12, we will discuss inheritance, which will enable us to accomplish this task quickly without modifying the existing class definitions.) Modify the tick function to call the nextDay function if the time increments into the next day. Modify functions printStandard and printUniversal to output the date and time. Write a program to test the new class DateAndTime. Specifically, test incrementing the time into the next day. 9.9
ANS :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
// Exercise 9.9 Solution: DateAndTime.h #ifndef DATEANDTIME_H #define DATEANDTIME_H class DateAndTime { public: DateAndTime( int = 1, int = 1, int = 1900, int = 0, int = 0, int = 0 ); // default constructor void setDate( int, int, int ); // set month, day, year void setMonth( int ); // set month void setDay( int ); // set day void setYear( int ); // set year void nextDay(); // next day void setTime( int, int, int ); // set hour, minute, second void setHour( int ); // set hour void setMinute( int ); // set minute void setSecond( int ); // set second void tick(); // tick function int getMonth(); // get month int getDay(); // get day int getYear(); // get year int getHour(); // get hour int getMinute(); // get minute int getSecond(); // get second void printStandard(); // print standard time
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
499
27 28 29 30 31 32 33 34 35 36 37 38 39
void printUniversal(); // print universal time private: int month; // 1-12 int day; // 1-31 (except February(leap year), April, June, Sept, Nov) int year; // 1900+ int hour; // 0-23 (24 hour clock format) int minute; // 0-59 int second; // 0-59 bool leapYear(); // leap year int monthDays(); // days in month }; // end class DateAndTime
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
// Exercise 9.9 Solution: DateAndTime.cpp // Member function definitions for class DateAndTime. #include using std::cout; using std::endl;
#endif
#include "DateAndTime.h" // include definition of class DateAndTime DateAndTime::DateAndTime( int m, int d, int y, int hr, int min, int sec ) { setDate( m, d, y ); // sets date setTime( hr, min, sec ); // sets time } // end DateAndTime constructor void DateAndTime::setDate( int mo, int dy, int yr ) { setMonth( mo ); // invokes function setMonth setDay( dy ); // invokes function setday setYear( yr ); // invokes function setYear } // end function setDate void DateAndTime::setDay( int d ) { if ( month == 2 && leapYear() ) day = ( d <= 29 && d >= 1 ) ? d : 1; else day = ( d <= monthDays() && d >= 1 ) ? d : 1; } // end function setDay void DateAndTime::setMonth( int m ) { month = m <= 12 && m >= 1 ? m : 1; // sets month } // end function setMonth void DateAndTime::setYear( int y ) { year = y >= 1900 ? y : 1900; // sets year } // end function setYear
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
500
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
Chapter 9
Classes: A Deeper Look, Part 1
void DateAndTime::nextDay() { setDay( day + 1 ); // increments day by 1 if ( day == 1 ) { setMonth( month + 1 ); // increments month by 1 if ( month == 1 ) setYear( year + 1 ); // increments year by 1 } // end if statement } //end function nextDay void DateAndTime::setTime( int hr, int min, int sec ) { setHour( hr ); // invokes function setHour setMinute( min ); // invokes function setMinute setSecond( sec ); // invokes function setSecond } // end function setTime void DateAndTime::setHour( int h ) { hour = ( h >= 0 && h < 24 ) ? h : 0; // sets hour } // end function setHour void DateAndTime::setMinute( int m ) { minute = ( m >= 0 && m < 60 ) ? m : 0; // sets minute } // end function setMinute void DateAndTime::setSecond( int s ) { second = ( s >= 0 && s < 60 ) ? s : 0; // sets second } // end function setSecond void DateAndTime::tick() { setSecond( second + 1 ); // increments second by 1 if ( second == 0 ) { setMinute( minute + 1 ); // increments minute by 1 if ( minute == 0 ) { setHour( hour + 1 ); // increments hour by 1 if ( hour == 0 ) nextDay(); // increments day by 1 } // end if } // end if } // end function tick int DateAndTime::getDay() {
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
return day; } // end function getDay int DateAndTime::getMonth() { return month; } // end function getMonth int DateAndTime::getYear() { return year; } // end function getYear int DateAndTime::getHour() { return hour; } // end function getHour int DateAndTime::getMinute() { return minute; } // end function getMinute int DateAndTime::getSecond() { return second; } // end function getSecond void DateAndTime::printStandard() { cout << ( ( hour % 12 == 0 ) ? 12 : hour % 12 ) << ':' << ( minute < 10 ? "0" : "" ) << minute << ':' << ( second < 10 ? "0" : "" ) << second << ( hour < 12 ? " AM " : " PM " ) << month << '-' << day << '-' << year << endl; } // end function printStandard void DateAndTime::printUniversal() { cout << ( hour < 10 ? "0" : "" ) << << ( minute < 10 ? "0" : "" ) << << ( second < 10 ? "0" : "" ) << << month << '-' << day << '-' << } // end function printUniversal
hour << ':' minute << ':' second << " year << endl;
"
bool DateAndTime::leapYear() { if ( year % 400 == 0 || ( year % 4 == 0 && year % 100 != 0 ) ) return true; // is a leap year else return false; // is not a leap year } // end function leapYear int DateAndTime::monthDays() {
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
501
502
151 152 153 154 155
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
Chapter 9
Classes: A Deeper Look, Part 1
const int days[ 12 ] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; return ( month == 2 && leapYear() ) ? 29 : days[ ( month - 1 ) ]; } // end function monthDays
// Exercise 9.9 Solution: Ex09_09.cpp #include using std::cout; using std::endl; #include "DateAndTime.h" // include definitions of class DateAndTime int main() { const int MAXTICKS = 30; DateAndTime d( 12, 31, 2004, 23, 59, 57 ); // instantiates object d // of class DateAndTime
for ( int ticks = 1; ticks <= MAXTICKS; ticks++ ) { cout << "Universal time: "; d.printUniversal(); // invokes function printUniversal cout << "Standard time: "; d.printStandard(); // invokes function printStandard d.tick(); // invokes function tick } // end for
cout << endl; return 0; } // end main
Universal Standard Universal Standard Universal Standard Universal Standard Universal Standard . . .
time: time: time: time: time: time: time: time: time: time:
23:59:57 11:59:57 23:59:58 11:59:58 23:59:59 11:59:59 00:00:00 12:00:00 00:00:01 12:00:01
PM PM PM AM AM
12-31-2004 12-31-2004 12-31-2004 12-31-2004 12-31-2004 12-31-2004 1-1-2005 1-1-2005 1-1-2005 1-1-2005
(Returning Error Indicators from Class Time’s set Functions) Modify the set functions in the Time class of Figs. 9.8–9.9 to return appropriate error values if an attempt is made toset a data mem9.10
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
503
ber of an object of class Time to an invalid value. Write a program that tests your new version of class Time. Display error messages when set functions return error values. ANS :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// Exercise 9.10 Solution: Time.h #ifndef TIME_H #define TIME_H
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// Exercise 9.10 Solution: Time.cpp // Member-function definitions for class Time. #include using std::cout;
class Time { public: Time( int = 0, int = 0, int = 0 ); // default constructor bool setTime( int, int, int ); // set hour, minute, second bool setHour( int ); // set hour bool setMinute( int ); // set minute bool setSecond( int ); // set second int getHour(); // get hour int getMinute(); // get minute int getSecond(); // get second void printUniversal(); // print universal time void printStandard(); // print standard time private: int hour; // 0-23 int minute; // 0-59 int second; // 0-59 }; // end class Time #endif
#include "Time.h" // include definition of class Time Time::Time( int hr, int min, int sec ) { setTime( hr, min, sec ); } // end Time constructor bool Time::setTime( int h, int m, int s ) { bool hourValid = setHour( h ); // invokes function setHour bool minuteValid = setMinute( m ); // invokes function setMinute bool secondValid = setSecond( s ); // invokes function setSecond return hourValid && minuteValid && secondValid; } // end function setTime bool Time::setHour( int hr ) { if ( hr >= 0 && hr < 24 ) {
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
504
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
Chapter 9
Classes: A Deeper Look, Part 1
hour = hr; return true; // hour is valid } // end if else { hour = 0; return false; // hour is invalid } // end else } // end function setHour bool Time::setMinute( int min ) { if ( min >= 0 && min < 60 ) { minute = min; return true; // minute is valid } // end if else { minute = 0; return false; // minute is invalid } // end else } // end function setMinute bool Time::setSecond( int sec ) { if ( sec >= 0 && sec < 60 ) { second = sec; return true; // second is valid } // end if else { second = 0; return false; // second is invalid } // end else } // end function setSecond // return hour value int Time::getHour() { return hour; } // end function getHour // return minute value int Time::getMinute() { return minute; } // end function getMinute // return second value int Time::getSecond() { return second; } // end function getSecond
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
void Time::printUniversal() { cout << ( hour < 10 ? "0" : "" ) << hour << ':' << ( minute < 10 ? "0" : "" ) << minute << ':' << ( second < 10 ? "0" : "" ) << second; } // end function printUniversal void Time::printStandard() { cout << ( ( hour % 12 == 0 ) ? 12 : hour % 12 ) << ':' << ( minute < 10 ? "0": "" ) << minute << ':' << ( second < 10 ? "0": "" ) << second << ( hour < 12 ? " AM" : " PM" ); } // end function printStandard
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
// Exercise 9.10 Solution: Ex09_10.cpp #include using std::cin; using std::cout; using std::endl;
1 2 3 4 5 6
// Exercise 9.10 Solution: Ex09_10.cpp #include using std::cin; using std::cout; using std::endl;
#include "Time.h" // include definition of class Time int main() { Time time; // the Time object
// all t1 object's times are valid if ( !t1.getInvalidTime() ) cout << "Error: invalid time setting(s) attempted." << '\n' << "Invalid setting(s) changed to zero." << '\n';
t1.printStandard();
// invokes function print standard
// object t2 has invalid time settings if ( !t2.getInvalidTime() ) cout << "\nError: invalid time setting(s) attempted.\n" << "Invalid setting(s) changed to zero.\n";
t2.printUniversal(); cout << endl;
// invokes function print universal
return 0; } // end main
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
505
506
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
Chapter 9
Classes: A Deeper Look, Part 1
#include "Time.h" // include definition of class Time int getMenuChoice(); // prototype int main() { Time time; // the Time object int choice = getMenuChoice(); int hours; int minutes; int seconds; while ( choice != 4 ) { switch ( choice ) { case 1: // set hour cout << "Enter Hours: "; cin >> hours; if ( !time.setHour( hours ) ) cout << "Invalid hours." << endl; break; case 2: // set minute cout << "Enter Minutes: "; cin >> minutes; if ( !time.setMinute( minutes ) ) cout << "Invalid minutes." << endl; break; case 3: // set seconds cout << "Enter Seconds: "; cin >> seconds; if ( !time.setSecond( seconds ) ) cout << "Invalid seconds." << endl; break; } // end switch
cout << "Hour: " << time.getHour() << " Minute: " << time.getMinute() << " Second: " << time.getSecond() << endl; cout << "Universal time: "; time.printUniversal(); cout << " Standard time: "; time.printStandard(); cout << endl;
choice = getMenuChoice(); } // end while } // end main // prints a menu and returns a value corresponding to the menu choice int getMenuChoice() { int choice;
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
62 63 64 65 66 67
507
cout << "1. Set Hour\n2. Set Minute\n3. Set Second\n" << "4. Exit\nChoice: " << endl; cin >> choice; return choice; } // end function getMenuChoice
1. Set Hour 2. Set Minute 3. Set Second 4. Exit Choice: 1
Enter Hours: 17 Hour: 17 Minute: 0 Second: 0 Universal time: 17:00:00 Standard time: 5:00:00 PM 1. Set Hour 2. Set Minute 3. Set Second 4. Exit Choice: 2
Enter Minutes: 65 Invalid minutes. Hour: 17 Minute: 0 Second: 0 Universal time: 17:00:00 Standard time: 5:00:00 PM 1. Set Hour 2. Set Minute 3. Set Second 4. Exit Choice: 3
Enter Seconds: 23 Hour: 17 Minute: 0 Second: 23 Universal time: 17:00:23 Standard time: 5:00:23 PM 1. Set Hour 2. Set Minute 3. Set Second 4. Exit Choice: 4
( Rectangle Class) Create a class Rectangle with attributes length and width, each of which defaults to 1. Provide member functions that calculate the perimeter and the area of the rectangle. Also, provide set and get functions for the length and width attributes. The set functions should verify that length and width are each floating-point numbers larger than 0.0 and less than 20.0. 9.11
ANS :
1 2 3 4 5 6
// Exercise 9.11 Solution: Rectangle.h #ifndef RECTANGLE_H #define RECTANGLE_H class Rectangle {
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
508
Chapter 9
Classes: A Deeper Look, Part 1
7 8 9 10 11 12 13 14 15 16 17 18 19 20
public: Rectangle( double = 1.0, double = 1.0 ); // default constructor void setWidth( double w ); // set width void setLength( double l ); // set length double getWidth(); // get width double getLength(); // get length double perimeter(); // perimeter double area(); // area private: double length; // 1.0 < length < 20.0 double width; // 1.0 < width < 20.0 }; // end class Rectangle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
// Exercise 9.11 Solution: Rectangle.cpp // Member-function definitions for class Rectangle.
#endif
#include "Rectangle.h" // include definition of class Rectangle Rectangle::Rectangle( double w, double l ) { setWidth(w); // invokes function setWidth setLength(l); // invokes function setLength } // end Rectangle constructor void Rectangle::setWidth( double w ) { width = w > 0 && w < 20.0 ? w : 1.0; // sets width } // end function setWidth void Rectangle::setLength( double l ) { length = l > 0 && l < 20.0 ? l : 1.0; // sets length } // end function setLength double Rectangle::getWidth() { return width; } // end function getWidth double Rectangle::getLength() { return length; } // end fucntion getLength double Rectangle::perimeter() { return 2 * ( width + length ); // returns perimeter } // end function perimeter double Rectangle::area() { return width * length; // returns area
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
40
} // end function area
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
// Exercise 9.11 Solution: Ex09_11.cpp #include using std::cout; using std::endl; using std::fixed;
509
#include using std::setprecision; #include "Rectangle.h" // include definition of class Rectangle int main() { Rectangle a, b( 4.0, 5.0 ), c( 67.0, 888.0 ); cout << fixed; cout << setprecision( 1 ); // output Rectangle a cout << "a: length = " << a.getLength() << "; width = " << a.getWidth() << "; perimeter = " << a.perimeter() << "; area = " << a.area() << '\n'; // output Rectangle b cout << "b: length = " << b.getLength() << "; width = " << b.getWidth() << "; perimeter = " << b.perimeter() << "; area = " << b.area() << '\n'; // output Rectangle c; bad values attempted cout << "c: length = " << c.getLength() << "; width = " << c.getWidth() << "; perimeter = " << c.perimeter() << "; area = " << c.area() << endl; return 0; } // end main
a: length = 1.0; width = 1.0; perimeter = 4.0; area = 1.0 b: length = 5.0; width = 4.0; perimeter = 18.0; area = 20.0 c: length = 1.0; width = 1.0; perimeter = 4.0; area = 1.0
(Enhancing Class Rectangle ) Create a more sophisticated Rectangle class than the one you created in Exercise 9.11. This class stores only the Cartesian coordinates of the four corners of the rectangle. The constructor calls a set function that accepts four sets of coordinates and verifies that each of these is in the first quadrant with no single x - or y -coordinate larger than 20.0. The set function also verifies that the supplied coordinates do, in fact, specify a rectangle. Provide member functions that calculate the length, width, perimeter and area. The length is the larger of the two dimensions. Include a predicate function square that determines whether the rectangle is a square. 9.12
ANS :
1
// Exercise 9.12 Solution: Point.h
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
510
Chapter 9
Classes: A Deeper Look, Part 1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#ifndef POINT_H #define POINT_H
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
// Exercise 9.12 Solution: Point.cpp // Member-function definitions for class Point.
class Point { public: Point( double = 0.0, double = 0.0 ); // default constructor // set and get functions void setX( double ); void setY( double ); double getX(); double getY(); private: double x; // 0.0 <= x <= 20.0 double y; // 0.0 <= y <= 20.0 }; // end class Point #endif
#include "Point.h" // include definition of class Point Point::Point( double xCoord, double yCoord ) { setX( xCoord ); // invoke function setX setY( yCoord ); // invoke function setY } // end Point constructor // set x coordinate void Point::setX( double xCoord ) { x = ( xCoord >= 0.0 && xCoord <= 20.0 ) ? xCoord : 0.0; } // end function setX // set y coordinate void Point::setY( double yCoord ) { y = ( yCoord >= 0.0 && yCoord <= 20.0 ) ? yCoord : 0.0; } // end function setY // return x coordinate double Point::getX() { return x; } // end function getX // return y coordinate double Point::getY() { return y;
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
34
} // end function getY
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
// Exercise 9.12 Solution: Rectangle.h #ifndef RECTANGLE_H #define RECTANGLE_H
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// Exercise 9.12 Solution: Rectangle.cpp // Member-function definitions for class Rectangle. #include using std::cout; using std::endl;
#include "Point.h" // include definition of class Point class Rectangle { public: // default constructor Rectangle( Point = Point( 0.0, 1.0 ), Point = Point( 1.0, 1.0 ), Point = Point( 1.0, 0.0 ), Point = Point( 0.0, 0.0 ) ); // sets x, y, x2, y2 coordinates void setCoord( Point, Point, Point, Point ); double length(); // length double width(); // width void perimeter(); // perimeter void area(); // area bool square(); // square private: Point point1; Point point2; Point point3; Point point4; }; // end class Rectangle #endif
#include using std::fixed; using std::setprecision; #include using std::fabs; #include "Rectangle.h" // include definition of class Rectangle Rectangle::Rectangle( Point a, Point b, Point c, Point d ) { setCoord( a, b, c, d ); // invokes function setCoord } // end Rectangle constructor void Rectangle::setCoord( Point p1, Point p2, Point p3, Point p4 ) {
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
511
512
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
Chapter 9
Classes: A Deeper Look, Part 1
// Arrangement of points // p4.........p3 // . . // . . // p1.........p2 // verify that points form a rectangle if ( ( p1.getY() == p2.getY() && p1.getX() == p4.getX() && p2.getX() == p3.getX() && p3.getY() == p4.getY() ) ) { point1 = p1; point2 = p2; point3 = p3; point4 = p4; } // end if else { cout << "Coordinates do not form a rectangle!\n" << "Use default values.\n"; point1 = Point( 0.0, 1.0 ); point2 = Point( 1.0, 1.0 ); point3 = Point( 1.0, 0.0 ); point4 = Point( 0.0, 0.0 ); } // end else } // end function setCoord double Rectangle::length() { double side1 = fabs( point4.getY() - point1.getY() ); // get side1 double side2 = fabs( point2.getX() - point1.getX() ); // get side2 double length = ( side1 > side2 ? side1 : side2 ); return length; } // end function length double Rectangle::width() { double side1 = fabs( point4.getY() - point1.getY() ); // get side1 double side2 = fabs( point2.getX() - point1.getX() ); // get side2 double width = ( side1 < side2 ? side1 : side2 ); return width; } // end function width void Rectangle::perimeter() { cout << fixed << "\nThe perimeter is: " << setprecision( 1 ) << 2 * ( length() + width() ) << endl; } // end function perimeter void Rectangle::area() { cout << fixed << "The area is: " << setprecision( 1 ) << length() * width() << endl; } // end function area bool Rectangle::square()
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
78 79 80 81
{
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
// Exercise 9.12 Solution: Ex09_12.cpp #include using std::cout;
return ( fabs( point4.getY() - point1.getY() ) == fabs( point2.getX() - point1.getX() ) ); } // end function square
#include "Rectangle.h" // include definition of class Rectangle int main() { Point w( 1.0, 1.0 ); Point x( 5.0, 1.0 ); Point y( 5.0, 3.0 ); Point z( 1.0, 3.0 ); Point j( 0.0, 0.0 ); Point k( 1.0, 0.0 ); Point m( 1.0, 1.0 ); Point n( 0.0, 1.0 ); Point v( 99.0, -2.3 ); Rectangle rectangles[ 4 ]; // array stores four rectangles // output rectangles for ( int i = 0; i < 4; i++ ) { cout << "Rectangle" << i + 1 << ":\n"; switch ( i ) // initialize four different rectangles { case 0: // first rectangle rectangles[ i ] = Rectangle( z, y, x, w ); break; case 1: // second rectangle rectangles[ i ] = Rectangle( j, k, m, n ); break; case 2: // third rectangle rectangles[ i ] = Rectangle( w, x, m, n ); break; case 3: // fourth rectangle rectangles[ i ] = Rectangle( v, x, y, z ); break; } // end switch cout << "length = " << rectangles[ i ].length(); cout << "\nwidth = " << rectangles[ i ].width(); rectangles[ i ].perimeter(); rectangles[ i ].area(); cout << "The rectangle " << ( rectangles[ i ].square() ? "is" : "is not" ) << " a square.\n"; } // end for
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
513
514
50 51 52
Chapter 9
Classes: A Deeper Look, Part 1
return 0; } // end main
Rectangle1: length = 4 width = 2 The perimeter is: 12.0 The area is: 8.0 The rectangle is not a square. Rectangle2: length = 1.0 width = 1.0 The perimeter is: 4.0 The area is: 1.0 The rectangle is a square. Rectangle3: Coordinates do not form a rectangle! Use default values. length = 1.0 width = 1.0 The perimeter is: 4.0 The area is: 1.0 The rectangle is a square. Rectangle4: Coordinates do not form a rectangle! Use default values. length = 1.0 width = 1.0 The perimeter is: 4.0 The area is: 1.0 The rectangle is a square.
(Enhancing Class Rectangle ) Modify class Rectangle from Exercise 9.12 to include a draw function that displays the rectangle inside a 25-by-25 box enclosing the portion of the first quadrant in which the rectangle resides. Include a setFillCharacter function to specify the character out of which the body of the rectangle will be drawn. Include a setPerimeterCharacter function to specify the character that will be used to draw the border of the rectangle. If you feel ambitious, you might include functions to scale the size of the rectangle, rotate it, and move it around within the designated portion of the first quadrant. 9.13
ANS :
1 2 3 4 5 6 7 8 9 10 11 12
// Exercise 9.13 Solution: Rectangle.h #ifndef RECTANGLE_H #define RECTANGLE_H #include "Point.h" // include definition of class Point class Rectangle { public: // default constructor Rectangle( Point = Point( 0.0, 1.0 ), Point = Point( 1.0, 1.0 ), Point = Point( 1.0, 0.0 ), Point = Point( 0.0, 0.0 ),
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
515
char = '*', char = '*' ); // sets x, y, x2, y2 coordinates void setCoord( Point, Point, Point, Point ); double length(); // length double width(); // width void perimeter(); // perimeter void area(); // area bool square(); // square void draw(); // draw rectangle void setPerimeterCharacter( char ); // set perimeter character void setFillCharacter( char ); // set fill character private: Point point1; Point point2; Point point3; Point point4; char fillCharacter; char perimeterCharacter; }; // end class Rectangle #endif
// Exercise 9.13 Solution: Rectangle.cpp // Member-function definitions for class Rectangle. #include using std::cout; using std::endl; #include using std::fixed; using std::setprecision; #include using std::fabs; #include "Rectangle.h" // include definition of class Rectangle Rectangle::Rectangle( Point a, Point b, Point c, Point d, char fillChar, char perimeterChar ) { setCoord( a, b, c, d ); // invoke function setCoord setFillCharacter( fillChar ); // set fill character setPerimeterCharacter( perimeterChar ); // set perimeter character } // end Rectangle constructor void Rectangle::setCoord( Point p1, Point p2, Point p3, Point p4 ) { // Arrangement of points // p4.........p3 // . . // . . // p1.........p2
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
516
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
Chapter 9
Classes: A Deeper Look, Part 1
// verify that points form a rectangle if ( ( p1.getY() == p2.getY() && p1.getX() == p4.getX() && p2.getX() == p3.getX() && p3.getY() == p4.getY() ) ) { point1 = p1; point2 = p2; point3 = p3; point4 = p4; } // end if else { cout << "Coordinates do not form a rectangle!\n" << "Use default values.\n"; point1 = Point( 0.0, 1.0 ); point2 = Point( 1.0, 1.0 ); point3 = Point( 1.0, 0.0 ); point4 = Point( 0.0, 0.0 ); } // end else } // end function setCoord double Rectangle::length() { double side1 = fabs( point4.getY() - point1.getY() ); // get side1 double side2 = fabs( point2.getX() - point1.getX() ); // get side2 double length = ( side1 > side2 ? side1 : side2 ); return length; } // end function length double Rectangle::width() { double side1 = fabs( point4.getY() - point1.getY() ); // get side1 double side2 = fabs( point2.getX() - point1.getX() ); // get side2 double width = ( side1 < side2 ? side1 : side2 ); return width; } // end function width void Rectangle::perimeter() { cout << fixed << "\nThe perimeter is: " << setprecision( 1 ) << 2 * ( length() + width() ) << endl; } // end function perimeter void Rectangle::area() { cout << fixed << "The area is: " << setprecision( 1 ) << length() * width() << endl; } // end function area bool Rectangle::square() { return ( fabs( point4.getY() - point1.getY() ) == fabs( point2.getX() - point1.getX() ) ); } // end function square // draw rectangle
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
1 2
517
void Rectangle::draw() { for ( double y = 25.0; y >= 0.0; y-- ) { for ( double x = 0.0; x <= 25.0; x++ ) { if ( ( point1.getX() == x && point1.getY() == y ) || ( point4.getX() == x && point4.getY() == y ) ) { // print horizontal perimeter of rectangle while ( x <= point2.getX() ) { cout << perimeterCharacter; x++; } // end while cout << '.'; // print remainder of quadrant } // end if else if ( ( ( x <= point4.getX() && x >= point1.getX() ) ) && point4.getY() >= y && point1.getY() <= y ) { cout << perimeterCharacter;
// fill inside of rectangle for ( x++; x < point2.getX(); ) { cout << fillCharacter; x++; } // end for cout << perimeterCharacter; } // end else if else cout << '.'; // print quadrant background } // end for
cout << '\n'; } // end for } // end function draw // set fill character void Rectangle::setFillCharacter( char fillChar ) { fillCharacter = fillChar; } // end function setFillCharacter // set perimeter character void Rectangle::setPerimeterCharacter( char perimeterChar ) { perimeterCharacter = perimeterChar; } // end function setPerimeterCharacter
// Exercise 9.13 Solution: Ex09_13.cpp
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
518
3 4 5 6 7 8 9 10 11 12 13 14
Chapter 9
Classes: A Deeper Look, Part 1
#include "Rectangle.h" // include definition of class Rectangle int main() { Point point1( 12.0, 12.0 ); Point point2( 18.0, 12.0 ); Point point3( 18.0, 20.0 ); Point point4( 12.0, 20.0 ); Rectangle rectangle( point1, point2, point3, point4, '?', '*' ); rectangle.draw(); // invokes function draw return 0; } // end main
.......................... .......................... .......................... .......................... .......................... ............*******....... ............*?????*....... ............*?????*....... ............*?????*....... ............*?????*....... ............*?????*....... ............*?????*....... ............*?????*....... ............*******....... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... .......................... ..........................
( HugeInteger Class) Create a class HugeInteger that uses a 40-element array of digits to store integers as large as 40 digits each. Provide member functions input, output, add and substract. For comparing HugeInteger objects, provide functions isEqualTo, isNotEqualTo, isGreaterThan, isLessThan, isGreaterThanOrEqualTo and isLessThanOrEqualTo—each of these is a “predicate” function that simply returns true if the relationship holds between the two HugeIntegers and returns false if the relationship does not hold. Also, provide a predicate function isZero. If you feel ambitious, provide member functions multiply, divide and modulus. 9.14
ANS :
1 2 3 4 5
// Exercise 9.14 Solution: HugeInteger.h // HugeInteger class definition. #ifndef HUGEINTEGER_H #define HUGEINTEGER_H
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
class HugeInteger { public:
1 2 3 4 5 6 7 8 9 10
// Exercise 9.14 Solution: HugeInteger.cpp // Member-function definitions for class HugeInteger. #include using std::cin; using std::cout;
HugeInteger( long = 0 ); // conversion/default constructor HugeInteger( const char * ); // copy constructor // addition operator; HugeInteger + HugeInteger HugeInteger add( const HugeInteger & ); // addition operator; HugeInteger + int HugeInteger add( int ); // addition operator; // HugeInteger + string that represents large integer value HugeInteger add( const char * ); // subtraction operator; HugeInteger - HugeInteger HugeInteger subtract( const HugeInteger & ); // subtraction operator; HugeInteger - int HugeInteger subtract( int ); // subtraction operator; // HugeInteger - string that represents large integer value HugeInteger subtract( const char * );
bool isEqualTo( HugeInteger & ); // is equal to bool isNotEqualTo( HugeInteger & ); // not equal to bool isGreaterThan(HugeInteger & ); // greater than bool isLessThan( HugeInteger & ); // less than bool isGreaterThanOrEqualTo( HugeInteger & ); // greater than // or equal to bool isLessThanOrEqualTo( HugeInteger & ); // less than or equal bool isZero(); // is zero void input( const char * ); // input void output(); // output short* getInteger(); // get integer private: short integer[ 40 ]; // 40 element array }; // end class HugeInteger #endif
#include "HugeInteger.h" // include definiton of class HugeInteger // default constructor; conversion constructor that converts // a long integer into a HugeInteger object
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
519
520
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
Chapter 9
Classes: A Deeper Look, Part 1
HugeInteger::HugeInteger( long value ) { // initialize array to zero for ( int i = 0; i < 40; i++ ) integer[ i ] = 0; // place digits of argument into array for ( int j = 39; value != 0 && j >= 0; j-- ) { integer[ j ] = static_cast< short > ( value % 10 ); value /= 10; } // end inner for } // end HugeInteger constructor // copy constructor; // converts a char string representing a large integer into a HugeInteger HugeInteger::HugeInteger( const char *string ) { this->input( string ); // call input to initialize HugeInteger } // end HugeInteger constructor // addition operator; HugeInteger + HugeInteger HugeInteger HugeInteger::add( const HugeInteger &op2 ) { HugeInteger temp; // temporary result int carry = 0; // iterate through HugeInteger for ( int i = 39; i >= 0; i-- ) { temp.integer[ i ] = integer[ i ] + op2.integer[ i ] + carry;
// determine whether to carry a 1 if ( temp.integer[ i ] > 9 ) { temp.integer[ i ] %= 10; // reduce to 0-9 carry = 1; } // end if else // no carry carry = 0; } // end for
return temp; // return the sum } // end function add // addition operator; HugeInteger + int HugeInteger HugeInteger::add( int op2 ) { // convert op2 to a HugeInteger, then invoke add return this->add( HugeInteger( op2 ) ); } // end function add // HugeInteger + string that represents large integer value HugeInteger HugeInteger::add( const char *op2 )
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
{ // convert op2 to a HugeInteger, then invoke add return this->add( HugeInteger( op2 ) ); } // end function add // function to subtract two HugeIntegers HugeInteger HugeInteger::subtract( const HugeInteger &op2 ) { HugeInteger temp; // temporary result int borrow = 0; // iterate through HugeInteger for ( int i = 39; i >= 0; i-- ) { // determine to add 10 to smaller integer if ( integer[i] < op2.integer[i] ) { temp.integer[ i ] = ( integer[ i ] + 10 ) - op2.integer[ i ] - borrow; borrow = 1; // set borrow to one } // end if else // if borrowing is not needed { temp.integer[ i ] = integer[ i ] - op2.integer[ i ] - borrow; borrow = 0; // set borrow to zero } // end else } // end for return temp; // return difference of two HugeIntegers } // end function subtract // function to subtract an integer from a HugeInteger HugeInteger HugeInteger::subtract( int op2 ) { // convert op2 to a HugeInteger, then invoke subtract return this->subtract( HugeInteger( op2 ) ); } // end function subtract // function that takes string represeting a number // and subtracts it from a HugeInteger HugeInteger HugeInteger::subtract( const char *op2 ) { // convert op2 to a HugeInteger, then invoke subtract return this->subtract( HugeInteger( op2 ) ); } // end function subtract // function that tests if two HugeIntegers are equal bool HugeInteger::isEqualTo( HugeInteger &x ) { return integer == x.getInteger(); } // end function isEqualTo // function that tests if two HugeIntegers are not equal bool HugeInteger::isNotEqualTo( HugeInteger &x )
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
521
522
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
Chapter 9
Classes: A Deeper Look, Part 1
{ return !( this->isEqualTo( x ) ); } // end function isNotEqualTo // function to test if one HugeInteger is greater than another bool HugeInteger::isGreaterThan( HugeInteger &x ) { return integer < x.getInteger(); } // end function isGreaterThan // function that tests if one HugeInteger is less than another bool HugeInteger::isLessThan( HugeInteger &x ) { return integer > x.getInteger(); } // end function isLessThan // function that tests if one HugeInteger is greater than // or equal to another bool HugeInteger::isGreaterThanOrEqualTo( HugeInteger &x ) { return integer <= x.getInteger(); } // end function isGreaterThanOrEqualTo // function that tests if one HugeInteger is less than or // equal to another bool HugeInteger::isLessThanOrEqualTo( HugeInteger &x ) { return integer >= x.getInteger(); } // end function isLessThanOrEqualTo // function that tests if a HugeInteger is zero bool HugeInteger::isZero() { return ( getInteger() == 0 ); } // end function isZero // converts a char string representing a large integer into a HugeInteger void HugeInteger::input( const char *string ) { // initialize array to zero for ( int i = 0; i < 40; i++ ) integer[ i ] = 0; // place digits of argument into array int length = strlen( string ); for ( int j = 40 - length, k = 0; j < 40; j++, k++ ) if ( isdigit( string[ k ] ) ) integer[ j ] = string[ k ] - '0'; } // end function input // overloaded output operator void HugeInteger::output() {
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
int i; // used for looping for ( i = 0; ( integer[ i ] == 0 ) && ( i <= 39 ); i++ ) ; // skip leading zeros if ( i == 40 ) cout << 0; else for ( ; i <= 39; i++ ) // display the HugeInteger cout << integer[ i ]; } // end function output // return a HugeInteger short* HugeInteger::getInteger() { return integer; } // end function getInteger
// Exercise 9.14 Solution: Ex09_14.cpp // HugeInteger test program. #include using std::cout; using std::endl; #include "HugeInteger.h" // include definiton of class HugeInteger int main() { HugeInteger HugeInteger HugeInteger HugeInteger HugeInteger
n1( n2( n3; n4( n5;
7654321 ); // HugeInteger object n1 "7891234" ); // HugeInteger object n2 // HugeInteger object n3 5 ); // HugeInteger object n4 // HugeInteger object n5
// outputs the sum of n1 and n2 n5 = n1.add( n2 ); n1.output(); cout << " + "; n2.output(); cout << " = "; n5.output(); cout << "\n\n"; // assigns the difference of n2 and n4 to n5 then outputs n5 n5 = n2.subtract( n4 ); n2.output(); cout<< " - "; n4.output(); cout << " = "; n5.output(); cout << "\n\n";
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
523
524
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
Chapter 9
Classes: A Deeper Look, Part 1
// checks for equality between n1 and n1 if ( n1.isEqualTo( n1 ) == true ) { n1.output(); cout << " is equal "; n1.output(); cout << "\n\n"; } // end if // checks for inequality between n1 and n2 if ( n1.isNotEqualTo( n2 ) == true ) { n1.output(); cout << " is not equal to "; n2.output(); cout << "\n\n"; } // end if // tests for greater number between n2 and n1 if ( n2.isGreaterThan( n1 ) == true ) { n2.output(); cout << " is greater than "; n1.output(); cout << "\n\n"; } // end if // tests for smaller number between n2 and n4 if ( n2.isLessThan( n4 ) == true ) { n4.output(); cout << " is less than "; n2.output(); cout << "\n\n"; } // end if // tests for smaller or equal number between n4 and n4 if ( n4.isLessThanOrEqualTo( n4 ) == true ) { n4.output(); cout << " is less than or equal to "; n4.output(); cout << "\n\n"; } // end if // tests for greater or equal number between n3 and n3 if ( n3.isGreaterThanOrEqualTo( n3 ) == true ) { n3.output(); cout << " is greater than or equal to "; n3.output(); cout << "\n\n"; } // end if // tests for zero at n3
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
91 92 93 94 95 96 97 98 99
525
if ( n3.isZero() != true ) { cout << "n3 contains value "; n3.output(); cout << "\n\n"; } // end if statement
return 0; } // end main
7654321 + 7891234 = 15545555 7891234 - 5 = 7891229 7654321 is equal 7654321 7654321 is not equal to 7891234 5 is less than or equal to 5 0 is greater than or equal to 0 n3 contains value 0
( TicTacToe Class) Create a class TicTacToe that will enable you to write a complete program to play the game of tic-tac-toe. The class contains as private data a 3-by-3 two-dimensional array of integers. The constructor should initialize the empty board t o all zeros. Allow two human players. Wherever the first player moves, place a X in the specified square. Place an O wherever the second player moves. Each move must be to an empty square. After each move, determine whether the game has been won or is a draw. If you feel ambitious, modify your program so that the computer makes the moves for one of the players. Also, allow the player to specify whether he or she wants to go first or second. If you feel exceptionally ambitious, develop a program that will play three-dimensional tic-tac-toe on a 4-by-4-by-4 board. [Caution: This is an extremely challenging project that could take many weeks of effort!] 9.15
ANS :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// Exercise 9.15 Solution: TicTacToe.h #ifndef TICTACTOE_H #define TICTACTOE_H class TicTacToe { private: enum Status { WIN, DRAW, CONTINUE }; // enumeration constants int board[ 3 ][ 3 ]; public: TicTacToe(); // default constructor void makeMove(); // make move void printBoard(); // print board bool validMove( int, int ); // validate move bool xoMove( int ); // x o move Status gameStatus(); // game status }; // end class TicTacToe
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
526
18 19
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
Chapter 9
Classes: A Deeper Look, Part 1
#endif
// Exercise 9.15 Solution: TicTacToe.cpp // Member-function definitions for class TicTacToe. #include using std::cin; using std::cout; #include using std::setw; #include "TicTacToe.h" // include definiton of class TicTacToe TicTacToe::TicTacToe() { for ( int j = 0; j < 3; j++ ) // initialize board for ( int k = 0; k < 3; k++ ) board[ j ][ k ] = ' '; } // end TicTacToe constructor bool TicTacToe::validMove( int r, int c ) { return r >= 0 && r < 3 && c >= 0 && c < 3 && board[ r ][ c ] == ' '; } // end function validMove // must specify that type Status is part of the TicTacToe class. // See Chapter 24 for a discussion of namespaces. TicTacToe::Status TicTacToe::gameStatus() { int a;
// check for a win on diagonals if ( board[ 0 ][ 0 ] != ' ' && board[ 0 ][ 0 ] == board[ 1 ][ 1 ] && board[ 0 ][ 0 ] == board[ 2 ][ 2 ] ) return WIN; else if ( board[ 2 ][ 0 ] != ' ' && board[ 2 ][ 0 ] == board[ 1 ][ 1 ] && board[ 2 ][ 0 ] == board[ 0 ][ 2 ] ) return WIN; // check for win in rows for ( a = 0; a < 3; ++a ) if ( board[ a ][ 0 ] != ' ' && board[ a ][ 0 ] == board[ a ][ 1 ] && board[ a ][ 0 ] == board[ a ][ 2 ] ) return WIN; // check for win in columns for ( a = 0; a < 3; ++a )
if ( board[ 0 ][ a ] != ' ' && board[ 0 ][ a ] == board[ 1 ][ a ] && board[ 0 ][ a ] == board[ 2 ][ a ] ) return WIN;
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
Solutions
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
527
// check for a completed game for ( int r = 0; r < 3; ++r ) for ( int c = 0; c < 3; ++c ) if ( board[ r ][ c ] == ' ' ) return CONTINUE; // game is not finished return DRAW; // game is a draw } // end function gameStatus void TicTacToe::printBoard() { cout << " 0 1 2\n\n"; for ( int r = 0; r < 3; ++r ) { cout << r; for ( int c = 0; c < 3; ++c ) { cout << setw( 3 ) << static_cast< char > ( board[ r ][ c ] ); if ( c != 2 ) cout << " |"; } // end for if ( r != 2 ) cout << "\n ____|____|____\n } // end for
|
|
\n";
cout << "\n\n"; } // end function printBoard void TicTacToe::makeMove() { printBoard(); while ( true ) { if ( xoMove( 'X' ) ) break; else if ( xoMove( 'O' ) ) break; } // end while structure } // end function makeMove bool TicTacToe::xoMove( int symbol ) { int x; int y; do {
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.
528
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
1 2 3 4 5 6 7 8 9 10
Chapter 9
Classes: A Deeper Look, Part 1
cout << "Player " << static_cast< char >( symbol ) << " enter move: "; cin >> x >> y; cout << '\n'; } while ( !validMove( x, y ) );
board[ x ][ y ] = symbol; printBoard(); Status xoStatus = gameStatus();
if ( xoStatus == WIN ) { cout << "Player " << static_cast< char >( symbol ) << " wins!\n"; return true; } // end if else if ( xoStatus == DRAW ) { cout << "Game is a draw.\n"; return true; } // end else if else // CONTINUE return false; } // end function xoMove
// Exercise 9.15 Solution: Ex09_15.cpp #include "TicTacToe.h" // include definiton of class TicTacToe int main() { TicTacToe g; // creates object g of class TicTacToe g.makeMove(); // invokes function makeMove return 0; } // end main
Copyright ® 1992-2005 by Deitel & Associates, Inc. All Rights Reserved.