4.2 If any string other than ``yes'' is entered, the else clause is executed (and the string ``De gustibus non Disputandum'' is printed).
4.3
if ("yes" == response)
{
cout << ...;
}
else if ("no" == respone)
{
cout << ...;
}
else
{
cout << "sorry, only responses of yes and no are recognized" << endl;
}
4.4 One code fragment that could be used is shown below. There are lots of others.
int grade;
cout << "enter a grade: ";
cin >> grade;
if (grade > 90)
{
cout << "excellent score" << endl;
}
else if (grade > 80)
{
cout << "good work, keep it up" << endl;
}
else if (grade > 70)
{
cout << "ok, keep working on the material" << endl;
}
else if (grade > 60)
{
cout << "be sure to ask questions when things are hard" << endl;
}
else
{
cout << "you need to work very hard" << endl;
}
Each else clause is necessary. If they're left out a grade of
100 would cause all the messages to be printed. In the code above
a grade of 75 will cause the guard (grade > 70) to be
true, and that's the only guard that will be evaluated as true.
4.5 When a string is used, the user can enter any characters from the keyboard. When an int is used, only digits can be entered, 0,1, ..., 9 (and +/- signs). By using strings, the program is more robust , that is less prone to crash if the user enters something unexpected.
Using a string ensures that anything entered by the user is processed, the string will always have a value. If an int is used, and the user enters "one", the int will have no value, the characters 'o', 'n', and 'e' will remain unprocessed on the input stream.
4.6 One variable is sufficient because only one value is needed at a time. The answer to any single question determines what action to take next, but because there is no reason to "remember" choices during the exection of the program one variable suffices.
4.7 Here's a program for BTU's to Joules, the other programs are similar.
double btu; cout << "enter BTU's "; cin >> btu; cout << btu << " BTU's = " << btu/1054.8 << " Joules";To use an assignment operator, use:
double joule;
...
joule = btu/1054.8;
cout << btu << " BTU's = " << joule << " Joules";
4.8
The output of cout << 9 * 3 < 4 * 5 << endl is 0
because the expression evaluates to 27 < 20 , which
evaluates to false, which is 0.
The expression 9 * (3 < 4) * 5 evaluates to
9 * 1 * 5
because (3 < 4) is true which is 1. This is why 45 is output.
4.9
The statement cout << 9 * 5 < 45 << endl generates
0 as output because it is false and false corresponds to 0 for output
(on most current systems).
The statement cout << 9*5 < 45 < 30 << endl evaluates
to 45 < 45 < 30 which evaluates to
0 < 30 which is 1
(true). This depends on the associativity of the < operator.
4.10 The average of three values can be output using the statement below.
cout << (a + b + c)/3.0 << endl;
The parentheses are necessary because / has higher precedence
than +. If the type of a,b,c is changed to
double then the average will be a double as well. However,
in the statement above a double value will be calculated even if
a,b,c are int's because of the 3.0. The
operator >> is left associative. The statement
cout >> a >> b >> c is treated like
((cout >> a) >> b) >> c .
4.11 There are many possibilities, one is shown below.
string grade;
int score;
cout << "enter score: ";
cin >> score;
if (score > 100)
{
cout << "score too high, between 0 and 100" << endl;
}
else if (score >= 80)
{
grade = "High Pass";
}
else if (score >= 60)
{
grade = "Pass";
}
else{
grade = "Fail";
}
4.12 There are many ways of writing this code. In the function below I've used a return statement on a single line with an if statement (for February). In some situations it's convenient not to use a compound statement. In such situations I put all the code on one line as shown below.
in DaysInMonth(int month, int year)
// precondition: month coded as 1 = january, ..., 12 = december
// postcondition: returns # of days in month in year
{
// 30 days has september, april, june, and november
if (9 == month || 4 == month ||
6 == month ||11 == month)
{
return 30;
}
else if (2 == month) // handle february
{
if (IsLeap(year)) return 29;
return 28;
}
else
{
return 31;
}
4.13 The parentheses are needed because the expression
TensPrefix(10 * num / 10)
when num == 22 evaluates to TensPrefix(10 * 22 / 10)
which is TensPrefix(220/10) which is
TensPrefix(22) because * and / have equal precedence so
in the absence of parentheses the order of evaluation is left-to-right.
4.14 This function can be written in many ways, I've shown two below. The second version uses the same ``logic'' as the first, but returns the result of the expression testing for divisibility by 2 which is either 0 or 1 depending on whether num is odd or even, respectively.
int IsEven(int num)
// precondition: returns 1 if num is even, else returns 0
{
if (num % 2 == 0)
{
return 1;
}
return 0;
}
int IsEven(int num)
// precondition: returns 1 if num is even, else returns 0
{
return num % 2 == 0;
}
4.15 In the function below I've used the one line form of an if statement again. In this case the code is clear and it probably won't be modified so this approach is justified.
string DayName(int day)
// precondition: 0 <= day <= 6
// postcondition: returns string representing day with
// 0 = "Sunday", 1 = "Monday", ..., 6 = "Saturday"
{
if (0 == day) return "Sunday";
if (1 == day) return "Monday";
if (2 == day) return "Tuesday";
if (3 == day) return "Wednesday";
if (4 == day) return "Thursday";
if (5 == day) return "Friday";
if (6 == day) return "Saturday";
}
4.16 (answer will appear soon)
4.17
There's room for improvement in the function below. It
is possible, for example, to check for common abbreviations
like nope, yeah, yup, etc. and return the string
"yes"
or "no" as appropriate.
string YesNo(string prompt)
// postcondition: returns either "yes" or "no"
// depending on user's entered response
{
string response;
cout << prompt << " [yes/no]";
cin >> response;
return response;
}
4.18 This function is easier to write than the leap year function for our (Julian/Gregorian) calendar.
int IsIslamicLeap(int year)
// postcondition: returns 1 if year is a leap year in the
// Islamic calendar, else returns 0
{
return ((11*y + 14) % 30) < 11;
}
4.19 I used only 2 if statements in the function below by using the && operator.
int IslamicDaysInMonth(int month, int year)
// postcondition: returns # of days in month/year
{
// odd numbered months have 30 days
if (month % 2 == 1) return 30;
if (12 == month && IsIslamicLeap(year)) return 30;
return 29; // even numbered months have 29 days
}
4.20
Once again, there are many ways to do this.
4.21
4.22
The loop guard uses the value of num, but this variable is
not modified in the loop body. Hence the loop body, if it executes
once, will execute ``forever''. If the user enters a number greater
than or equal to 100 the loop body won't execute at all.
4.23
This loop effectively calculates the base-2 logarithm of a number
(actually one more than the base-2 log). If log_2(X) = Y then the
relationship 2^Y = X holds. Thus log_2(32) = 5 since 2^5 = 32.
4.24
This can be done with one loop, using the value of the number being
printed to determine when a new line of output should be started
(multiples of 10). In the loop below, a space is printed after every
number rather than between numbers. The next loop shows a solution to
the fencepost problem of only printing a space between numbers.
A nested-loop can be used for this problem too. One loop for each
line, and an outer loop for the number of lines. In general, it's a
good idea to try to write code without nested loops if possible. Nested
loops are usually hard to get right.
4.25
4.26
This code does pass a black-box test. The only difference is that the
value of
4.27
The code will never generate an error because of short-circuit
evaluation. If the value of
4.28
Yes, if
4.29
The call
4.30
If the loop below is used in IsPrime, some method is needed for
determining why the loop exits, i.e., which of the conjuncts
4.31
The sqrt function yields approximations to square
roots, not the exact square root. This is due to the finite precision
of floating point numbers (the type double in C++). For numbers
like 9.0, the square root will most likely be 3.0, but for larger
numbers that are perfect squares the likelihood of small perturbations
from the exact result increases. When these small differences are
multiplied as in the code fragment from this problem, the differences
are ``magnified''.
In general, it's not a good idea to check for exact equality when
comparing floating point (double) values, but to use some kind of
tolerance.
Fragments like the one below can be used to see if two values are
``close''. Choosing the correct tolerance is part of the study of
numerical analysis , a branch of computer science we'll only
briefly explore.
4.32
Think about these questions.
4.33
Soda machines are complicated. Next time one is being serviced,
watch the person doing this fill the soda racks.
4.34
There are lots of comments so that users (or clients) of the class
will be able to use the Dice class in programs. Comments are needed
to understand what the class does (at least for client programs).
The comments are like a manual for how to use the class.
4.35
There is a typo in the Fall 1995 version of the book, the line should
read.
4.36
To allow the user to enter the number of sides of the dice the
following could be used.
4.37
4.38
4.40
If the two lines below are the entire function Power, the
function won't work as intended.
4.41
If the output statements are added, the call Power(25,6)
will generate output as shown below. These are powers of 25 from
25^1, 25^2, ... , 25^5, 25^6. On PC's and macs the return type for
the function Power should be long or long int or
the last ``correct'' value below will be 15625, the other values exceed
the maximum value of 16-bit integers.
The call Power(3,9) generates the output below (successive powers
of 3 from 3^1 to 3^9).
4.42
The loop iterates exactly expo times.
4.43
A ``good'' invariant is shown below.
When the loop terminates, the value of k is expo so the
truth of the invariant indicates that
4.44
The addition of the output statement
4.45
There is a typo in the Fall 1995 version of this code. The function
body should be
#include
num = 1;
while (num < 30000)
{
cout << num << endl;
num *= 2; // next power of two
}
int num;
cout << "enter a number ";
cin >> num;
int count = 0;
while (num > 0)
{
num /= 2;
count += 1;
}
cout << "base 2 log + 1 of " << num << " = " << count;
// space after every number
num = 1;
while (num <= 100)
{
cout << num << " ";
if (num % 10 == 0)
{
cout << endl; // new line on multiple of 10
}
num += 1; // next number
}
// space between numbers only
int num = 1;
while (num <= 100)
{
if (num % 10 != 1) // NOT first number on line
{
cout << " "; // so has space before it
}
cout << num;
if (num % 10 == 0)
{
cout << endl; // new line
}
num += 1;
}
int numLines = 0; // # of lines printed
while (numLines < 10) // more lines of output?
{
int num = numLines*10 + 1; // first number on line
int count = 0; // count # of numbers printed
while (count < 10)
{
cout << num;
num += 1; // next number to print
count += 1; // another number printed
}
cout << endl; // new line of output
numLines += 1;
}
The code in the inner loop doesn't need both num and
count . Since both are incremented by one each time through the
loop, one of them is superfluous. Defining and using both is ok, but
it's possible to dispense with count and use a test of
while (num <= numLines*10 + 10)
as the guard. It might be useful to use a variable with the value
numLines*10+ 10
so that this isn't recalculated everytime through
the loop. Smart compilers can ``optimize'' this kind of recomputation
away, however.
page 142
int Factorial(int num)
// postcondition: returns num! if num >= 0
// returns (-num)! if num is negative
{
num = Abs(num);
// remaining code identical to fact.cc code
int product = 1;
int count = 1;
while (count <= num) // invariant: product == (count-1)!
{
product *= count;
count += 1;
}
return product;
}
count starts at 0 instead of 1 (and the loop
test compensates for this). Because count is incremented
before the value of product is updated (in
contrast to the loop in fact.cc) the value returned is correct.
x is negative when
if (x >= 0 && sqrt(x) > 10)
is evaluated. Then the subexpression x >= 0 will be
false, and the call to sqrt will NOT be made because the
whole expression must be false. This is one of the nice things about
short-circuit evaluation of boolean expressions.
divisor += 2 is changed to
divisor += 1 the function IsPrime will still
return the correct values. However, it will test many
more divisors than necessary since it will now test all numbers
between 3 and limit rather than just odd numbers. Since even
numbers have already been checked before the loop, checking even
divisors is not necessary.
IsPrime(1) evaluates to false (the first if
statement takes care of this, checking for numbers less than 2.
divisor <= limit and n % divisor
is false.
while (divisor <= limit && n % divisor != 0)
{
divisor += 2;
}
If the loop exits because a divisor was found, then false should be
returned.
if (n % divisor == 0)
{
return false;
}
else
{
return true;
}
This can be shorted considerably to
return ! (n % divisor = 0);
You should think about this; the expresion n % divisor == 0
is either true or false. If it is true, then n has
a divisor so IsPrime should return false. Hence the use of !. The
expression could be written as n % divisor != 0 but
this is hard to think about (at least for me it is).
if (abs(root*root - num) <= TOLERANCE)
{
//... code here
}
page 151
cout << "# of sides = " << tetra.mySides << endl;
The data field mySides is private and hence not
accessible to client (user) programs. The member function
NumSides() provides access to the value of the data. The
line
cout << "# of sides = " << tetra.NumSides() << endl;
will compile successfully.
int sides;
cout << "enter # of sides : ";
cin >> sides;
Dice die(sides);
// ... continue with program
The number of rolls can be entered as well, a loop is needed for this to work.
page 156
long int Factorial(int num)
// precondition: num >= 0
// postcondition returns num!
{
long int product = 1;
int count;
for(count=1; count <= num; count += 1) // invariant: product == (count-1)!
{
product *= count;
}
return product;
}
double total = 0.0;
double val = 1.0
while (val < 10000)
{
total += val;
val *= 1.5;
}
4.39
int sum = 0;
Dice die(12);
int k;
for(k=1; k <= num; k += 2)
{
sum += die.Roll();
}
page 167
int value = Power(base,expo-1);
return base * value;
In this case there is no base case for the chain of recursive
calls. A call of Power(3,4) to compute 3^4 will generate a
recursive call Power(3,3). This generates the chain of calls
Power(3,2) Power(3,1) Power(3,0) Power(3,-1) ...
and nothing (except running out of memory) will stop the chain from
being extended each time another call to Power is made.
25
625
15625
390625
9765625
244140625
3
9
27
81
243
729
2187
6561
19683
result = base^k
The first time the loop guard is evaulated this expression is true
because 1 = base^0 for any value of base.
Because both
result and k are upated each time the loop body is
executed, the relationship continues to hold. This is true since
k is incremented by 1 and the value of result is
multiplied by base.
result = base^expo
which is what should be returned.
cout << expo << endl
before the if
statement will generate the output below (one number per line) for the
call Power(2,14)
14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
The call Power(3,9) will generate the output below, again one
number per line.
9 8 7 6 5 4 3 2 1 0
Note that the output statement occurs before any recursive calls are
made.
if (1 == expo)
{
return base;
}
Reducing the number of multiplications by one isn't an important
savings in terms of efficiency. Using 24 instead of 25 multiplications
for 2^{25} won't save significant time, nor will reducing the number
even for ``large'' exponents like 1,000. For increased efficiency,
saving one multiplication isn't (usually) important. In the next
section a much more efficient method saves many more multiplications.
In general, ``optimizing'' a program with such small savings doesn't
make sense until it can be determined that the savings will accrue large
benefits. For example, if one billion powers were being calculated, the
savings would be beneficial.