Chapter 4 - Computation¶
Drill¶
- Write a program that consists of a
while
-loop that (each time around the loop) reads in twoint
s and then prints them. Exit the program when a terminating'|'
is entered.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include "std_lib_facilities.h"
int main() {
cout << "Enter two integer values separated by a space (followed by 'Enter'):\n";
int val1, val2;
while (cin >> val1 >> val2)
{
cout << val1 << '\t' << val2 << '\n';
}
return 0;
}
|
The input and output of this program is:
Enter two integer values seperated by a space (followed by 'Enter'):
1 2
1 2
2 1
2 1
3 5
3 5
|
Process finished with exit code 0
- Change the program to write out
the smaller value is:
followed by the smaller of the numbers andthe larger value is:
followed by the larger value.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include "std_lib_facilities.h"
int main() {
cout << "Enter two integer values separated by a space (followed by 'Enter'):\n";
int val1, val2;
while (cin >> val1 >> val2)
{
if (val1 < val2)
{
cout << "The smaller value is: " << val1 << '\n';
cout << "The larger value is: " << val2 << '\n';
}
else
{
cout << "The smaller value is: " << val2 << '\n';
cout << "The larger value is: " << val1 << '\n';
}
}
return 0;
}
|
Input and output of this program is:
Enter two integer values seperated by a space (followed by 'Enter'):
1 2
The smaller value is: 1
The larger value is: 2
3 2
The smaller value is: 2
The larger value is: 3
2 2
The smaller value is: 2
The larger value is: 2
^D
Notice that the output if the values are the same. The next drill handles the case if the two values are equal
- Augment the program so that it writes the line
the numbers are equal
(only) if they are equal.
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 | #include "std_lib_facilities.h"
int main() {
cout << "Enter two integer values separated by a space (followed by 'Enter'):\n";
int val1, val2;
while (cin >> val1 >> val2)
{
if (val1 == val2)
{
cout << "The numbers are equal.\n";
}
else if (val1 < val2)
{
cout << "The smaller value is: " << val1 << '\n';
cout << "The larger value is: " << val2 << '\n';
}
else
{
cout << "The smaller value is: " << val2 << '\n';
cout << "The larger value is: " << val1 << '\n';
}
}
return 0;
}
|
The output is:
Enter two integer values separated by a space (followed by 'Enter'):
1 2
The smaller value is: 1
The larger value is: 2
3 2
The smaller value is: 2
The larger value is: 3
1 5
The smaller value is: 1
The larger value is: 5
10 1
The smaller value is: 1
The larger value is: 10
5 5
The numbers are equal.
^D
- Change the program so that it uses
double
s instead ofint
s.
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 | #include "std_lib_facilities.h"
int main() {
cout << "Enter two double values separated by a space (followed by 'Enter'):\n";
double val1, val2;
while (cin >> val1 >> val2)
{
if (val1 == val2)
{
cout << "The numbers are equal.\n";
}
else if (val1 < val2)
{
cout << "The smaller value is: " << val1 << '\n';
cout << "The larger value is: " << val2 << '\n';
}
else
{
cout << "The smaller value is: " << val2 << '\n';
cout << "The larger value is: " << val1 << '\n';
}
}
return 0;
}
|
Example input and output:
Enter two double values separated by a space (followed by 'Enter'):
10.0 5.0
The smaller value is: 5
The larger value is: 10
2.0 6.0
The smaller value is: 2
The larger value is: 6
1 2
The smaller value is: 1
The larger value is: 2
2.0 2.0
The numbers are equal.
1 1
The numbers are equal.
1 1.0
The numbers are equal.
1 2.0
The smaller value is: 1
The larger value is: 2
^D
- Change the program so that it writes out
the numbers are almost equal
after writing out which is the larger and the smaller if the two numbers differ by less than 1.0/100.
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 | #include "std_lib_facilities.h"
int main() {
cout << "Enter two double values separated by a space (followed by 'Enter'):\n";
double val1, val2;
while (cin >> val1 >> val2)
{
if (val1 == val2)
{
cout << "The numbers are equal.\n";
}
else if (val1 < val2)
{
cout << "The smaller value is: " << val1 << '\n';
cout << "The larger value is: " << val2 << '\n';
}
else
{
cout << "The smaller value is: " << val2 << '\n';
cout << "The larger value is: " << val1 << '\n';
}
double diff = val1 - val2;
if (diff > 0 && diff < 1.0/100 || diff < 0 && diff > -1.0/100)
{
cout << "The numbers are almost equal.\n";
}
}
return 0;
}
|
Output for values that are similar:
Enter two double values separated by a space (followed by 'Enter'):
10.0 10.0
The numbers are equal.
10.0 11.0
The smaller value is: 10
The larger value is: 11
10.0 10.0001
The smaller value is: 10
The larger value is: 10.0001
The numbers are almost equal.
1.0 0.09
The smaller value is: 0.09
The larger value is: 1
1.0 0.99
The smaller value is: 0.99
The larger value is: 1
1.0 0.999
The smaller value is: 0.999
The larger value is: 1
The numbers are almost equal.
-1.0 -0.999
The smaller value is: -1
The larger value is: -0.999
The numbers are almost equal.
-1.0 -1.01
The smaller value is: -1.01
The larger value is: -1
-1.0 -1.001
The smaller value is: -1.001
The larger value is: -1
The numbers are almost equal.
-1.0 -1.002
The smaller value is: -1.002
The larger value is: -1
The numbers are almost equal.
1 1.001
The smaller value is: 1
The larger value is: 1.001
The numbers are almost equal.
- Now change the body of the loop so that it reads just one
double
each time around. Define two variables to keep track of which is the smallest and which is the largest value you have seen so far. Each time through the loop write out the value entered. If it’s the smallest so far, writethe smallest so far
after the number. If it is the largest so far, writethe largest so far
after the number.
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 | #include "std_lib_facilities.h"
int main() {
cout << "Enter a double value (followed by 'Enter'):\n";
bool first {true};
double val {0.0};
double smallest {0.0};
double largest {0.0};
string unit {" "};
while (cin >> val)
{
cout << val;
if (first == true)
{
first = false;
smallest = val;
largest = val;
cout << " is the first value and therefore the smallest and largest so far.\n";
}
else if (val < smallest)
{
cout << " the smallest so far.\n";
smallest = val;
}
else if (val > largest)
{
cout << " the largest so far.\n";
largest = val;
}
else
{
cout << '\n';
}
}
return 0;
}
|
The following are some inputs with the resulting output:
Enter a double value (followed by 'Enter'):
7
7 is the first value and therefore the smallest and largest so far.
5
5 the smallest so far.
8
8 the largest so far.
6
6
7
7
2
2 the smallest so far.
10
10 the largest so far.
- Add a unit to each
double
entered; that is, enter values such as10cm
,2.5in
,5ft
, or3.33m
. Accept the four units:cm
,m
,in
,ft
. Assume conversion factors1m == 100cm
,1in == 2.54cm
,1ft == 12in
. Read the unit indicator into a string. You may consider12 m
(with a space between the number and the unit) equivalent to12m
(without a space).
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 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 | #include "std_lib_facilities.h"
constexpr double cm_to_m {0.01};
constexpr double in_to_m {2.54*cm_to_m};
constexpr double ft_to_m {12.0*in_to_m};
const vector<string> legal_units {"cm", "m", "in", "ft"};
bool legalUnit(string unit)
{
bool legal = false;
for (auto legal_unit : legal_units)
{
if (unit == legal_unit)
{
legal = true;
}
}
return legal;
}
void printLegalUnits()
{
cout << "\tcm for centimeters\n"
<< "\tm for meters\n"
<< "\tin for inches\n"
<< "\tft for feet\n";
}
double convertToMeter(double val, string unit)
{
if ("cm" == unit)
{
return val * cm_to_m;
}
else if ("in" == unit)
{
return val * in_to_m;
}
else if ("ft" == unit)
{
return val * ft_to_m;
}
else {
return val;
}
}
int main() {
cout << "Enter a double value followed by a unit with or without a space in between (followed by 'Enter'):\n";
bool first {true};
double val {0.0};
double valMeter {0.0};
double smallest {0.0};
double largest {0.0};
string unit {" "};
printLegalUnits();
while (cin >> val >> unit)
{
if (legalUnit(unit))
{
valMeter = convertToMeter(val, unit);
cout << val << unit;
if (unit != "m")
{
cout << " (" << valMeter << "m)";
}
if (first == true)
{
first = false;
smallest = val;
largest = val;
cout << " is the first value and therefore the smallest and largest so far.\n";
}
else if (valMeter < smallest)
{
cout << " the smallest so far.\n";
smallest = valMeter;
}
else if (valMeter > largest)
{
cout << " the largest so far.\n";
largest = valMeter;
}
else
{
cout << '\n';
}
}
}
return 0;
}
|
Here is the output of the program after entering some values:
Enter a double value followed by a unit with or without a space in between (followed by 'Enter'):
cm for centimeters
m for meters
in for inches
ft for feet
5 m
5m is the first value and therefore the smallest and largest so far.
7 m
7m the largest so far.
3 m
3m the smallest so far.
4 m
4m
8 m
8m the largest so far.
6 m
6m
2 cm
2cm (0.02m) the smallest so far.
1 in
1in (0.0254m)
9 ft
9ft (2.7432m)
100 ft
100ft (30.48m) the largest so far.
1 y
1 m
1m
^D
On Mac Mojave I had to use spaces between the value and the unit. Otherwise cin
failed (returns false) and never enters
the while loop (this is a bug in libc++). Everything works on linux.
- Reject values without units or with “illegal” representations of units, such as
y
,yard
,meter
,km
, andgallons
.
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 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 | #include "std_lib_facilities.h"
constexpr double cm_to_m {0.01};
constexpr double in_to_m {2.54*cm_to_m};
constexpr double ft_to_m {12.0*in_to_m};
const vector<string> legal_units {"cm", "m", "in", "ft"};
bool legalUnit(string unit)
{
bool legal = false;
for (auto legal_unit : legal_units)
{
if (unit == legal_unit)
{
legal = true;
}
}
return legal;
}
void printLegalUnits()
{
cout << "\tcm for centimeters\n"
<< "\tm for meters\n"
<< "\tin for inches\n"
<< "\tft for feet\n";
}
double convertToMeter(double val, string unit)
{
if ("cm" == unit)
{
return val * cm_to_m;
}
else if ("in" == unit)
{
return val * in_to_m;
}
else if ("ft" == unit)
{
return val * ft_to_m;
}
else {
return val;
}
}
int main() {
cout << "Enter a double value followed by a unit with or without a space in between (followed by 'Enter'):\n";
bool first {true};
double val {0.0};
double valMeter {0.0};
double smallest {0.0};
double largest {0.0};
string unit {" "};
printLegalUnits();
while (cin >> val >> unit)
{
if (legalUnit(unit))
{
valMeter = convertToMeter(val, unit);
cout << val << unit;
if (unit != "m")
{
cout << " (" << valMeter << "m)";
}
if (first == true)
{
first = false;
smallest = val;
largest = val;
cout << " is the first value and therefore the smallest and largest so far.\n";
}
else if (valMeter < smallest)
{
cout << " the smallest so far.\n";
smallest = valMeter;
}
else if (valMeter > largest)
{
cout << " the largest so far.\n";
largest = valMeter;
}
else
{
cout << '\n';
}
}
else {
cout << "Error: no legal unit. Enter one of \n";
printLegalUnits();
}
}
return 0;
}
|
The output is:
Enter a double value followed by a unit with or without a space in between (followed by 'Enter'):
cm for centimeters
m for meters
in for inches
ft for feet
5 m
5m is the first value and therefore the smallest and largest so far.
7 m
7m the largest so far.
3 m
3m the smallest so far.
4 m
4m
2 cm
2cm (0.02m) the smallest so far.
9 cm
9cm (0.09m)
1 in
1in (0.0254m)
1 yard
Error: no legal unit. Enter one of
cm for centimeters
m for meters
in for inches
ft for feet
1 m
1m
^D
- Keep track of the sum of values entered (as well as the smallest and the largest) and the number of values entered. When the loop ends, print the smallest, the largest, the number of values, and the sum of values. Note that to keep the sum, you have to decide on a unit to use for that sum; use meters.
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 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 107 108 109 110 111 112 113 | #include "std_lib_facilities.h"
constexpr double cm_to_m {0.01};
constexpr double in_to_m {2.54*cm_to_m};
constexpr double ft_to_m {12.0*in_to_m};
const vector<string> legal_units {"cm", "m", "in", "ft"};
bool legalUnit(string unit)
{
bool legal = false;
for (auto legal_unit : legal_units)
{
if (unit == legal_unit)
{
legal = true;
}
}
return legal;
}
void printLegalUnits()
{
cout << "\tcm for centimeters\n"
<< "\tm for meters\n"
<< "\tin for inches\n"
<< "\tft for feet\n";
}
double convertToMeter(double val, string unit)
{
if ("cm" == unit)
{
return val * cm_to_m;
}
else if ("in" == unit)
{
return val * in_to_m;
}
else if ("ft" == unit)
{
return val * ft_to_m;
}
else {
return val;
}
}
int main() {
cout << "Enter a double value followed by a unit with or without a space in between (followed by 'Enter'):\n";
double val {0.0};
double valMeter {0.0};
double smallest {0.0};
double largest {0.0};
string unit {" "};
int count {0};
double sum {0.0};
printLegalUnits();
while (cin >> val >> unit)
{
if (legalUnit(unit))
{
valMeter = convertToMeter(val, unit);
cout << val << unit;
if (unit != "m")
{
cout << " (" << valMeter << "m)";
}
if (0 == count)
{
smallest = val;
largest = val;
cout << " is the first value and therefore the smallest and largest so far.\n";
}
else if (valMeter < smallest)
{
cout << " the smallest so far.\n";
smallest = valMeter;
}
else if (valMeter > largest)
{
cout << " the largest so far.\n";
largest = valMeter;
}
else
{
cout << '\n';
}
sum += valMeter;
count++;
}
else {
cout << "Error: no legal unit. Enter one of \n";
printLegalUnits();
}
}
cout << "The smallest: " << smallest << "m\n"
<< "The largest: " << largest << "m\n"
<< "Number of values entered: " << count << '\n'
<< "The sum of values: " << sum << "m\n";
return 0;
}
|
Enter a double value followed by a unit with or without a space in between (followed by 'Enter'):
cm for centimeters
m for meters
in for inches
ft for feet
5 m
5m is the first value and therefore the smallest and largest so far.
2 m
2m the smallest so far.
9 m
9m the largest so far.
2 ft
2ft (0.6096m) the smallest so far.
0.5 in
0.5in (0.0127m) the smallest so far.
100 yard
Error: no legal unit. Enter one of
cm for centimeters
m for meters
in for inches
ft for feet
2 gallons
Error: no legal unit. Enter one of
cm for centimeters
m for meters
in for inches
ft for feet
10 cm
10cm (0.1m)
|
The smallest: 0.0127m
The largest: 9m
Number of values entered: 6
The sum of values: 16.7223m
- Keep all the values entered (converted into meters) in a
vector
. At the end, write out those values.
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 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | #include "std_lib_facilities.h"
constexpr double cm_to_m {0.01};
constexpr double in_to_m {2.54*cm_to_m};
constexpr double ft_to_m {12.0*in_to_m};
const vector<string> legal_units {"cm", "m", "in", "ft"};
bool legalUnit(string unit)
{
bool legal = false;
for (auto legal_unit : legal_units)
{
if (unit == legal_unit)
{
legal = true;
}
}
return legal;
}
void printLegalUnits()
{
cout << "\tcm for centimeters\n"
<< "\tm for meters\n"
<< "\tin for inches\n"
<< "\tft for feet\n";
}
double convertToMeter(double val, string unit)
{
if ("cm" == unit)
{
return val * cm_to_m;
}
else if ("in" == unit)
{
return val * in_to_m;
}
else if ("ft" == unit)
{
return val * ft_to_m;
}
else {
return val;
}
}
int main() {
cout << "Enter a double value followed by a unit with or without a space in between (followed by 'Enter'):\n";
double val {0.0};
double valMeter {0.0};
double smallest {0.0};
double largest {0.0};
string unit {" "};
int count {0};
double sum {0.0};
vector<double> values(0);
printLegalUnits();
while (cin >> val >> unit)
{
if (legalUnit(unit))
{
valMeter = convertToMeter(val, unit);
cout << val << unit;
if (unit != "m")
{
cout << " (" << valMeter << "m)";
}
if (0 == count)
{
smallest = val;
largest = val;
cout << " is the first value and therefore the smallest and largest so far.\n";
}
else if (valMeter < smallest)
{
cout << " the smallest so far.\n";
smallest = valMeter;
}
else if (valMeter > largest)
{
cout << " the largest so far.\n";
largest = valMeter;
}
else
{
cout << '\n';
}
sum += valMeter;
values.push_back(valMeter);
count++;
}
else {
cout << "Error: no legal unit. Enter one of \n";
printLegalUnits();
}
}
cout << "The smallest: " << smallest << "m\n"
<< "The largest: " << largest << "m\n"
<< "Number of values entered: " << count << '\n'
<< "The sum of values: " << sum << "m\n";
cout << "The entered values: ";
for (auto value : values)
{
cout << value << " ";
}
cout << '\n';
return 0;
}
|
The output of this drill is:
Enter a double value followed by a unit with or without a space in between (followed by 'Enter'):
cm for centimeters
m for meters
in for inches
ft for feet
10 m
10m is the first value and therefore the smallest and largest so far.
8 m
8m the smallest so far.
3 m
3m the smallest so far.
5 m
5m
2 cm
2cm (0.02m) the smallest so far.
1 in
1in (0.0254m)
0.2 in
0.2in (0.00508m) the smallest so far.
100 ft
100ft (30.48m) the largest so far.
1 yard
Error: no legal unit. Enter one of
cm for centimeters
m for meters
in for inches
ft for feet
.2 cm
0.2cm (0.002m) the smallest so far.
|
The smallest: 0.002m
The largest: 30.48m
Number of values entered: 9
The sum of values: 56.5325m
The entered values: 10 8 3 5 0.02 0.0254 0.00508 30.48 0.002
- Before writing out the values from the
vector
, sort them (that’ll make them come out in increasing order).
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 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | #include "std_lib_facilities.h"
constexpr double cm_to_m {0.01};
constexpr double in_to_m {2.54*cm_to_m};
constexpr double ft_to_m {12.0*in_to_m};
const vector<string> legal_units {"cm", "m", "in", "ft"};
bool legalUnit(string unit)
{
bool legal = false;
for (auto legal_unit : legal_units)
{
if (unit == legal_unit)
{
legal = true;
}
}
return legal;
}
void printLegalUnits()
{
cout << "\tcm for centimeters\n"
<< "\tm for meters\n"
<< "\tin for inches\n"
<< "\tft for feet\n";
}
double convertToMeter(double val, string unit)
{
if ("cm" == unit)
{
return val * cm_to_m;
}
else if ("in" == unit)
{
return val * in_to_m;
}
else if ("ft" == unit)
{
return val * ft_to_m;
}
else {
return val;
}
}
int main() {
cout << "Enter a double value followed by a unit with or without a space in between (followed by 'Enter'):\n";
double val {0.0};
double valMeter {0.0};
double smallest {0.0};
double largest {0.0};
string unit {" "};
int count {0};
double sum {0.0};
vector<double> values(0);
printLegalUnits();
while (cin >> val >> unit)
{
if (legalUnit(unit))
{
valMeter = convertToMeter(val, unit);
cout << val << unit;
if (unit != "m")
{
cout << " (" << valMeter << "m)";
}
if (0 == count)
{
smallest = val;
largest = val;
cout << " is the first value and therefore the smallest and largest so far.\n";
}
else if (valMeter < smallest)
{
cout << " the smallest so far.\n";
smallest = valMeter;
}
else if (valMeter > largest)
{
cout << " the largest so far.\n";
largest = valMeter;
}
else
{
cout << '\n';
}
sum += valMeter;
values.push_back(valMeter);
count++;
}
else {
cout << "Error: no legal unit. Enter one of \n";
printLegalUnits();
}
}
cout << "The smallest: " << smallest << "m\n"
<< "The largest: " << largest << "m\n"
<< "Number of values entered: " << count << '\n'
<< "The sum of values: " << sum << "m\n";
sort(values);
cout << "The entered values in sorted order: ";
for (auto value : values)
{
cout << value << " ";
}
cout << '\n';
return 0;
}
|
Output for drill 11:
Enter a double value followed by a unit with or without a space in between (followed by 'Enter'):
cm for centimeters
m for meters
in for inches
ft for feet
8 m
8m is the first value and therefore the smallest and largest so far.
9 m
9m the largest so far.
5 m
5m the smallest so far.
2 cm
2cm (0.02m) the smallest so far.
1 in
1in (0.0254m)
0.1 in
0.1in (0.00254m) the smallest so far.
100 ft
100ft (30.48m) the largest so far.
2 yard
Error: no legal unit. Enter one of
cm for centimeters
m for meters
in for inches
ft for feet
6 cm
6cm (0.06m)
6 m
6m
|
The smallest: 0.00254m
The largest: 30.48m
Number of values entered: 9
The sum of values: 58.5879m
The entered values in sorted order: 0.00254 0.02 0.0254 0.06 5 6 8 9 30.48
Review¶
- What is a computation?
By computation we simply mean the act of producing some outputs based on some inputs,
such as producing the result (output) 49
from the argument (input) 7
using the computation (function) square
(see §4.5).
All that a program ever does is to compute; that is, it takes some inputs and produces some output. After all, we call the hardware on which we run the program a computer.
- What do we mean by inputs and outputs to a computation? Give examples.
When we say “input” and “output” we generally mean information coming into and out of a computer, but we can also use the terms for information given to or produced by a part of a program. Inputs to a part of a program are often called arguments and outputs from a part of a program are often called results.
By computation we simply mean the act of producing some outputs based on some inputs, such as producing the result (output) 49 from the argument (input) 7 using the computation (function) square (see §4.5).
- What are the three requirements a programmer should keep in mind when expressing computations?
Our job as programmers is to express computations
- Correctly
- Simply
- Efficiently
Please note the order of those ideals: it doesn’t matter how fast a program is if it gives the wrong results. Similarly, a correct and efficient program can be so complicated that it must be thrown away or completely rewritten to produce a new version (release). Remember, useful programs will always be modified to accommodate new needs, new hardware, etc. Therefore a program — and any part of a program — should be as simple as possible to perform its task.
- What does an expression do?
The most basic building block of programs is an expression.
An expression computes a value from a number of operands.
The simplest expression is simply a literal value, such as 10
, 'a'
, 3.14
, or "Norah"
.
Names of variables are also expressions. A variable represents the object of which it is the name.
- What is the difference between a statement and an expression, as described in this chapter?
An expression computes a value from a set of operands using operators like the ones mentioned in §4.3. To produce several values, do something many times, choose among alternatives, or if you want to get input or produce output, in C++, as in many languages, you use language constructs called statements to express those things.
Two kinds of statements are:
- expression statements
- declarations
An expression statement is simply an expression followed by a semicolon. For example:
a = b;
++b;
Those are two expression statements. Note that the assignment =
is an operator
so that a=b
is an expression and we need the terminating semicolon to make a=b;
a statement.
- What is an lvalue? List the operators that require an lvalue. Why do these operators, and not the others, require an lvalue?
An lvalue is an expression that identifies an object that could in principle be modified (but obviously an lvalue that has a const type is protected against modification by the type system) and have its address taken. The complement to lvalue is rvalue, that is, an expression that identifies something that may not be modified or have its address taken, such as a value returned from a function (&f(x) is an error because f(x) is an rvalue).
The following operators require an lvalue on the left han side because they may modify this value.
Assignments:
v=x;
v*=x;
v/=x;
v%=x
v+=x
v–=x
v>>=x
v<<=x
v&=x
v^=x
v|=x
Address of:
&v
(pre/post-)increment/decrement:
++v;
--v;
v++;
v--;
- What is a constant expression?
To handle cases where the value of a “variable” that is initialized with a value that
is not known at compile time but never changes after initialization, C++ offers a second form (beside constexpr
) of constant (a const
)
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
const int c2 = n+7; // OK, but don’t try to change the value of c2
// ...
c2 = 7; // error: c2 is a const
}
Such “const variables” are very common for two reasons:
- C++98 did not have constexpr, so people used const.
- “Variables” that are not constant expressions (their value is not known at compile time) but do not change values after initialization are in themselves widely useful.
- What is a literal?
Literals represent values of various types. For example, the literal 12
represents
the integer value “twelve”, "Morning"
represents the character string value Morning,
and true
represents the Boolean value true.
- What is a symbolic constant and why do we use them?
C++ offers the notion of a symbolic constant, that is, a named object to which you can’t give a new value after it has been initialized. For example:
constexpr double pi = 3.14159;
pi = 7; // error: assignment to constant
double c = 2*pi*r; // OK: we just read pi; we don’t try to change it
Such constants are useful for keeping code readable.
A constexpr symbolic constant must be given a value that is known at compile time.
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
constexpr int c2 = n+7; // error: we don’t know the value of c2
// ...
}
- What is a magic constant? Give examples.
Non-obvious literals in code (outside definitions of symbolic constants) are derisively referred to as magic constants. For example:
299792458 // fundamental onstant of the universe: speed of light in vacuum measured in meters per second
3.14159 // approximation to pi
Use constants with descriptive names and not use these magic constants (literals) directly in an expression.
- What are some operators that we can use for integers and floating-point values?
Name | Comment | |
---|---|---|
a+b |
add | |
a-b |
subtract | |
out<<b |
write b to out |
where out is an ostream |
in>>b |
read from in to b |
where in is an istream |
a<b |
less than | result is bool |
a<=b |
less than or equal | result is bool |
a>b |
greater than | result is bool |
a>=b |
greater than or equal | result is bool |
a==b |
equal | not to be confused with = |
a!=b |
not equal | result is bool |
a&&b |
logical and | result is bool |
a|a|b |
logical or | result is bool |
lval=a |
assignment | not to be confused with == |
lval*=a |
compound assignment | lval=lval*a ; also for / , % , + , - |
- What operators can be used on integers but not on floating-point numbers?
Name | Comment | |
---|---|---|
a%b |
modulo (remainder) | only for integer types |
- What are some operators that can be used for strings?
Name | Comment | |
---|---|---|
a+b |
add | |
out<<b |
write b to out |
where out is an ostream |
in>>b |
read from in to b |
where in is an istream |
a<b |
less than | result is bool |
a<=b |
less than or equal | result is bool |
a>b |
greater than | result is bool |
a>=b |
greater than or equal | result is bool |
a==b |
equal | not to be confused with = |
a!=b |
not equal | result is bool |
lval=a |
assignment | result is bool |
lval+=a |
compound assignment | lval=lval+a |
- When would a programmer prefer a
switch
-statement to anif
-statement?
A selection based on comparison of a value against several constants can be tedious to write using if
and else
statements. C++ offers a switch
-statement which is archaic but still clearer than nested if
-statements,
especially when we compare against many constants.
Here are some technical details about switch-statements:
- The value on which we switch must be of an integer,
char
, or enumeration (§9.5) type. In particular, you cannot switch on astring
. - The values in the case labels must be constant expressions (§4.3.1). In particular, you cannot use a variable in a case label.
- You cannot use the same value for two case labels.
- You can use several case labels for a single case.
- Don’t forget to end each case with a
break
. Unfortunately, the compiler probably won’t warn you if you forget.
- What are some common problems with
switch
-statements?
The most common error with switch
-statements is to forget to terminate a case
with a break
.
For example:
int main() // example of bad code (a break is missing)
{
constexpr double cm_per_inch = 2.54; // number of centimeters in // an inch
double length = 1; // length in inches or // centimeters
char unit = 'a';
cout << "Please enter a length followed by a unit (c or i):\n"; cin >> length >> unit;
switch (unit)
{
case 'i':
cout << length << "in == " << cm_per_inch*length << "cm\n";
case 'c':
cout << length << "cm == " << length/cm_per_inch << "in\n";
}
}
Unfortunately, the compiler will accept this, and when you have finished case 'i'
you’ll just “drop through”
into case 'c'
, so that if you enter 2i
the program will output
2in == 5.08cm
2cm == 0.787402in
To select based on string
you have to use an if
-statement or a map
.
int main() // you can switch only on integers, etc.
{
cout << "Do you like fish?\n";
string s;
cin >> s;
switch (s) // error: the value must be of integer, char, or enum type
{
case "no":
// ...
break;
case "yes":
// ...
break;
}
}
Case label values must be constants and distinct.
For example:
int main() // case labels must be constants
{
// define alternatives:
int y = 'y'; // this is going to cause trouble constexpr char n = 'n';
constexpr char m = '?';
cout << "Do you like fish?\n";
char a;
cin >> a;
switch (a) {
case n:
// ...
break;
case y: // error: variable in case label
// ...
break;
case m:
// . . .
break;
case 'n': // error: duplicate case label (n’s value is ‘n’)
// ...
break;
default:
// ...
break;
}
}
- What is the function of each part of the header line in a
for
-loop, and in what sequence are they executed?
A for
-statement is like a while
-statement except that the management of the control variable is concentrated
at the top where it is easy to see and understand.
For example:
// calculate and print a table of squares 0–99
int main()
{
for (int i = 0; i<100; ++i)
cout << i << '\t' << square(i) << '\n';
}
This means “Execute the body with i starting at 0 incrementing i after each execution of the body until we reach 100.” A for-statement is always equivalent to some while-statement. In this case
for (int i = 0; i<100; ++i)
cout << i << '\t' << square(i) << '\n';
means
{
int i = 0; // the for-statement initializer
while (i<100) { // the for-statement condition
cout << i << '\t' << square(i) << '\n'; // the for-statement body
++i; // the for-statement increment
}
}
Never modify the loop variable inside the body of a for
-statement. That would
violate every reader’s reasonable assumption about what a loop is doing.
- When should the
for
-loop be used and when should thewhile
-loop be used?
Some novices prefer while
-statements and some novices prefer for
-statements.
However, using a for
-statement yields more easily understood and more maintainable code
whenever a loop can be defined as a for
-statement with a simple initializer, condition, and increment operation.
Use a while
-statement only when that’s not the case.
- How do you print the numeric value of a
char
?
The value of a character, such as 'a'
for a
, is implementation dependent (but easily discovered, for example, cout << int('a')
).
- Describe what the line
char foo(int x)
means in a function definition.
The line of this definition tells us that this is a function (that’s what the parentheses mean),
that it is called foo
, that it takes an int
argument (here, called x
), and that it returns a char
(the type of the result always comes first in a function declaration);
- When should you define a separate function for part of a program? List reasons.
We define a function when we want a separate computation with a name because doing so
- Makes the computation logically separate
- Makes the program text clearer (by naming the computation)
- Makes it possible to use the function in more than one place in our program
- Eases testing
- What can you do to an
int
that you cannot do to astring
?
The following operators can be applied to an int
but not to a string
.
- What can you do to a
string
that you cannot do to anint
?
- What is the index of the third element of a
vector
?
The first element of a vector
has index 0, the second index 1, and so on.
We refer to an element by subscripting the name of the vector with the element’s index,
for example, v[0]
for the value of the first element, the value of v[1] yields the second element, and so on.
Indices for a vector always start with 0 and increase by 1. The index of the third element is therefore v[2]
.
vector<int> vec = {0, 1, 2};
int i3 = vec[2];
- How do you write a
for
-loop that prints every element of avector
?
To print every value of a vector, a range-based for
-loop can be used:
vector<int> vec = {0, 1, 2, 3, 4, 5};
for (auto element : vec)
{
cout << element;
}
A vector “knows” its size, so we can print the elements of a vector like this:
vector<int> v = {5, 7, 9, 4, 6, 8};
for (int i=0; i<v.size(); ++i)
cout << v[i] << '\n';
The call v.size()
gives the number of elements of the vector
called v
.
In general, v.size()
gives us the ability to access elements of a vector without accidentally referring to an element
outside the vector’s range. The range for a vector v
is [0:v. size())
.
That’s the mathematical notation for a half-open sequence of elements.
The first element of v
is v[0]
and the last v[v.size()–1]
. If v.size==0
, v
has no elements, that is,
v
is an empty vector.
This notion of half-open sequences is used throughout C++ and the C++ standard library (§17.3, §20.3).
The language takes advantage of the notion of a half-open sequence to provide a simple loop over all the elements of a sequence, such as the elements of a vector.
For example:
vector<int> v = {5, 7, 9, 4, 6, 8};
for (int x : v) // for each x in v
cout << x << '\n';
This is called a range-for-loop because the word range is often used to mean the same as “sequence of elements”.
We read for (int x : v)
as “for each int
x
in v
” and the meaning of the loop is exactly like the equivalent loop
over the subscripts [0:v.size())
.
We use the range-for
-loop for simple loops over all the elements of a sequence looking at one element at a time.
- What does
vector<char> alphabet(26);
do?
This initializes a vector that can hold 26 elements of type char
which are initialized to '\0'
, the null/empty char.
This defines a vector of a given size, 26 in this case, without specifying the element values.
In that case, we use the (n)
notation where n
is the number of elements, and the elements are given a default value
according to the element type.
For example:
vector<int> vi(6); // vector of 6 ints initialized to 0
vector<string> vs(4); // vector of 4 strings initialized to ""
- Describe what
push_back()
does to a vector.
The operation push_back()
adds a new element to a vector
.
The new element becomes the last element of the vector
.
For example:
vector<double> v; // start off empty; that is, v has no elements
v.push_back(2.7); // add an element with the value 2.7 at end (“the back”) of v
// v now has one element and v[0]==2.7
v.push_back(5.6); // add an element with the value 5.6 at end of v
// v now has two elements and v[1]==5.6
Note the syntax for a call of push_back()
. It is called a member function call;
push_back()
is a member function of vector
and must be called using this dot notation:
member-function-call:
object_name.member-function-name ( argument-list )
- What do vector’s member functions
begin()
,end()
, andsize()
do?
The member functions begin()
and end()
of a vector
return iterators, begin
and end
;
they identify the beginning and the end of the sequence. An STL sequence is what is usually called “half-open”;
that is, the element identified by begin is part of the sequence,
but the end iterator points one beyond the end of the sequence.
The usual mathematical notation for such sequences (ranges) is [begin:end)
.
An iterator is an object that identifies an element of a sequence.
The member function size()
returns the number of elements stored in a vector
.
The call v.size()
gives the number of elements of the vector called v
.
In general, v.size()
gives us the ability to access elements of a vector without accidentally referring to an element
outside the vector
’s range. The range for a vector
v
is [0:v.size())
.
That’s the mathematical notation for a half-open sequence of elements.
The first element of v
is v[0]
and the last v[v.size()–1]
.
If v.size==0
, v
has no elements, that is, v
is an empty vector
.
This notion of half-open sequences is used throughout C++ and the C++ standard library (§17.3, §20.3).
- What makes vector so popular/useful?
A vector
is similar to an array in C and other languages.
However, you need not specify the size (length) of a vector
in advance, and you can add as many elements as you like.
The C++ standard vector
has other useful properties.
- How do you sort the elements of a
vector
?
C++ offers a variant of the standard library sort
algorithm, sort()
:
vector<double> temps = {33.0, 23.9, 25.7, 21.2, 28.5, 19.8};
sort(temps); // modifies temps vector to be in sorted order
Terms¶
abstraction¶
Our main tool for organizing a program — and for organizing our thoughts as we program — is to break up a big computation into many little ones. This technique comes in two variations:
- Abstraction: Hide details that we don’t need to use a facility (“implementation details”)
behind a convenient and general interface. For example, rather than considering the details of how to sort a phone book
(thick books have been written about how to sort), we just call the sort algorithm from the C++ standard library.
sort()
is a variant (§21.9) of the standard library sort algorithm (§21.8, §B.5.4) defined instd_library.h
. Another example is the way we use computer memory. Direct use of memory can be quite messy, so we access it through typed and named variables (§3.2), standard libraryvectors
(§4.6, Chapters 17–19),maps
(Chapter 21), etc. - “Divide and conquer”: Here we take a large problem and divide it into several little ones. For example, if we need to build a dictionary, we can separate that job into three: read the data, sort the data, and output the data.
begin()
¶
The member functions begin()
and end()
of a vector
return iterators, begin
and end
;
they identify the beginning and the end of the sequence. An STL sequence is what is usually called “half-open”;
that is, the element identified by begin is part of the sequence, but the end iterator points one beyond the end of the sequence.
The usual mathematical notation for such sequences (ranges) is [begin:end)
.
An iterator is an object that identifies an element of a sequence.
computation¶
By computation we simply mean the act of producing some outputs based on some inputs,
such as producing the result (output) 49
from the argument (input) 7
using the computation (function) square
(see §4.5).
All that a program ever does is to compute; that is, it takes some inputs and produces some output. After all, we call the hardware on which we run the program a computer.
conditional statement¶
In programs, as in life, we often have to select among alternatives.
In C++, that is done using either an if
-statement or a switch
-statement.
The simplest form of selection is an if
-statement, which selects between two alternatives.
If its condition is true, the first statement is executed; otherwise, the second statement is.
A selection based on comparison of a value against several constants is so common that C++ provides a special statement for it:
the switch
-statement.
Conditional statements, conditional expressions and conditional constructs are features of a programming language, which perform different computations or actions depending on whether a programmer-specified boolean condition evaluates to true or false. This is always achieved by selectively altering the control flow based on some condition.
The ?:
construct is called an arithmetic if or a conditional expression.
The value of (a>=b)?a:b
is a
if a>=b
and b
otherwise. A conditional expression saves us from writing long-winded code like this:
int max(int a, int b) // max is global; a and b are local
{
int m; // m is local
if (a>=b)
m = a;
else
m = b;
return m;
}
Conditional expression:
x?y:z
If x
the result is y
; otherwise the result is z
.
declaration¶
All the information needed to call a function is in the first line of its definition. For example:
int square(int x)
Given that, we know enough to say
int x = square(44);
We don’t really need to look at the function body.
Almost all of the time, we are just interested in knowing how to call a function — seeing the definition would just be distracting. C++ provides a way of supplying that information separate from the complete function definition. It is called a function declaration:
int square(int); // declaration of square
double sqrt(double); // declaration of sqrt
Note the terminating semicolons. A semicolon is used in a function declaration instead of the body used in the corresponding function definition:
int square(int x) // definition of square
{
return x*x;
}
So, if you just want to use a function, you simply write — or more commonly #include
— its declaration.
The function definition can be elsewhere.
This distinction between declarations and definitions becomes essential in larger programs where we use declarations to keep most of the code out of sight to allow us to concentrate on a single part of a program at a time (§4.2).
definition¶
The syntax of a function definition can be described like this:
type identifi er ( parameter-list ) function-body
That is, a type (the return type), followed by an identifier (the name of the function),
followed by a list of parameters in parentheses, followed by the body of the
function (the statements to be executed). The list of arguments required by the
function is called a parameter list and its elements are called parameters (or formal
arguments). The list of parameters can be empty, and if we don’t want to return a
result we give void
(meaning “nothing”) as the return type. For example:
void write_sorry() // take no argument; return no value
{
cout << "Sorry\n";
}
divide and conquer¶
Our main tool for organizing a program — and for organizing our thoughts as we program — is to break up a big computation into many little ones. This technique comes in two variations:
- Abstraction: Hide details that we don’t need to use a facility (“implementation details”)
behind a convenient and general interface. For example, rather than considering the details of how to sort a phone book
(thick books have been written about how to sort), we just call the sort algorithm from the C++ standard library.
sort()
is a variant (§21.9) of the standard library sort algorithm (§21.8, §B.5.4) defined instd_library.h
. Another example is the way we use computer memory. Direct use of memory can be quite messy, so we access it through typed and named variables (§3.2), standard libraryvectors
(§4.6, Chapters 17–19),maps
(Chapter 21), etc. - “Divide and conquer”: Here we take a large problem and divide it into several little ones. For example, if we need to build a dictionary, we can separate that job into three: read the data, sort the data, and output the data.
else
¶
The simplest form of selection is an if
-statement, which selects between two alternatives.
For the second alternative the else
-statement is used.
For example:
int main()
{
int a = 0;
int b = 0;
cout << "Please enter two integers\n";
cin >> a >> b;
if (a<b) // condition
// 1st alternative (taken if condition is true):
cout << "max(" << a << "," << b <<") is " << b <<"\n";
else
// 2nd alternative (taken if condition is false):
cout << "max(" << a << "," << b <<") is " << a << "\n";
}
An if
-statement chooses between two alternatives. If its condition is true, the first statement is executed;
otherwise, the second statement is, which is defined by the else
statement.
The general form of an if
-statement is
if ( expression ) statement else statement
That is, an if
, followed by an expression in parentheses, followed by a statement, followed by an else
, followed by a statement.
It is also possible to combine two if
-statements: For that use an if
-statement as the else
part of an if
-statement:
if ( expression ) statement else if ( expression ) statement else statement
For our program that gives this structure:
if (unit == 'i')
... // 1st alternative
else if (unit == 'c')
... // 2nd alternative
else
... // 3rd alternative
In this way, we can write arbitrarily complex tests and associate a statement with each alternative.
end()
¶
The member functions begin()
and end()
of a vector
return iterators, begin
and end
;
they identify the beginning and the end of the sequence. An STL sequence is what is usually called “half-open”;
that is, the element identified by begin is part of the sequence,
but the end iterator points one beyond the end of the sequence.
The usual mathematical notation for such sequences (ranges) is [begin:end)
.
An iterator is an object that identifies an element of a sequence.
expression¶
The most basic building block of programs is an expression. An expression computes
a value from a number of operands. The simplest expression is simply a literal value, such as 10
, 'a'
, 3.14
, or "Norah"
.
Names of variables are also expressions. A variable represents the object of which it is the name.
for
-statement¶
Iterating over a sequence of numbers is so common that C++, like most other programming languages, has a special syntax for it.
A for
-statement is like a while
-statement except that the management of the control variable is concentrated at the top
where it is easy to see and understand.
For example:
// calculate and print a table of squares 0–99
int main()
{
for (int i = 0; i<100; ++i)
cout << i << '\t' << square(i) << '\n';
}
This means “Execute the body with i
starting at 0
incrementing i after each execution of the body until we reach 100
.”
A for
-statement is always equivalent to some while
-statement. The corresponding while
-statement would look like:
{
int i = 0; // the for-statement initializer
while (i<100) { // the for-statement condition
cout << i << '\t' << square(i) << '\n'; // the for-statement body
++i; // the for-statement increment
}
}
Using a for
-statement yields more easily understood and more maintainable code whenever a loop can be defined as a for
-statement
with a simple initializer, condition, and increment operation. Use a while
-statement only when that’s not the case.
Never modify the loop variable inside the body of a for
-statement.
That would violate every reader’s reasonable assumption about what a loop is doing.
range-for
-statement¶
The language takes advantage of the notion of a half-open sequence to provide a simple loop over all the elements of a sequence,
such as the elements of a vector
.
For example:
vector<int> v = {5, 7, 9, 4, 6, 8};
for (int x : v) // for each x in v
cout << x << '\n';
This is called a range-for
-loop because the word range is often used to mean the same as “sequence of elements”.
We read for (int x : v)
as “for each int
x
in v
” and the meaning of the loop is exactly like the equivalent loop over
the subscripts [0:v.size())
.
We use the range-for
-loop for simple loops over all the elements of a sequence looking at one element at a time.
More complicated loops, such as looking at every third element of a vector, looking at only the second half of a vector,
or comparing elements of two vectors, are usually better done using the more complicated and more general traditional for
-statement (§4.4.2.3).
function¶
A function is a named sequence of statements. A function can return a result (also called a return value).
The standard library provides a lot of useful functions, such as the square root function sqrt()
that we used in §3.4.
However, we write many functions ourselves.
Here is a plausible definition of square
:
int square(int x) // return the square of x
{
return x*x;
}
The first line of this definition tells us that this is a function (that’s what the parentheses mean), that it is called square
,
that it takes an int
argument (here, called x
), and that it returns an int
(the type of the result always comes first in a function declaration); that is, we can use it like this:
int main()
{
cout << square(2) << '\n'; // print 4
cout << square(10) << '\n'; // print 100
}
We don’t have to use the result of a function call, but we do have to give a function exactly the arguments it requires.
The function body is the block (§4.4.2.2) that actually does the work.
{
return x*x; // return the square of x
}
The syntax of a function definition can be described like this:
type identifi er ( parameter-list ) function-body
That is, a type (the return type), followed by an identifier (the name of the function), followed by a list of parameters in parentheses, followed by the body of the function (the statements to be executed). The list of arguments required by the function is called a parameter list and its elements are called parameters (or formal arguments). The list of parameters can be empty, and if we don’t want to return a result we give void (meaning “nothing”) as the return type.
For example:
void write_sorry() // take no argument; return no value
{
cout << "Sorry\n";
}
if
-statement¶
The simplest form of selection is an if
-statement, which selects between two alternatives.
For the second alternative the else
-statement is used.
For example:
int main()
{
int a = 0;
int b = 0;
cout << "Please enter two integers\n";
cin >> a >> b;
if (a<b) // condition
// 1st alternative (taken if condition is true):
cout << "max(" << a << "," << b <<") is " << b <<"\n";
else
// 2nd alternative (taken if condition is false):
cout << "max(" << a << "," << b <<") is " << a << "\n";
}
An if
-statement chooses between two alternatives. If its condition is true, the first statement is executed;
otherwise, the second statement is, which is defined by the else
statement.
The general form of an if
-statement is
if ( expression ) statement else statement
That is, an if
, followed by an expression in parentheses, followed by a statement, followed by an else
, followed by a statement.
It is also possible to combine two if
-statements: For that use an if
-statement as the else
part of an if
-statement:
if ( expression ) statement else if ( expression ) statement else statement
For our program that gives this structure:
if (unit == 'i')
... // 1st alternative
else if (unit == 'c')
... // 2nd alternative
else
... // 3rd alternative
In this way, we can write arbitrarily complex tests and associate a statement with each alternative.
increment¶
The increment operators a++
, ++a
, a+=n
is defined for types int
and double
to increment by one or n
respectively.
Incrementing a variable (that is, adding 1 to it) is so common in programs that C++ provides a special syntax for it.
For example:
++counter
means
counter = counter + 1
There are many other common ways of changing the value of a variable based on its current value. For example, we might like to add 7 to it, to subtract 9, or to multiply it by 2. Such operations are also supported directly by C++.
For example:
a += 7; // means a = a+7
b –= 9; // means b = b–9
c *= 2; // means c = c*2
In general, for any binary operator oper
, a oper= b
means a = a oper b
(§A.5).
For starters, that rule gives us operators +=
, –=
, *=
, /=
, and %=
.
This provides a pleasantly compact notation that directly reflects our ideas.
For example, in many application domains *=
and /=
are referred to as “scaling”.
input¶
From one point of view, all that a program ever does is to compute; that is, it takes some inputs and produces some output. After all, we call the hardware on which we run the program a computer. This view is accurate and reasonable as long as we take a broad view of what constitutes input and output.
The input can come from a keyboard, from a mouse, from a touch screen, from files, from other input devices, from other programs, from other parts of a program. “Other input devices” is a category that contains most really interesting input sources: music keyboards, video recorders, network connections, temperature sensors, digital camera image sensors, etc. The variety is essentially infinite. To deal with input, a program usually contains some data, sometimes referred to as its data structures or its state.
When we say “input” and “output” we generally mean information coming into and out of a computer,
but the terms can also be used for information given to or produced by a part of a program.
Inputs to a part of a program are often called arguments and outputs from a part of a program are often called results.
By computation we simply mean the act of producing some outputs based on some inputs,
such as producing the result (output) 49
from the argument (input) 7
using the computation (function) square
(see §4.5).
iteration¶
Programming languages provide convenient ways of doing something several times. This is called repetition or — especially when you do something to a series of elements of a data structure — iteration.
loop¶
In C++ a loop can be a while
-statement or a for
-statement. These statements are ways to repeat some statement (to loop).
For this we need:
- A variable to keep track of how many times we have been through the loop (a loop variable or a control variable),
for example the
int
calledi
- An initializer for the loop variable, for example
int i = 0
- A termination criterion, for example that we want to go through the loop 100 times
- Something to do each time around the loop (the body of the loop)
For example:
while (i<100) // the loop condition testing the loop variable i
{
cout << i << '\t' << square(i) << '\n';
++i ; // increment the loop variable i
}
lvalue¶
It is a value that points to a storage location, potentially allowing new values to be assigned (so named because it appears on the left side of a variable assignment).
An lvalue is an expression that identifies an object that could in principle be modified (but obviously an lvalue that has a const type is protected against modification by the type system) and have its address taken.
member function¶
A member function is part of an object (class or struct) and must be called using this dot notation:
member-function-call:
object_name.member-function-name ( argument-list )
For example, push_back()
is a member functions of a vector
to add elements. The size can be obtain by a call
to another of vector
’s member functions: size()
. A vector
initialized with no elements, v.size()
is 0
, and after the third call of push_back()
, v.size()
becomes 3
.
output¶
From one point of view, all that a program ever does is to compute; that is, it takes some inputs and produces some output. Input comes from a wide variety of sources. Similarly, output can go to a wide variety of destinations. Output can be to a screen, to files, to network connections, to other output devices, to other programs, and to other parts of a program. Examples of output devices include network interfaces, music synthesizers, electric motors, light generators, heaters, etc.
push_back()
¶
Often, we start a vector empty and grow it to its desired size as we read or compute the data we want in it.
The key operation here is push_back()
, which adds a new element to a vector.
The new element becomes the last element of the vector.
For example:
vector<double> v; // start off empty; that is, v has no elements
v.push_back(2.7); //add an element with the value 2.7 at end (“theback”) of v
// v now has one element and v[0]==2.7
v.push_back(5.6); // add an element with the value 5.6 at end of v
// v now has two elements and v[1]==5.6
v.push_back(7.9); // add an element with the value 7.9 at end of v
// v now has three elements and v[2]==7.9
Note the syntax for a call of push_back()
. It is called a member function call;
push_back()
is a member function of vector
and must be called using this dot notation:
member-function-call:
object_name.member-function-name ( argument-list )
repetition¶
We rarely do something only once. Therefore, programming languages provide convenient ways of doing something several times. This is called repetition or — especially when you do something to a series of elements of a data structure — iteration.
To do something repeatedly we need
- A way to repeat some statement (to loop)
- A variable to keep track of how many times we have been through the loop (a loop variable or a control variable), here the int called i
- An initializer for the loop variable, here 0
- A termination criterion, here that we want to go through the loop 100 times
- Something to do each time around the loop (the body of the loop)
The language construct in C++ to repeat something is called a while
-statement or a for
-statement.
while (i<100) // the loop condition testing the loop variable i
{
cout << i << '\t' << square(i) << '\n';
++i ; // increment the loop variable i
}
Iterating over a sequence of numbers is so common that C++, like most other programming languages,
has a special syntax for it. A for
-statement is like a while
-statement except that the management of
the control variable is concentrated at the top where it is easy to see and understand.
For example:
// calculate and print a table of squares 0–99
int main()
{
for (int i = 0; i<100; ++i)
cout << i << '\t' << square(i) << '\n';
}
This means “Execute the body with i
starting at 0
incrementing i
after each execution of the body until we reach 100
.”
A for
-statement is always equivalent to some while
-statement.
rvalue¶
In computer science, a value considered independently of its storage location. The address of an rvalue may not be taken. An rvalue can’t be used as the left-hand operand of the built-in assignment or compound assignment operators.
Consider
length = 99; // assign 99 to length
We distinguish between length
used on the left-hand side of an assignment or an initialization
(“the lvalue of length
” or “the object named by length
”) and length
used on the right-hand side of an assignment or initialization (“the rvalue of length
,” “the value of the object named by length,” or just “the value of length”).
selection¶
In programs, as in life, we often have to select among alternatives.
In C++, that is done using either an if
-statement or a switch
-statement.
size()
¶
The size of a vector can be obtained by a call to one of vector’s member functions: size()
.
v.size()
is 0
for a vector
v
that has initially no elements.
After the third call of push_back()
, v.size()
becomes 3
.
sort()
¶
C++ offers a variant of the standard library sort
algorithm, sort()
:
vector<double> temps = {33.0, 23.9, 25.7, 21.2, 28.5, 19.8};
sort(temps); // modifies temps vector to be in sorted order
It is used to sort a sequence of elements.
statement¶
An expression computes a value from a set of operands using operators like the ones mentioned in §4.3. To produce several values, do something many times, choose among alternatives, or if you want to get input or produce output, in C++, as in many languages, you use language constructs called statements to express those things.
Two kinds of statements are:
- expression statements
- declarations
An expression statement is simply an expression followed by a semicolon. For example:
a = b;
++b;
Those are two expression statements. Note that the assignment =
is an operator
so that a=b
is an expression and we need the terminating semicolon to make a=b;
a statement.
switch
-statement¶
A selection based on comparison of a value against several constants can be tedious to write using if
and else
statements. C++ offers a switch
-statement which is archaic but still clearer than nested if
-statements,
especially when we compare against many constants.
To select based on a string
you have to use an if
-statement or a map
(Chapter 21).
A switch
-statement generates optimized code for comparing against a set of constants.
For larger sets of constants, this typically yields more efficient code than a collection of if
-statements.
However, this means that the case label values must be constants and distinct.
Often you want the same action for a set of values in a switch. It would be tedious to repeat the action so you can label a single action by a set of case labels.
The most common error with switch-statements is to forget to terminate a case with a break.
Here are some technical details about switch-statements:
- The value on which we switch must be of an integer,
char
, or enumeration (§9.5) type. In particular, you cannot switch on astring
. - The values in the case labels must be constant expressions (§4.3.1). In particular, you cannot use a variable in a case label.
- You cannot use the same value for two case labels.
- You can use several case labels for a single case.
- Don’t forget to end each case with a
break
. Unfortunately, the compiler probably won’t warn you if you forget.
vector
¶
To store a collection of data and to work on it a vector
can be used.
It is a data structure that is simply a sequence of elements that you can access by an index.
That is, the first element has index 0, the second index 1, and so on.
We refer to an element by subscripting the name of the vector with the element’s index,
so the value of the first element can be obtained with v[0]
, the value of the second element with v[1]
, and so on.
Indices for a vector
always start with 0 and increase by 1.
A vector doesn’t just store its elements, it also stores its size. The size can be obtained with its member function size()
.
We could make such a vector
like this:
vector<int> v = {5, 7, 9, 4, 6, 8}; // vector of 6 ints
We see that to make a vector
we need to specify the type of the elements and the initial set of elements.
The element type comes after vector
in angle brackets (<
>
), here <int>
.
We can also define a vector of a given size without specifying the element values.
In that case, we use the (n)
notation where n
is the number of elements,
and the elements are given a default value according to the element type.
For example:
vector<int> vi(6); // vector of 6 ints initialized to 0
vector<string> vs(4); // vector of 4 strings initialized to ""
Traversing a vector:¶
A vector “knows” its size, so we can print the elements of a vector like this:
vector<int> v = {5, 7, 9, 4, 6, 8};
for (int i=0; i<v.size(); ++i)
cout << v[i] << '\n';
The call v.size()
gives the number of elements of the vector
called v
.
In general, v.size()
gives us the ability to access elements of a vector
without accidentally referring to an element
outside the vector’s range. The range for a vector
v
is [0:v.size())
.
That’s the mathematical notation for a half-open sequence of elements.
The first element of v
is v[0]
and the last v[v.size()–1]
. If v.size==0
, v
has no elements, that is,
v
is an empty vector
.
This notion of half-open sequences is used throughout C++ and the C++ standard library (§17.3, §20.3).
The language takes advantage of the notion of a half-open sequence to provide a simple loop over all the elements of a
sequence, such as the elements of a vector
.
For example:
vector<int> v = {5, 7, 9, 4, 6, 8};
for (int x : v) // for each x in v
cout << x << '\n';
This is called a range-for
-loop because the word range is often used to mean the same as “sequence of elements”.
Growing a vector
¶
Often, we start a vector
empty and grow it to its desired size as we read or compute the data we want in it.
The key operation here is push_back()
, which adds a new element to a vector.
The new element becomes the last element of the vector.
For example:
vector<double> v; // start off empty; that is, v has no elements
v.push_back(2.7); //add an element with the value 2.7 at end (“theback”) of v
// v now has one element and v[0]==2.7
v.push_back(5.6); // add an element with the value 5.6 at end of v
// v now has two elements and v[1]==5.6
v.push_back(7.9); // add an element with the value 7.9 at end of v
// v now has three elements and v[2]==7.9
If you have programmed before, you will note that a vector
is similar to an array in C and other languages.
However, you need not specify the size (length) of a vector
in advance, and you can add as many elements as you like.
As we go along, you’ll find that the C++ standard vector
has other useful properties.
while
-statement¶
We rarely do something only once. Therefore, programming languages provide convenient ways of doing something several times. This is called repetition or — especially when you do something to a series of elements of a data structure — iteration.
To do this, C++ provides a while
-statement and a for
-statement.
For example:
// calculate and print a table of squares 0–99
int main()
{
int i = 0; // start from 0
while (i<100) {
cout << i << '\t' << square(i) << '\n';
++i; // increment i (that is, i becomes i+1)
}
}
Clearly, to do this we need
- A way to repeat some statement (to loop)
- A variable to keep track of how many times we have been through the loop (a loop variable or a control variable), here the int called i
- An initializer for the loop variable, here 0
- A termination criterion, here that we want to go through the loop 100 times
- Something to do each time around the loop (the body of the loop)
The language construct we used is called a while
-statement.
Just following its distinguishing keyword, while
, it has a condition “on top” followed by its body:
while (i<100) // the loop condition testing the loop variable i
{
cout << i << '\t' << square(i) << '\n';
++i ; // increment the loop variable i
}
The loop body is a block (delimited by curly braces) that writes out a row of the table and increments the loop variable, i
.
We start each pass through the loop by testing if i<100
. If so, we are not yet finished and we can execute the loop body.
If we have reached the end, that is, if i
is 100
, we leave the while
-statement and execute what comes next.
In this program the end of the program is next, so we leave the program.
The loop variable for a while
-statement must be defined and initialized outside (before) the while
-statement.
Try This¶
Currency Converter¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // convert from inches to centimeters or centimeters to inches
// a suffix ‘i’ or ‘c’ indicates the unit of the input
// any other suffix is an error
#include "std_lib_facilities.h"
int main()
{
constexpr double cm_per_inch = 2.54; // number of centimeters in an inch
double length = 1; // length in inches or centimeters
char unit = ' '; // a space is not a unit
cout<< "Please enter a length followed by a unit (c or i):\n";
cin >> length >> unit;
if (unit == 'i')
cout << length << "in == " << cm_per_inch*length << "cm\n";
else if (unit == 'c')
cout << length << "cm == " << length/cm_per_inch << "in\n";
else
cout << "Sorry, I don't know a unit called '" << unit << "'\n";
return 0;
}
|
Output of the cm to inch converter:
Please enter a length followed by a unit (c or i):
1 c
1cm == 0.393701in
And the output when converting inch to cm:
Please enter a length followed by a unit (c or i):
1 i
1in == 2.54cm
Use the example above as a model for a program that converts yen, euros, and pounds into dollars. If you like realism, you can find conversion rates on the web.
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 | // converts yen, euros, and pounds into dollars
// a suffix ‘y’, ‘e’ or 'p' indicates the currency of the input
// any other suffix is an error
#include "std_lib_facilities.h"
int main()
{
constexpr double yens_per_dollar = 106.36; // number of yen in a dollar
constexpr double euros_per_dollar = 0.91; // number of euro in a dollar
constexpr double pounds_per_dollar = 0.82; // number of pounds in a dollar
double amount = 1.0; // amount entered by the user (unit is yen, euro or pound)
char currency = ' '; // a space is not a currency
cout<< "Please enter an amount followed by a currency (y, e or p):\n";
cin >> amount >> currency;
if ('y' == currency)
cout << amount << "yen == " << amount / yens_per_dollar << "dollar\n";
else if ('e' == currency)
cout << amount << "euro == " << amount / euros_per_dollar << "dollar\n";
else if ('p' == currency)
cout << amount << "pound == " << amount / pounds_per_dollar << "dollar\n";
else
cout << "Sorry, I don't know a currency called '" << currency << "'\n";
return 0;
}
|
Here are some example inputs and their resulting output:
Please enter an amount followed by a currency (y, e or p):
1 y
1yen == 0.00940203dollar
Please enter an amount followed by a currency (y, e or p):
1 e
1euro == 1.0989dollar
Please enter an amount followed by a currency (y, e or p):
1 p
1pound == 1.21951dollar
Currency Converter switch
¶
Rewrite your currency converter program from the previous Try this to use a switch-statement. Add conversions from yuan and kroner. Which version of the program is easier to write, understand, and modify? Why?
Output of the currency converter program using switch statement:
Please enter an amount followed by a currency (y, e or p):
1 u
1yuan == 0.139665dollar
This version of the currency converter program is easier to write and understand than the version using if statements. However, using switch-statement it is not possible to compare strings. For this example is was necessary to use the character ‘u’ for yuan because ‘y’ was already taken for yen.
Character Loop¶
The character 'b'
is char('a'+1)
, 'c'
is char('a'+2)
, etc.
Use a loop to write out a table of characters with their corresponding integer values:
a 97
b 98
.. .
z 122
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include "std_lib_facilities.h"
int main()
{
int i = 0;
while (i<26) // the loop condition testing the loop variable i
{
int val = 'a' + i;
cout << char(val) << '\t' << int(val) << '\n';
++i ; // increment the loop variable i
}
return 0;
}
|
The result is:
a 97
b 98
c 99
d 100
e 101
f 102
g 103
h 104
i 105
j 106
k 107
l 108
m 109
n 110
o 111
p 112
q 113
r 114
s 115
t 116
u 117
v 118
w 119
x 120
y 121
z 122
Character Loop for
¶
Rewrite the character value example from the previous Try this to use a for
-statement.
Then modify your program to also write out a table of the integer values for uppercase letters and digits.
This program yields the same result as the previous one using the while loop:
a 97
b 98
c 99
d 100
e 101
f 102
g 103
h 104
i 105
j 106
k 107
l 108
m 109
n 110
o 111
p 112
q 113
r 114
s 115
t 116
u 117
v 118
w 119
x 120
y 121
z 122
The output of the extended version is:
a 97 A 65
b 98 B 66
c 99 C 67
d 100 D 68
e 101 E 69
f 102 F 70
g 103 G 71
h 104 H 72
i 105 I 73
j 106 J 74
k 107 K 75
l 108 L 76
m 109 M 77
n 110 N 78
o 111 O 79
p 112 P 80
q 113 Q 81
r 114 R 82
s 115 S 83
t 116 T 84
u 117 U 85
v 118 V 86
w 119 W 87
x 120 X 88
y 121 Y 89
z 122 Z 90
Square¶
Implement square()
without using the multiplication operator;
that is, do the x*x
by repeated addition (start a variable result at 0
and add x
to it x
times).
Then run some version of “the first program” using that square()
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include "std_lib_facilities.h"
int square(int x)
{
int result = 0;
for (int i = 0; i < x; ++i)
{
result += x;
}
return result;
}
int main()
{
for (int i = 0; i<100; ++i)
cout << i << '\t' << square(i) << '\n';
return 0;
}
|
The output of the program of the first few lines is:
0 0
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
...
Bleep¶
Write a program that “bleeps” out words that you don’t like;
that is, you read in words using cin and print them again on cout.
If a word is among a few you have defined, you write out BLEEP
instead of that word.
Start with one “disliked word” such as
string disliked = “Broccoli”;
When that works, add a few more.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include "std_lib_facilities.h"
int main()
{
string disliked = "Broccoli";
for (string temp; cin>>temp; ) // read
{
if (disliked != temp)
cout << temp << '\n';
else
cout << "BLEEP" << '\n';
}
return 0;
}
|
This program outputs:
Tomato
Tomato
Apple
Apple
Lemon
Lemon
Broccoli
BLEEP
^D
The extended program uses more disliked words:
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 | #include "std_lib_facilities.h"
int main()
{
vector<string> dislikedVector = {"Broccoli", "Puree", "Cauliflower", "Cabbage"};
bool disliked = false;
for (string temp; cin>>temp; ) // read
{
for (auto word : dislikedVector)
{
if (word == temp)
{
disliked = true;
break;
}
}
if (disliked)
cout << "BLEEP" << '\n';
else
cout << temp << '\n';
disliked = false;
}
return 0;
}
|
It outputs:
Broccoli
BLEEP
Apple
Apple
Cauliflower
BLEEP
Lemon
Lemon
Exercises¶
Exercise 02¶
If we define the median of a sequence as “a number so that exactly as many elements come before it in the sequence as come after it” fix the program in §4.6.3 so that it always prints out a median. Hint: A median need not be an element of the sequence.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include "std_lib_facilities.h"
// compute median temperatures int
int main()
{
cout << "Enter a series of temperatures to get the median (followed by '|' or a another non double/integer character):\n";
vector<double> temps; // temperatures
for (double temp; cin>>temp; ) // read into temp
temps.push_back(temp); // put temp into vector
// compute mean temperature:
double sum = 0;
for (double x : temps) sum += x;
cout << "Average temperature: " << sum/temps.size() << '\n';
// compute median temperature:
sort(temps); // sort temperatures
cout << "Median temperature: " << temps[temps.size()/2] << '\n';
return 0;
}
|
Here are two example inputs to the mean and median program:
Enter a series of temperatures to get the median (followed by '|' or a another non double/integer character):
1 2 3 4 5 |
Average temperature: 3
Median temperature: 3
Enter a series of temperatures to get the median (followed by '|' or a another non double/integer character):
1 2 3 4 |
Average temperature: 2.5
Median temperature: 3
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 | #include "std_lib_facilities.h"
// compute median temperatures int
int main()
{
cout << "Enter a series of temperatures to get the median (followed by '|' or a another non double/integer character):\n";
vector<double> temps; // temperatures
for (double temp; cin>>temp; ) // read into temp
temps.push_back(temp); // put temp into vector
// compute mean temperature:
double sum = 0;
for (double x : temps) sum += x;
cout << "Average temperature: " << sum/temps.size() << '\n';
// compute median temperature:
sort(temps); // sort temperatures
double median = -1;
if (temps.size() > 1 && 0 == temps.size() % 2)
median = (temps[temps.size()/2 - 1] + temps[temps.size()/2]) / 2.0;
else
median = temps[temps.size()/2];
cout << "Median temperature: " << median << '\n';
return 0;
}
|
The following to inputs are the same as for the previous program. Notice that the second input is different this time, because the median computation is changed.
Enter a series of temperatures to get the median (followed by '|' or a another non double/integer character):
1 2 3 4 5 |
Average temperature: 3
Median temperature: 3
Enter a series of temperatures to get the median (followed by '|' or a another non double/integer character):
1 2 3 4 |
Average temperature: 2.5
Median temperature: 2.5
Exercise 03¶
Read a sequence of double values into a vector. Think of each value as the distance between two cities along a given route. Compute and print the total distance (the sum of all distances). Find and print the smallest and greatest distance between two neighboring cities. Find and print the mean distance between two neighboring cities.
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 | #include "std_lib_facilities.h"
// City distances
int main()
{
cout << "Enter a series of double values, which represent the distance between two cities\n"
"(followed by '|' or a another non double/integer character):\n";
vector<double> distances; // city distances
for (double distance; cin >> distance; ) // read into distance
distances.push_back(distance); // put distance into vector
// compute total distance:
double sum {0.0};
for (double distance : distances)
sum += distance;
cout << "Total distance: " << sum << '\n';
// compute smallest and largest distance:
sort(distances); // sort distances
cout << "Smallest distance: " << distances[0] << '\n'
<< "Largest distance: " << distances[distances.size()-1] << '\n';
cout << "The mean distance between two cities is: " << sum/distances.size() << '\n';
return 0;
}
|
Here is the output of the program:
Enter a series of double values, which represent the distance between two cities
(followed by '|' or a another non double/integer character):
1.0 2.0 0.5 10 50.2 30.8 22.1 |
Total distance: 116.6
Smallest distance: 0.5
Largest distance: 50.2
The mean distance between two cities is: 16.6571
Exercise 04¶
Write a program to play a numbers guessing game.
The user thinks of a number between 1 and 100 and your program asks questions to figure out what the number is
(e.g., “Is the number you are thinking of less than 50?”).
Your program should be able to identify the number after asking no more than seven questions.
Hint: Use the <
and <=
operators and the if
-else
construct.
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 52 53 54 55 56 57 58 59 60 | #include "std_lib_facilities.h"
// Number guessing game
int main()
{
int number {50};
// define upper and lower bounds
int upper {100};
int lower {1};
int range {upper - lower};
int half {range/2};
char answer {'\0'};
int question {0};
cout << "Think of a number between " << lower << " and " << upper << "\n\n";
while (lower != upper)
{
range = upper - lower;
if (range == 1 && number < half)
{
number = upper;
}
else if (range == 1 && number > half)
{
number = upper;
}
else
number = lower + range/2;
//cout << "upper: " << upper << " lower: " << lower << " range: " << range << '\n';
cout << question + 1 << ". Is the number you are thinking of less than " << number << "? (Enter 'y' or 'n') \n";
cin >> answer;
if ('y' == answer)
{
upper = number-1;
question++;
} else if ('n' == answer) {
lower = number;
question++;
} else {
cout << "Please enter 'y' or 'n' ...\n";
}
//cout << "upper: " << upper << " lower: " << lower << " range: " << range << '\n';
}
cout << "The number you are thinking of is " << lower << "\n";
cout << "I needed " << question << " guesses.\n";
return 0;
}
|
When I think of 100 the result is:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
n
2. Is the number you are thinking of less than 75? (Enter 'y' or 'n')
n
3. Is the number you are thinking of less than 87? (Enter 'y' or 'n')
n
4. Is the number you are thinking of less than 93? (Enter 'y' or 'n')
n
5. Is the number you are thinking of less than 96? (Enter 'y' or 'n')
n
6. Is the number you are thinking of less than 98? (Enter 'y' or 'n')
n
7. Is the number you are thinking of less than 99? (Enter 'y' or 'n')
n
8. Is the number you are thinking of less than 100? (Enter 'y' or 'n')
n
The number you are thinking of is 100
I needed 8 guesses.
Example with 99:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
n
2. Is the number you are thinking of less than 75? (Enter 'y' or 'n')
n
3. Is the number you are thinking of less than 87? (Enter 'y' or 'n')
n
4. Is the number you are thinking of less than 93? (Enter 'y' or 'n')
n
5. Is the number you are thinking of less than 96? (Enter 'y' or 'n')
n
6. Is the number you are thinking of less than 98? (Enter 'y' or 'n')
n
7. Is the number you are thinking of less than 99? (Enter 'y' or 'n')
n
8. Is the number you are thinking of less than 100? (Enter 'y' or 'n')
y
The number you are thinking of is 99
I needed 8 guesses.
Example with 98:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
n
2. Is the number you are thinking of less than 75? (Enter 'y' or 'n')
n
3. Is the number you are thinking of less than 87? (Enter 'y' or 'n')
n
4. Is the number you are thinking of less than 93? (Enter 'y' or 'n')
n
5. Is the number you are thinking of less than 96? (Enter 'y' or 'n')
n
6. Is the number you are thinking of less than 98? (Enter 'y' or 'n')
n
7. Is the number you are thinking of less than 99? (Enter 'y' or 'n')
y
The number you are thinking of is 98
I needed 7 guesses.
Example with 1:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
y
2. Is the number you are thinking of less than 25? (Enter 'y' or 'n')
y
3. Is the number you are thinking of less than 12? (Enter 'y' or 'n')
y
4. Is the number you are thinking of less than 6? (Enter 'y' or 'n')
y
5. Is the number you are thinking of less than 3? (Enter 'y' or 'n')
y
6. Is the number you are thinking of less than 2? (Enter 'y' or 'n')
y
The number you are thinking of is 1
I needed 6 guesses.
Example with 2:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
y
2. Is the number you are thinking of less than 25? (Enter 'y' or 'n')
y
3. Is the number you are thinking of less than 12? (Enter 'y' or 'n')
y
4. Is the number you are thinking of less than 6? (Enter 'y' or 'n')
y
5. Is the number you are thinking of less than 3? (Enter 'y' or 'n')
y
6. Is the number you are thinking of less than 2? (Enter 'y' or 'n')
n
The number you are thinking of is 2
I needed 6 guesses.
Example with 3:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
y
2. Is the number you are thinking of less than 25? (Enter 'y' or 'n')
y
3. Is the number you are thinking of less than 12? (Enter 'y' or 'n')
y
4. Is the number you are thinking of less than 6? (Enter 'y' or 'n')
y
5. Is the number you are thinking of less than 3? (Enter 'y' or 'n')
n
6. Is the number you are thinking of less than 4? (Enter 'y' or 'n')
y
The number you are thinking of is 3
I needed 6 guesses.
Example with 50:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
n
2. Is the number you are thinking of less than 75? (Enter 'y' or 'n')
y
3. Is the number you are thinking of less than 62? (Enter 'y' or 'n')
y
4. Is the number you are thinking of less than 55? (Enter 'y' or 'n')
y
5. Is the number you are thinking of less than 52? (Enter 'y' or 'n')
y
6. Is the number you are thinking of less than 51? (Enter 'y' or 'n')
y
The number you are thinking of is 50
I needed 6 guesses.
Example with 49:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
y
2. Is the number you are thinking of less than 25? (Enter 'y' or 'n')
n
3. Is the number you are thinking of less than 37? (Enter 'y' or 'n')
n
4. Is the number you are thinking of less than 43? (Enter 'y' or 'n')
n
5. Is the number you are thinking of less than 46? (Enter 'y' or 'n')
n
6. Is the number you are thinking of less than 47? (Enter 'y' or 'n')
n
7. Is the number you are thinking of less than 48? (Enter 'y' or 'n')
n
8. Is the number you are thinking of less than 49? (Enter 'y' or 'n')
n
The number you are thinking of is 49
I needed 8 guesses.
Example with 51:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
n
2. Is the number you are thinking of less than 75? (Enter 'y' or 'n')
y
3. Is the number you are thinking of less than 62? (Enter 'y' or 'n')
y
4. Is the number you are thinking of less than 55? (Enter 'y' or 'n')
y
5. Is the number you are thinking of less than 52? (Enter 'y' or 'n')
y
6. Is the number you are thinking of less than 51? (Enter 'y' or 'n')
n
The number you are thinking of is 51
I needed 6 guesses.
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | #include "std_lib_facilities.h"
// Number guessing game
int main()
{
int number {50};
// define upper and lower bounds
int upper {100};
int lower {1};
int range {upper - lower};
char answer {'\0'};
int question {0};
cout << "Think of a number between " << lower << " and " << upper << "\n\n";
while (lower != upper)
{
range = upper - lower;
if (range == 1)
number = upper;
else
number = lower + range/2;
//cout << "upper: " << upper << " lower: " << lower << " range: " << range << '\n';
if (question%2 == 0)
{
cout << question + 1 << ". Is the number you are thinking of less than " << number << "? (Enter 'y' or 'n') \n";
cin >> answer;
if ('y' == answer)
{
upper = number-1;
question++;
} else if ('n' == answer) {
lower = number;
question++;
} else {
cout << "Please enter 'y' or 'n' ...\n";
}
} else {
cout << question + 1 << ". Is the number you are thinking of greater than " << number << "? (Enter 'y' or 'n') \n";
cin >> answer;
if ('y' == answer)
{
lower = number+1;
question++;
} else if ('n' == answer) {
upper = number;
question++;
} else {
cout << "Please enter 'y' or 'n' ...\n";
}
}
}
cout << "The number you are thinking of is " << lower << "\n";
cout << "I needed " << question << " guesses.\n";
return 0;
}
|
When I think of 100 the result is:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
n
2. Is the number you are thinking of greater than 75? (Enter 'y' or 'n')
y
3. Is the number you are thinking of less than 88? (Enter 'y' or 'n')
n
4. Is the number you are thinking of greater than 94? (Enter 'y' or 'n')
y
5. Is the number you are thinking of less than 97? (Enter 'y' or 'n')
n
6. Is the number you are thinking of greater than 98? (Enter 'y' or 'n')
y
7. Is the number you are thinking of less than 100? (Enter 'y' or 'n')
n
The number you are thinking of is 100
I needed 7 guesses.
Example with 99:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
n
2. Is the number you are thinking of greater than 75? (Enter 'y' or 'n')
y
3. Is the number you are thinking of less than 88? (Enter 'y' or 'n')
n
4. Is the number you are thinking of greater than 94? (Enter 'y' or 'n')
y
5. Is the number you are thinking of less than 97? (Enter 'y' or 'n')
n
6. Is the number you are thinking of greater than 98? (Enter 'y' or 'n')
y
7. Is the number you are thinking of less than 100? (Enter 'y' or 'n')
y
The number you are thinking of is 99
I needed 7 guesses.
Example with 98:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
n
2. Is the number you are thinking of greater than 75? (Enter 'y' or 'n')
y
3. Is the number you are thinking of less than 88? (Enter 'y' or 'n')
n
4. Is the number you are thinking of greater than 94? (Enter 'y' or 'n')
y
5. Is the number you are thinking of less than 97? (Enter 'y' or 'n')
n
6. Is the number you are thinking of greater than 98? (Enter 'y' or 'n')
n
7. Is the number you are thinking of less than 98? (Enter 'y' or 'n')
n
The number you are thinking of is 98
I needed 7 guesses.
Example with 1:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
y
2. Is the number you are thinking of greater than 25? (Enter 'y' or 'n')
n
3. Is the number you are thinking of less than 13? (Enter 'y' or 'n')
y
4. Is the number you are thinking of greater than 6? (Enter 'y' or 'n')
n
5. Is the number you are thinking of less than 3? (Enter 'y' or 'n')
y
6. Is the number you are thinking of greater than 2? (Enter 'y' or 'n')
n
7. Is the number you are thinking of less than 2? (Enter 'y' or 'n')
y
The number you are thinking of is 1
I needed 7 guesses.
Example with 2:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
y
2. Is the number you are thinking of greater than 25? (Enter 'y' or 'n')
n
3. Is the number you are thinking of less than 13? (Enter 'y' or 'n')
y
4. Is the number you are thinking of greater than 6? (Enter 'y' or 'n')
n
5. Is the number you are thinking of less than 3? (Enter 'y' or 'n')
y
6. Is the number you are thinking of greater than 2? (Enter 'y' or 'n')
n
7. Is the number you are thinking of less than 2? (Enter 'y' or 'n')
n
The number you are thinking of is 2
I needed 7 guesses.
Example with 3:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
y
2. Is the number you are thinking of greater than 25? (Enter 'y' or 'n')
n
3. Is the number you are thinking of less than 13? (Enter 'y' or 'n')
y
4. Is the number you are thinking of greater than 6? (Enter 'y' or 'n')
n
5. Is the number you are thinking of less than 3? (Enter 'y' or 'n')
n
6. Is the number you are thinking of greater than 4? (Enter 'y' or 'n')
n
7. Is the number you are thinking of less than 4? (Enter 'y' or 'n')
y
The number you are thinking of is 3
I needed 7 guesses.
Example with 50:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
n
2. Is the number you are thinking of greater than 75? (Enter 'y' or 'n')
n
3. Is the number you are thinking of less than 62? (Enter 'y' or 'n')
y
4. Is the number you are thinking of greater than 55? (Enter 'y' or 'n')
n
5. Is the number you are thinking of less than 52? (Enter 'y' or 'n')
y
6. Is the number you are thinking of greater than 51? (Enter 'y' or 'n')
n
7. Is the number you are thinking of less than 51? (Enter 'y' or 'n')
y
The number you are thinking of is 50
I needed 7 guesses.
Example with 49:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
y
2. Is the number you are thinking of greater than 25? (Enter 'y' or 'n')
y
3. Is the number you are thinking of less than 37? (Enter 'y' or 'n')
n
4. Is the number you are thinking of greater than 43? (Enter 'y' or 'n')
y
5. Is the number you are thinking of less than 46? (Enter 'y' or 'n')
n
6. Is the number you are thinking of greater than 47? (Enter 'y' or 'n')
y
7. Is the number you are thinking of less than 49? (Enter 'y' or 'n')
n
The number you are thinking of is 49
I needed 7 guesses.
Example with 51:
Think of a number between 1 and 100
1. Is the number you are thinking of less than 50? (Enter 'y' or 'n')
n
2. Is the number you are thinking of greater than 75? (Enter 'y' or 'n')
n
3. Is the number you are thinking of less than 62? (Enter 'y' or 'n')
y
4. Is the number you are thinking of greater than 55? (Enter 'y' or 'n')
n
5. Is the number you are thinking of less than 52? (Enter 'y' or 'n')
y
6. Is the number you are thinking of greater than 51? (Enter 'y' or 'n')
n
7. Is the number you are thinking of less than 51? (Enter 'y' or 'n')
n
The number you are thinking of is 51
I needed 7 guesses.
Exercise 05¶
Write a program that performs as a very simple calculator.
Your calculator should be able to handle the four basic math operations —
add, subtract, multiply, and divide — on two input values.
Your program should prompt the user to enter three arguments: two double
values and a character to represent an operation.
If the entry arguments are 35.6
, 24.1
, and '+'
, the program output should be The sum of 35.6 and 24.1 is 59.7
.
In Chapter 6 we look at a much more sophisticated simple calculator.
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 | #include "std_lib_facilities.h"
// Simple calculator
int main()
{
string input {"Enter three arguments: two double operands and a character ('+','-','*','/') representing an operation (followed by 'Enter').\n"};
cout << input;
double op1, op2;
char operation {'\0'};
while (cin >> op1 >> op2 >> operation)
{
switch (operation)
{
case '+':
cout << "The sum of " << op1 << " and " << op2 << " is " << op1+op2 << '\n';
break;
case '-':
cout << "The difference of " << op1 << " and " << op2 << " is " << op1-op2 << '\n';
break;
case '*':
cout << "The product of " << op1 << " and " << op2 << " is " << op1*op2 << '\n';
break;
case '/':
if (op2 == 0)
cout << "ERROR: Division by zero\n";
else
cout << "The division of " << op1 << " and " << op2 << " is " << op1/op2 << '\n';
break;
default:
cout << "The operator " << operation << " is not supported!\n";
break;
}
cout << input;
}
return 0;
}
|
Example output:
Enter three arguments: two double operands and a character ('+','-','*','/') representing an operation (followed by 'Enter').
5.2 6.5 +
The sum of 5.2 and 6.5 is 11.7
Enter three arguments: two double operands and a character ('+','-','*','/') representing an operation (followed by 'Enter').
7.2 8.9 -
The difference of 7.2 and 8.9 is -1.7
Enter three arguments: two double operands and a character ('+','-','*','/') representing an operation (followed by 'Enter').
2.2 5.0 *
The product of 2.2 and 5 is 11
Enter three arguments: two double operands and a character ('+','-','*','/') representing an operation (followed by 'Enter').
10.0 2.0 /
The division of 10 and 2 is 5
Enter three arguments: two double operands and a character ('+','-','*','/') representing an operation (followed by 'Enter').
7.3 1.2 %
The operator % is not supported!
Enter three arguments: two double operands and a character ('+','-','*','/') representing an operation (followed by 'Enter').
|
Process finished with exit code 0
Exercise 06¶
Make a vector
holding the ten string
values "zero"
, "one"
, … "nine"
.
Use that in a program that converts a digit to its corresponding spelled-out value; e.g., the input 7
gives the output seven.
Have the same program, using the same input loop, convert spelled-out numbers into their digit form;
e.g., the input seven
gives the output 7
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include "std_lib_facilities.h"
// Convert spelled-out digits
int main()
{
vector<string> stringDigits {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
cout << "Enter integer digits from 0 to 9 which will be converted to spelled-out digits (followed by 'Enter')\n";
int value;
while (cin >> value)
{
if (0 <= value && value <= 9)
cout << stringDigits[value] << '\n';
else
cout << "Error: value must be an integer between 0 and 9.\n";
}
return 0;
}
|
Example output:
Enter integer digits from 0 to 9 which will be converted to spelled-out digits (followed by 'Enter')
0
zero
1
one
2
two
3
three
4
four
5
five
6
six
7
seven
8
eight
9
nine
10
Error: value must be an integer between 0 and 9.
-1
Error: value must be an integer between 0 and 9.
|
Process finished with exit code 0
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | #include "std_lib_facilities.h"
vector<string> stringDigits {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
string input {"Enter digits from 0 to 9 (either as string or integer) which will be converted to (spelled-out) digits (followed by 'Enter')\n"};
int convertStringToInt(string digit)
{
for (int i = 0; i < stringDigits.size(); ++i)
{
if (stringDigits[i] == digit)
return i;
}
cout << "Error: digit not in vector\n";
cout << input;
return -1;
}
string convertIntToString(int digit)
{
if (0 <= digit && digit <= 9)
{
return stringDigits[digit];
}
else
{
cout << "Error: digit not in vector\n";
cout << input;
return " ";
}
}
// Convert spelled-out digits in both directions
int main()
{
cout << input;
string digit;
int value;
bool validinput {true};
while (validinput)
{
if (cin >> value)
{
string result = convertIntToString(value);
if (" " != result)
cout << result << '\n';
}
else
{
cin.clear(); // To use cin again after a failed read, you need to use a function call "cin.clear();" to "clear" it.
cin >> digit;
if (digit == "|")
validinput = false;
else
{
int result = convertStringToInt(digit);
if (-1 != result)
cout << result << '\n';
}
}
}
return 0;
}
|
Example output:
Enter digits from 0 to 9 (either as string or integer) which will be converted to (spelled-out) digits (followed by 'Enter')
0
zero
1
one
2
two
3
three
4
four
5
five
6
six
7
seven
8
eight
9
nine
10
Error: digit not in vector
Enter digits from 0 to 9 (either as string or integer) which will be converted to (spelled-out) digits (followed by 'Enter')
zero
0
one
1
two
2
three
3
four
4
five
5
six
6
seven
7
eight
8
nine
9
ten
Error: digit not in vector
Enter digits from 0 to 9 (either as string or integer) which will be converted to (spelled-out) digits (followed by 'Enter')
|
Process finished with exit code 0
Exercise 07¶
Modify the “mini calculator” from exercise 5 to accept (just) single-digit numbers written as either digits or spelled out.
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 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 107 108 109 110 111 112 113 114 115 116 | #include "std_lib_facilities.h"
vector<string> stringDigits {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
string inputDigits {"Operands must be digits from 0 to 9 (either as string or integer)\n"};
int convertStringToInt(string digit)
{
for (int i = 0; i < stringDigits.size(); ++i)
{
if (stringDigits[i] == digit)
return i;
}
cout << "Error: digit not in vector\n";
cout << inputDigits;
return -1;
}
vector<char> validOperators {'+','-','*','/'};
string inputOperator {"Enter a valid operator ('+','-','*','/')\n"};
bool checkValidOperator(char oper)
{
for (char o : validOperators)
{
if (oper == o)
return true;
}
cout << inputOperator;
return false;
}
// Simple calculator
int main()
{
string input {"Enter three arguments: two integer operands and a character ('+','-','*','/') representing an operation (followed by 'Enter').\n"};
cout << input << inputDigits;
int op, op1, op2;
vector<int> integerOperands(2);
string opstring;
char operation {'\0'};
bool validOperator {false};
while (true)
{
int i = 0;
while (i < integerOperands.size())
{
if (cin >> op)
{
integerOperands[i] = op;
++i;
}
else
{
cin.clear(); // To use cin again after a failed read, you need to use a function call "cin.clear();" to "clear" it.
cin >> opstring;
if (opstring == "|")
return 0;
else
{
int result = convertStringToInt(opstring);
if (-1 != result)
{
integerOperands[i] = result;
++i;
}
}
}
}
while (!validOperator)
{
if (cin >> operation)
validOperator = checkValidOperator(operation);
else
cout << inputOperator;
}
validOperator = false;
op1 = integerOperands[0];
op2 = integerOperands[1];
switch (operation)
{
case '+':
cout << "The sum of " << op1 << " and " << op2 << " is " << op1+op2 << '\n';
break;
case '-':
cout << "The difference of " << op1 << " and " << op2 << " is " << op1-op2 << '\n';
break;
case '*':
cout << "The product of " << op1 << " and " << op2 << " is " << op1*op2 << '\n';
break;
case '/':
if (op2 == 0)
cout << "ERROR: Division by zero\n";
else
cout << "The division of " << op1 << " and " << op2 << " is " << op1/op2 << '\n';
break;
default:
cout << "The operator " << operation << " is not supported!\n";
break;
}
cout << input;
cin.clear();
}
return 0;
}
|
Enter three arguments: two integer operands and a character ('+','-','*','/') representing an operation (followed by 'Enter').
Operands must be digits from 0 to 9 (either as string or integer)
1 2 +
The sum of 1 and 2 is 3
Enter three arguments: two integer operands and a character ('+','-','*','/') representing an operation (followed by 'Enter').
four five *
The product of 4 and 5 is 20
Enter three arguments: two integer operands and a character ('+','-','*','/') representing an operation (followed by 'Enter').
six 3 /
The division of 6 and 3 is 2
Enter three arguments: two integer operands and a character ('+','-','*','/') representing an operation (followed by 'Enter').
seven eight -
The difference of 7 and 8 is -1
Enter three arguments: two integer operands and a character ('+','-','*','/') representing an operation (followed by 'Enter').
5 two /
The division of 5 and 2 is 2
Enter three arguments: two integer operands and a character ('+','-','*','/') representing an operation (followed by 'Enter').
|
Process finished with exit code 0
Exercise 08¶
There is an old story that the emperor wanted to thank the inventor of
the game of chess and asked the inventor to name his reward. The inventor
asked for one grain of rice for the first square, 2 for the second, 4 for
the third, and so on, doubling for each of the 64 squares. That may sound
modest, but there wasn’t that much rice in the empire! Write a program to
calculate how many squares are required to give the inventor at least 1000
grains of rice, at least 1,000,000 grains, and at least 1,000,000,000 grains.
You’ll need a loop, of course, and probably an int
to keep track of which
square you are at, an int
to keep the number of grains on the current
square, and an int
to keep track of the grains on all previous squares. We
suggest that you write out the value of all your variables for each iteration
of the loop so that you can see what’s going on.
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 | #include "std_lib_facilities.h"
int main() {
vector<int> naDesiredRice{1000, 1'000'000, 1'000'000'000};
int nSquare {1};
int nRiceOnCurrSquare {1};
int nRiceOnPrevSquares {0};
for (int i = 0; i < naDesiredRice.size(); ++i) {
while (naDesiredRice[i] > nRiceOnPrevSquares + nRiceOnCurrSquare) {
cout << "Square: " << nSquare++ << '\n';
cout << "\tGrains at current square: " << nRiceOnCurrSquare << '\n';
cout << "\tRice on previous squares: " << nRiceOnPrevSquares << '\n';
cout << "\tTotal rice grains: " << nRiceOnPrevSquares + nRiceOnCurrSquare << '\n';
nRiceOnPrevSquares += nRiceOnCurrSquare;
nRiceOnCurrSquare *= 2;
}
cout << "To give the inventor at least " << naDesiredRice[i] << " grains, " << nSquare << " squares are required.\n";
cout << "Grains at square " << nSquare << ": " << nRiceOnCurrSquare << '\n';
cout << "With the rice on the previous squares this results in " << nRiceOnPrevSquares + nRiceOnCurrSquare << " total grains for the inventor.\n\n";
nSquare = 1;
nRiceOnCurrSquare = 1;
nRiceOnPrevSquares = 0;
}
return 0;
}
|
Output of the program:
Square: 1
Grains at current square: 1
Rice on previous squares: 0
Total rice grains: 1
Square: 2
Grains at current square: 2
Rice on previous squares: 1
Total rice grains: 3
Square: 3
Grains at current square: 4
Rice on previous squares: 3
Total rice grains: 7
Square: 4
Grains at current square: 8
Rice on previous squares: 7
Total rice grains: 15
Square: 5
Grains at current square: 16
Rice on previous squares: 15
Total rice grains: 31
Square: 6
Grains at current square: 32
Rice on previous squares: 31
Total rice grains: 63
Square: 7
Grains at current square: 64
Rice on previous squares: 63
Total rice grains: 127
Square: 8
Grains at current square: 128
Rice on previous squares: 127
Total rice grains: 255
Square: 9
Grains at current square: 256
Rice on previous squares: 255
Total rice grains: 511
To give the inventor at least 1000 grains, 10 squares are required.
Grains at square 10: 512
With the rice on the previous squares this results in 1023 total grains for the inventor.
Square: 1
Grains at current square: 1
Rice on previous squares: 0
Total rice grains: 1
Square: 2
Grains at current square: 2
Rice on previous squares: 1
Total rice grains: 3
Square: 3
Grains at current square: 4
Rice on previous squares: 3
Total rice grains: 7
Square: 4
Grains at current square: 8
Rice on previous squares: 7
Total rice grains: 15
Square: 5
Grains at current square: 16
Rice on previous squares: 15
Total rice grains: 31
Square: 6
Grains at current square: 32
Rice on previous squares: 31
Total rice grains: 63
Square: 7
Grains at current square: 64
Rice on previous squares: 63
Total rice grains: 127
Square: 8
Grains at current square: 128
Rice on previous squares: 127
Total rice grains: 255
Square: 9
Grains at current square: 256
Rice on previous squares: 255
Total rice grains: 511
Square: 10
Grains at current square: 512
Rice on previous squares: 511
Total rice grains: 1023
Square: 11
Grains at current square: 1024
Rice on previous squares: 1023
Total rice grains: 2047
Square: 12
Grains at current square: 2048
Rice on previous squares: 2047
Total rice grains: 4095
Square: 13
Grains at current square: 4096
Rice on previous squares: 4095
Total rice grains: 8191
Square: 14
Grains at current square: 8192
Rice on previous squares: 8191
Total rice grains: 16383
Square: 15
Grains at current square: 16384
Rice on previous squares: 16383
Total rice grains: 32767
Square: 16
Grains at current square: 32768
Rice on previous squares: 32767
Total rice grains: 65535
Square: 17
Grains at current square: 65536
Rice on previous squares: 65535
Total rice grains: 131071
Square: 18
Grains at current square: 131072
Rice on previous squares: 131071
Total rice grains: 262143
Square: 19
Grains at current square: 262144
Rice on previous squares: 262143
Total rice grains: 524287
To give the inventor at least 1000000 grains, 20 squares are required.
Grains at square 20: 524288
With the rice on the previous squares this results in 1048575 total grains for the inventor.
Square: 1
Grains at current square: 1
Rice on previous squares: 0
Total rice grains: 1
Square: 2
Grains at current square: 2
Rice on previous squares: 1
Total rice grains: 3
Square: 3
Grains at current square: 4
Rice on previous squares: 3
Total rice grains: 7
Square: 4
Grains at current square: 8
Rice on previous squares: 7
Total rice grains: 15
Square: 5
Grains at current square: 16
Rice on previous squares: 15
Total rice grains: 31
Square: 6
Grains at current square: 32
Rice on previous squares: 31
Total rice grains: 63
Square: 7
Grains at current square: 64
Rice on previous squares: 63
Total rice grains: 127
Square: 8
Grains at current square: 128
Rice on previous squares: 127
Total rice grains: 255
Square: 9
Grains at current square: 256
Rice on previous squares: 255
Total rice grains: 511
Square: 10
Grains at current square: 512
Rice on previous squares: 511
Total rice grains: 1023
Square: 11
Grains at current square: 1024
Rice on previous squares: 1023
Total rice grains: 2047
Square: 12
Grains at current square: 2048
Rice on previous squares: 2047
Total rice grains: 4095
Square: 13
Grains at current square: 4096
Rice on previous squares: 4095
Total rice grains: 8191
Square: 14
Grains at current square: 8192
Rice on previous squares: 8191
Total rice grains: 16383
Square: 15
Grains at current square: 16384
Rice on previous squares: 16383
Total rice grains: 32767
Square: 16
Grains at current square: 32768
Rice on previous squares: 32767
Total rice grains: 65535
Square: 17
Grains at current square: 65536
Rice on previous squares: 65535
Total rice grains: 131071
Square: 18
Grains at current square: 131072
Rice on previous squares: 131071
Total rice grains: 262143
Square: 19
Grains at current square: 262144
Rice on previous squares: 262143
Total rice grains: 524287
Square: 20
Grains at current square: 524288
Rice on previous squares: 524287
Total rice grains: 1048575
Square: 21
Grains at current square: 1048576
Rice on previous squares: 1048575
Total rice grains: 2097151
Square: 22
Grains at current square: 2097152
Rice on previous squares: 2097151
Total rice grains: 4194303
Square: 23
Grains at current square: 4194304
Rice on previous squares: 4194303
Total rice grains: 8388607
Square: 24
Grains at current square: 8388608
Rice on previous squares: 8388607
Total rice grains: 16777215
Square: 25
Grains at current square: 16777216
Rice on previous squares: 16777215
Total rice grains: 33554431
Square: 26
Grains at current square: 33554432
Rice on previous squares: 33554431
Total rice grains: 67108863
Square: 27
Grains at current square: 67108864
Rice on previous squares: 67108863
Total rice grains: 134217727
Square: 28
Grains at current square: 134217728
Rice on previous squares: 134217727
Total rice grains: 268435455
Square: 29
Grains at current square: 268435456
Rice on previous squares: 268435455
Total rice grains: 536870911
To give the inventor at least 1000000000 grains, 30 squares are required.
Grains at square 30: 536870912
With the rice on the previous squares this results in 1073741823 total grains for the inventor.
Exercise 09¶
Try to calculate the number of rice grains that the inventor asked for in exercise 8 above.
You’ll find that the number is so large that it won’t fit in an int
or a double
.
Observe what happens when the number gets too large to represent exactly as an int
and as a double
.
What is the largest number of squares for which you can calculate the exact number of grains (using an int
)?
What is the largest number of squares for which you can calculate the approximate number of grains (using a double
)?
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 | #include "std_lib_facilities.h"
int main() {
int nRiceOnCurrSquare {1};
int nRiceOnPrevSquares {0};
double dRiceOnCurrSquare {1.0};
double dRiceOnPrevSquares {0.0};
// Maximum number that fits in an int (assuming 32 bits)
// 2^32/2: form −(2^31) to 2^31 − 1 => maximum is 2,147,483,647
// Maximum number that fits in an int (assuming 64 bit)
// 2^64/2: from −(2^63) to 2^63 − 1 => 9,223,372,036,854,775,807
// Maximum number that fits in a double (https://en.wikipedia.org/wiki/Double-precision_floating-point_format)
// From +-5e-324 to +-1.7e308
for (int nSquare = 1; nSquare <= 1024; ++nSquare) {
cout << "Square: " << nSquare << '\n';
cout << "\tGrains on current square [in]: " << nRiceOnCurrSquare << ", [double]: " << dRiceOnCurrSquare << '\n';
cout << "\tRice on previous squares [int]: " << nRiceOnPrevSquares << ", [double]: " << dRiceOnPrevSquares << '\n';
cout << "\tTotal rice grains [int]: " << nRiceOnPrevSquares + nRiceOnCurrSquare << ", [double]: " << dRiceOnPrevSquares + dRiceOnCurrSquare << '\n';
nRiceOnPrevSquares += nRiceOnCurrSquare;
nRiceOnCurrSquare *= 2;
dRiceOnPrevSquares += dRiceOnCurrSquare;
dRiceOnCurrSquare *= 2;
}
return 0;
}
|
Program output:
Square: 1
Grains on current square [in]: 1, [double]: 1
Rice on previous squares [int]: 0, [double]: 0
Total rice grains [int]: 1, [double]: 1
Square: 2
Grains on current square [in]: 2, [double]: 2
Rice on previous squares [int]: 1, [double]: 1
Total rice grains [int]: 3, [double]: 3
Square: 3
Grains on current square [in]: 4, [double]: 4
Rice on previous squares [int]: 3, [double]: 3
Total rice grains [int]: 7, [double]: 7
Square: 4
Grains on current square [in]: 8, [double]: 8
Rice on previous squares [int]: 7, [double]: 7
Total rice grains [int]: 15, [double]: 15
Square: 5
Grains on current square [in]: 16, [double]: 16
Rice on previous squares [int]: 15, [double]: 15
Total rice grains [int]: 31, [double]: 31
Square: 6
Grains on current square [in]: 32, [double]: 32
Rice on previous squares [int]: 31, [double]: 31
Total rice grains [int]: 63, [double]: 63
Square: 7
Grains on current square [in]: 64, [double]: 64
Rice on previous squares [int]: 63, [double]: 63
Total rice grains [int]: 127, [double]: 127
Square: 8
Grains on current square [in]: 128, [double]: 128
Rice on previous squares [int]: 127, [double]: 127
Total rice grains [int]: 255, [double]: 255
Square: 9
Grains on current square [in]: 256, [double]: 256
Rice on previous squares [int]: 255, [double]: 255
Total rice grains [int]: 511, [double]: 511
Square: 10
Grains on current square [in]: 512, [double]: 512
Rice on previous squares [int]: 511, [double]: 511
Total rice grains [int]: 1023, [double]: 1023
Square: 11
Grains on current square [in]: 1024, [double]: 1024
Rice on previous squares [int]: 1023, [double]: 1023
Total rice grains [int]: 2047, [double]: 2047
Square: 12
Grains on current square [in]: 2048, [double]: 2048
Rice on previous squares [int]: 2047, [double]: 2047
Total rice grains [int]: 4095, [double]: 4095
Square: 13
Grains on current square [in]: 4096, [double]: 4096
Rice on previous squares [int]: 4095, [double]: 4095
Total rice grains [int]: 8191, [double]: 8191
Square: 14
Grains on current square [in]: 8192, [double]: 8192
Rice on previous squares [int]: 8191, [double]: 8191
Total rice grains [int]: 16383, [double]: 16383
Square: 15
Grains on current square [in]: 16384, [double]: 16384
Rice on previous squares [int]: 16383, [double]: 16383
Total rice grains [int]: 32767, [double]: 32767
Square: 16
Grains on current square [in]: 32768, [double]: 32768
Rice on previous squares [int]: 32767, [double]: 32767
Total rice grains [int]: 65535, [double]: 65535
Square: 17
Grains on current square [in]: 65536, [double]: 65536
Rice on previous squares [int]: 65535, [double]: 65535
Total rice grains [int]: 131071, [double]: 131071
Square: 18
Grains on current square [in]: 131072, [double]: 131072
Rice on previous squares [int]: 131071, [double]: 131071
Total rice grains [int]: 262143, [double]: 262143
Square: 19
Grains on current square [in]: 262144, [double]: 262144
Rice on previous squares [int]: 262143, [double]: 262143
Total rice grains [int]: 524287, [double]: 524287
Square: 20
Grains on current square [in]: 524288, [double]: 524288
Rice on previous squares [int]: 524287, [double]: 524287
Total rice grains [int]: 1048575, [double]: 1.04858e+06
Square: 21
Grains on current square [in]: 1048576, [double]: 1.04858e+06
Rice on previous squares [int]: 1048575, [double]: 1.04858e+06
Total rice grains [int]: 2097151, [double]: 2.09715e+06
Square: 22
Grains on current square [in]: 2097152, [double]: 2.09715e+06
Rice on previous squares [int]: 2097151, [double]: 2.09715e+06
Total rice grains [int]: 4194303, [double]: 4.1943e+06
Square: 23
Grains on current square [in]: 4194304, [double]: 4.1943e+06
Rice on previous squares [int]: 4194303, [double]: 4.1943e+06
Total rice grains [int]: 8388607, [double]: 8.38861e+06
Square: 24
Grains on current square [in]: 8388608, [double]: 8.38861e+06
Rice on previous squares [int]: 8388607, [double]: 8.38861e+06
Total rice grains [int]: 16777215, [double]: 1.67772e+07
Square: 25
Grains on current square [in]: 16777216, [double]: 1.67772e+07
Rice on previous squares [int]: 16777215, [double]: 1.67772e+07
Total rice grains [int]: 33554431, [double]: 3.35544e+07
Square: 26
Grains on current square [in]: 33554432, [double]: 3.35544e+07
Rice on previous squares [int]: 33554431, [double]: 3.35544e+07
Total rice grains [int]: 67108863, [double]: 6.71089e+07
Square: 27
Grains on current square [in]: 67108864, [double]: 6.71089e+07
Rice on previous squares [int]: 67108863, [double]: 6.71089e+07
Total rice grains [int]: 134217727, [double]: 1.34218e+08
Square: 28
Grains on current square [in]: 134217728, [double]: 1.34218e+08
Rice on previous squares [int]: 134217727, [double]: 1.34218e+08
Total rice grains [int]: 268435455, [double]: 2.68435e+08
Square: 29
Grains on current square [in]: 268435456, [double]: 2.68435e+08
Rice on previous squares [int]: 268435455, [double]: 2.68435e+08
Total rice grains [int]: 536870911, [double]: 5.36871e+08
Square: 30
Grains on current square [in]: 536870912, [double]: 5.36871e+08
Rice on previous squares [int]: 536870911, [double]: 5.36871e+08
Total rice grains [int]: 1073741823, [double]: 1.07374e+09
Square: 31
Grains on current square [in]: 1073741824, [double]: 1.07374e+09
Rice on previous squares [int]: 1073741823, [double]: 1.07374e+09
Total rice grains [int]: 2147483647, [double]: 2.14748e+09
Square: 32
Grains on current square [in]: -2147483648, [double]: 2.14748e+09
Rice on previous squares [int]: 2147483647, [double]: 2.14748e+09
Total rice grains [int]: -1, [double]: 4.29497e+09
Square: 33
Grains on current square [in]: 0, [double]: 4.29497e+09
Rice on previous squares [int]: -1, [double]: 4.29497e+09
Total rice grains [int]: -1, [double]: 8.58993e+09
Square: 34
Grains on current square [in]: 0, [double]: 8.58993e+09
Rice on previous squares [int]: -1, [double]: 8.58993e+09
Total rice grains [int]: -1, [double]: 1.71799e+10
Square: 35
Grains on current square [in]: 0, [double]: 1.71799e+10
Rice on previous squares [int]: -1, [double]: 1.71799e+10
Total rice grains [int]: -1, [double]: 3.43597e+10
Square: 36
Grains on current square [in]: 0, [double]: 3.43597e+10
Rice on previous squares [int]: -1, [double]: 3.43597e+10
Total rice grains [int]: -1, [double]: 6.87195e+10
Square: 37
Grains on current square [in]: 0, [double]: 6.87195e+10
Rice on previous squares [int]: -1, [double]: 6.87195e+10
Total rice grains [int]: -1, [double]: 1.37439e+11
Square: 38
Grains on current square [in]: 0, [double]: 1.37439e+11
Rice on previous squares [int]: -1, [double]: 1.37439e+11
Total rice grains [int]: -1, [double]: 2.74878e+11
Square: 39
Grains on current square [in]: 0, [double]: 2.74878e+11
Rice on previous squares [int]: -1, [double]: 2.74878e+11
Total rice grains [int]: -1, [double]: 5.49756e+11
Square: 40
Grains on current square [in]: 0, [double]: 5.49756e+11
Rice on previous squares [int]: -1, [double]: 5.49756e+11
Total rice grains [int]: -1, [double]: 1.09951e+12
Square: 41
Grains on current square [in]: 0, [double]: 1.09951e+12
Rice on previous squares [int]: -1, [double]: 1.09951e+12
Total rice grains [int]: -1, [double]: 2.19902e+12
Square: 42
Grains on current square [in]: 0, [double]: 2.19902e+12
Rice on previous squares [int]: -1, [double]: 2.19902e+12
Total rice grains [int]: -1, [double]: 4.39805e+12
Square: 43
Grains on current square [in]: 0, [double]: 4.39805e+12
Rice on previous squares [int]: -1, [double]: 4.39805e+12
Total rice grains [int]: -1, [double]: 8.79609e+12
Square: 44
Grains on current square [in]: 0, [double]: 8.79609e+12
Rice on previous squares [int]: -1, [double]: 8.79609e+12
Total rice grains [int]: -1, [double]: 1.75922e+13
Square: 45
Grains on current square [in]: 0, [double]: 1.75922e+13
Rice on previous squares [int]: -1, [double]: 1.75922e+13
Total rice grains [int]: -1, [double]: 3.51844e+13
Square: 46
Grains on current square [in]: 0, [double]: 3.51844e+13
Rice on previous squares [int]: -1, [double]: 3.51844e+13
Total rice grains [int]: -1, [double]: 7.03687e+13
Square: 47
Grains on current square [in]: 0, [double]: 7.03687e+13
Rice on previous squares [int]: -1, [double]: 7.03687e+13
Total rice grains [int]: -1, [double]: 1.40737e+14
Square: 48
Grains on current square [in]: 0, [double]: 1.40737e+14
Rice on previous squares [int]: -1, [double]: 1.40737e+14
Total rice grains [int]: -1, [double]: 2.81475e+14
Square: 49
Grains on current square [in]: 0, [double]: 2.81475e+14
Rice on previous squares [int]: -1, [double]: 2.81475e+14
Total rice grains [int]: -1, [double]: 5.6295e+14
Square: 50
Grains on current square [in]: 0, [double]: 5.6295e+14
Rice on previous squares [int]: -1, [double]: 5.6295e+14
Total rice grains [int]: -1, [double]: 1.1259e+15
Square: 51
Grains on current square [in]: 0, [double]: 1.1259e+15
Rice on previous squares [int]: -1, [double]: 1.1259e+15
Total rice grains [int]: -1, [double]: 2.2518e+15
Square: 52
Grains on current square [in]: 0, [double]: 2.2518e+15
Rice on previous squares [int]: -1, [double]: 2.2518e+15
Total rice grains [int]: -1, [double]: 4.5036e+15
Square: 53
Grains on current square [in]: 0, [double]: 4.5036e+15
Rice on previous squares [int]: -1, [double]: 4.5036e+15
Total rice grains [int]: -1, [double]: 9.0072e+15
Square: 54
Grains on current square [in]: 0, [double]: 9.0072e+15
Rice on previous squares [int]: -1, [double]: 9.0072e+15
Total rice grains [int]: -1, [double]: 1.80144e+16
Square: 55
Grains on current square [in]: 0, [double]: 1.80144e+16
Rice on previous squares [int]: -1, [double]: 1.80144e+16
Total rice grains [int]: -1, [double]: 3.60288e+16
Square: 56
Grains on current square [in]: 0, [double]: 3.60288e+16
Rice on previous squares [int]: -1, [double]: 3.60288e+16
Total rice grains [int]: -1, [double]: 7.20576e+16
Square: 57
Grains on current square [in]: 0, [double]: 7.20576e+16
Rice on previous squares [int]: -1, [double]: 7.20576e+16
Total rice grains [int]: -1, [double]: 1.44115e+17
Square: 58
Grains on current square [in]: 0, [double]: 1.44115e+17
Rice on previous squares [int]: -1, [double]: 1.44115e+17
Total rice grains [int]: -1, [double]: 2.8823e+17
Square: 59
Grains on current square [in]: 0, [double]: 2.8823e+17
Rice on previous squares [int]: -1, [double]: 2.8823e+17
Total rice grains [int]: -1, [double]: 5.76461e+17
Square: 60
Grains on current square [in]: 0, [double]: 5.76461e+17
Rice on previous squares [int]: -1, [double]: 5.76461e+17
Total rice grains [int]: -1, [double]: 1.15292e+18
Square: 61
Grains on current square [in]: 0, [double]: 1.15292e+18
Rice on previous squares [int]: -1, [double]: 1.15292e+18
Total rice grains [int]: -1, [double]: 2.30584e+18
Square: 62
Grains on current square [in]: 0, [double]: 2.30584e+18
Rice on previous squares [int]: -1, [double]: 2.30584e+18
Total rice grains [int]: -1, [double]: 4.61169e+18
Square: 63
Grains on current square [in]: 0, [double]: 4.61169e+18
Rice on previous squares [int]: -1, [double]: 4.61169e+18
Total rice grains [int]: -1, [double]: 9.22337e+18
Square: 64
Grains on current square [in]: 0, [double]: 9.22337e+18
Rice on previous squares [int]: -1, [double]: 9.22337e+18
Total rice grains [int]: -1, [double]: 1.84467e+19
The maximum number of squares for an int
is 31,
which results exactly in the total positive value that a 32 bit integer can represent 2,147,483,647 = 2^31 - 1.
Afterwards the total value overflows and is negative from square 32 on.
Square: 31
Grains on current square [in]: 1073741824, [double]: 1.07374e+09
Rice on previous squares [int]: 1073741823, [double]: 1.07374e+09
Total rice grains [int]: 2147483647, [double]: 2.14748e+09
Square: 32
Grains on current square [in]: -2147483648, [double]: 2.14748e+09
Rice on previous squares [int]: 2147483647, [double]: 2.14748e+09
Total rice grains [int]: -1, [double]: 4.29497e+09
For double
square 1024 resulted in an inf
value of total grains:
Square: 1023
Grains on current square [in]: 0, [double]: 4.49423e+307
Rice on previous squares [int]: -1, [double]: 4.49423e+307
Total rice grains [int]: -1, [double]: 8.98847e+307
Square: 1024
Grains on current square [in]: 0, [double]: 8.98847e+307
Rice on previous squares [int]: -1, [double]: 8.98847e+307
Total rice grains [int]: -1, [double]: inf
Square 1023 yields the “maximum displayable” double
value of 8.98847e+307.
Afterwards the total number of rice grains is inf.
Exercise 10¶
Write a program that plays the game “Rock, Paper, Scissors”.
If you are not familiar with the game do some research (e.g., on the web using Google).
Research is a common task for programmers. Use a switch
-statement to solve this exercise.
Also, the machine should give random answers (i.e., select the next rock, paper, or scissors randomly).
Real randomness is too hard to provide just now,
so just build a vector with a sequence of values to be used as “the next value”.
If you build the vector into the program, it will always play the same game,
so maybe you should let the user enter some values.
Try variations to make it less easy for the user to guess which move the machine will make next.
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 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 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 | #include "std_lib_facilities.h"
const vector<string> straGesture {"Rock", "Paper", "Scissors"};
string PlayerThrow()
{
cout << "\tEnter a gesture ('Rock', 'Paper', 'Scissors'):\n";
string strPlayerThrow;
while (true)
{
if (cin >> strPlayerThrow)
{
for (string strGesture : straGesture)
{
if (strGesture == strPlayerThrow)
return strPlayerThrow;
}
}
cout << "Please try again. Enter 'Rock', 'Paper' or 'Scissors'\n";
cin.clear();
}
}
string ComputerThrow()
{
cout << "\tEnter an integer which I will use to generate a random gesture.\n";
int nRandomNumber;
while (true)
{
if (cin >> nRandomNumber)
{
int nRandomIdx = nRandomNumber % straGesture.size();
return straGesture[nRandomIdx];
}
cout << "Please try again. Enter an integer'\n";
cin.clear();
cin.ignore();
}
}
void Draw(string i_strGesture)
{
cout << "\tDraw! We both threw " << i_strGesture << " ... Repeat\n";
}
void PlayerWin(string i_strPlayerGesture, string i_strComputerGesture)
{
cout << "\tYou win with " << i_strPlayerGesture << " against my " << i_strComputerGesture << " gesture.\n";
}
void ComputerWin(string i_strPlayerGesture, string i_strComputerGesture)
{
cout << "\tI win with " << i_strComputerGesture << " against your " << i_strPlayerGesture << " gesture.\n";
}
int main()
{
vector<int> rand {1, 2, 4, 8, 1, 9, 8, 2, 4, 3, 7, 1, 9, 4, 0, 6, 7, 0, 2, 4, 6, 8, 4, 3, 9, 1, 0, 2, 4, 8};
string strComputerGesture {" "};
string strPlayerGesture {" "};
int nRound {1};
int nWins {2};
int nPlayerScore {0};
int nComputerScore {0};
cout << "Let's play 'Rock, Paper, Scissors'. Finish when one wins " << nWins << " games and repeat on draws.\n";
while (nPlayerScore < nWins && nComputerScore < nWins) {
cout << nRound << ". Round:\n";
strComputerGesture = ComputerThrow();
strPlayerGesture = PlayerThrow();
cout << "Rock, Paper, Scissors\n";
if (strPlayerGesture == strComputerGesture)
{
Draw(strPlayerGesture);
}
else {
switch (strComputerGesture[0]) {
case 'R':
switch (strPlayerGesture[0]) {
case 'P':
PlayerWin(strPlayerGesture, strComputerGesture);
nPlayerScore++;
break;
case 'S':
ComputerWin(strPlayerGesture, strComputerGesture);
nComputerScore++;
break;
default:
cout << "Error, something went wrong!\n";
}
break;
case 'P':
switch (strPlayerGesture[0]) {
case 'R':
ComputerWin(strPlayerGesture, strComputerGesture);
nComputerScore++;
break;
case 'S':
PlayerWin(strPlayerGesture, strComputerGesture);
nPlayerScore++;
break;
default:
cout << "Error, something went wrong!\n";
}
break;
case 'S':
switch (strPlayerGesture[0]) {
case 'R':
PlayerWin(strPlayerGesture, strComputerGesture);
nPlayerScore++;
break;
case 'P':
ComputerWin(strPlayerGesture, strComputerGesture);
nComputerScore++;
break;
default:
cout << "Error, something went wrong!\n";
}
break;
default:
cout << "Error, something went wrong!\n";
}
cout << "\tScore: Player " << nPlayerScore << ":" << nComputerScore << " Computer\n\n";
nRound++;
}
}
if (nPlayerScore > nComputerScore)
{
cout << "You win this game with a score of ";
} else {
cout << "I win this game with a score of ";
}
cout << nPlayerScore << ":" << nComputerScore << '\n';
return 0;
}
|
Example games:
Let's play 'Rock, Paper, Scissors'. Finish when one wins 2 games and repeat on draws.
1. Round:
Enter an integer which I will use to generate a random gesture.
1
Enter a gesture ('Rock', 'Paper', 'Scissors'):
Rock
Rock, Paper, Scissors
I win with Paper against your Rock gesture.
Score: Player 0:1 Computer
2. Round:
Enter an integer which I will use to generate a random gesture.
2
Enter a gesture ('Rock', 'Paper', 'Scissors'):
Rock
Rock, Paper, Scissors
You win with Rock against my Scissors gesture.
Score: Player 1:1 Computer
3. Round:
Enter an integer which I will use to generate a random gesture.
2
Enter a gesture ('Rock', 'Paper', 'Scissors'):
Rock
Rock, Paper, Scissors
You win with Rock against my Scissors gesture.
Score: Player 2:1 Computer
You win this game with a score of 2:1
Let's play 'Rock, Paper, Scissors'. Finish when one wins 2 games and repeat on draws.
1. Round:
Enter an integer which I will use to generate a random gesture.
500
Enter a gesture ('Rock', 'Paper', 'Scissors'):
Scissors
Rock, Paper, Scissors
Draw! We both threw Scissors ... Repeat
Score: Player 0:0 Computer
1. Round:
Enter an integer which I will use to generate a random gesture.
1
Enter a gesture ('Rock', 'Paper', 'Scissors'):
Paper
Rock, Paper, Scissors
Draw! We both threw Paper ... Repeat
Score: Player 0:0 Computer
1. Round:
Enter an integer which I will use to generate a random gesture.
320
Enter a gesture ('Rock', 'Paper', 'Scissors'):
Stone
Please try again. Enter 'Rock', 'Paper' or 'Scissors'
Rock
Rock, Paper, Scissors
You win with Rock against my Scissors gesture.
Score: Player 1:0 Computer
2. Round:
Enter an integer which I will use to generate a random gesture.
160
Enter a gesture ('Rock', 'Paper', 'Scissors'):
Paper
Rock, Paper, Scissors
Draw! We both threw Paper ... Repeat
Score: Player 1:0 Computer
2. Round:
Enter an integer which I will use to generate a random gesture.
750
Enter a gesture ('Rock', 'Paper', 'Scissors'):
Paper
Rock, Paper, Scissors
You win with Paper against my Rock gesture.
Score: Player 2:0 Computer
You win this game with a score of 2:0
The next game shows that the random generator is missing:
Let's play 'Rock, Paper, Scissors'. Finish when one wins 2 games and repeat on draws.
1. Round:
Enter an integer which I will use to generate a random gesture.
2
Enter a gesture ('Rock', 'Paper', 'Scissors'):
Paper
Rock, Paper, Scissors
I win with Scissors against your Paper gesture.
Score: Player 0:1 Computer
2. Round:
Enter an integer which I will use to generate a random gesture.
2
Enter a gesture ('Rock', 'Paper', 'Scissors'):
Paper
Rock, Paper, Scissors
I win with Scissors against your Paper gesture.
Score: Player 0:2 Computer
I win this game with a score of 0:2
Exercise 11¶
Create a program to find all the prime numbers between 1 and 100. One
way to do this is to write a function that will check if a number is prime
(i.e., see if the number can be divided by a prime number smaller than
itself) using a vecto
r of primes in order (so that if the vector
is called
primes
, primes[0]==2
, primes[1]==3
, primes[2]==5
, etc.). Then write a
loop that goes from 1 to 100, checks each number to see if it is a prime,
and stores each prime found in a vecto
r. Write another loop that lists the
primes you found. You might check your result by comparing your vector
of prime numbers with primes. Consider 2 the first prime.
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 | #include "std_lib_facilities.h"
// Check if the number can be divided by a prime number smaller than itself
bool IsPrime(int i_nNumber, vector<int> i_naPrimes)
{
for (int prime : i_naPrimes)
{
if (i_nNumber < prime || i_nNumber % prime == 0)
return false;
}
return true;
}
int main() {
vector<int> naPrimes {2};
for (int nNumber = 1; nNumber <= 100; ++nNumber)
{
if (IsPrime(nNumber, naPrimes))
{
naPrimes.push_back(nNumber);
}
}
cout << "Found prime numbers between 1 and 100: \n";
for (int nPrime : naPrimes)
{
cout << nPrime << " ";
}
cout << '\n';
return 0;
}
|
The result of this program is:
Found prime numbers between 1 and 100:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Exercise 12¶
Modify the program described in the previous exercise to take an input value max
and then find all prime numbers from 1
to max
.
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 | #include "std_lib_facilities.h"
// Check if the number can be divided by a prime number smaller than itself
bool IsPrime(int i_nNumber, vector<int> i_naPrimes)
{
for (int prime : i_naPrimes)
{
if (i_nNumber < prime || i_nNumber % prime == 0)
return false;
}
return true;
}
int main() {
vector<int> naPrimes {2};
cout << "Enter an integer greater than 1 that defines the maximum of a range for which primes are searched.\n";
int nMax;
bool bValidInput {false};
while (!bValidInput)
{
if (cin >> nMax && nMax > 1)
bValidInput = true;
else
cout << "Enter an integer greater than 1 (followed by 'Enter')\n";
}
for (int nNumber = 1; nNumber <= nMax; ++nNumber)
{
if (IsPrime(nNumber, naPrimes))
{
naPrimes.push_back(nNumber);
}
}
cout << "Found prime numbers between 1 and " << nMax << ": \n";
int nPrime {2};
for (int nIdx = 0; nIdx < naPrimes.size(); ++nIdx)
{
nPrime = naPrimes[nIdx];
cout << nPrime << " ";
if ((nIdx+1) % 25 == 0) // Line break after 25 primes
cout << '\n';
}
cout << '\n';
return 0;
}
|
Example input and the corresponding output:
Enter an integer that defines the maximum of a range for which primes are searched.
10
Found prime numbers between 1 and 10:
2 3 5 7
Enter an integer greater than 1 that defines the maximum of a range for which primes are searched.
1
Enter an integer greater than 1 (followed by 'Enter')
2
Found prime numbers between 1 and 2:
2
Enter an integer greater than 1 that defines the maximum of a range for which primes are searched.
100
Found prime numbers between 1 and 100:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Enter an integer greater than 1 that defines the maximum of a range for which primes are searched.
1000
Found prime numbers between 1 and 1000:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229
233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379
383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541
547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691
701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863
877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997
Exercise 13¶
Create a program to find all the prime numbers between 1 and 100. There is a classic method for doing this, called the “Sieve of Eratosthenes”. If you don’t know that method, get on the web and look it up. Write your program using this method.
From Wikipedia:
To find all the prime numbers less than or equal to a given integer n
by Eratosthenes’ method:
- Create a list of consecutive integers from 2 through n: (2, 3, 4, …, n).
- Initially, let p equal 2, the smallest prime number.
- Enumerate the multiples of p by counting in increments of p from 2p to n, and mark them in the list (these will be 2p, 3p, 4p, …; the p itself should not be marked).
- Find the first number greater than p in the list that is not marked. If there was no such number, stop. Otherwise, let p now equal this new number (which is the next prime), and repeat from step 3.
- When the algorithm terminates, the numbers remaining not marked in the list are all the primes below n.
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 52 53 54 55 56 57 58 59 60 | #include "std_lib_facilities.h"
// Sieve of Eratosthenes algorithm:
// 1. Create a list of consecutive integers from 2 through n: (2, 3, 4, ..., n).
// 2. Initially, let p equal 2, the smallest prime number.
// 3. Enumerate the multiples of p by counting in increments of p from 2p to n,
// and mark them in the list (these will be 2p, 3p, 4p, ...; the p itself should not be marked).
// 4. Find the first number greater than p in the list that is not marked.
// If there was no such number, stop. Otherwise, let p now equal this new number (which is the next prime),
// and repeat from step 3.
// 5. When the algorithm terminates, the numbers remaining not marked in the list are all the primes below n.
int main()
{
// 1. Create a list of consecutive integers from 2 through n: (2, 3, 4, ..., n).
// The indices will represent the numbers and true or false will specify if a number is marked, meaning it is no prime.
constexpr int nMax {100};
vector<int> baMarked(nMax+1); // Plus 1 because nMax should also be check if it is prime
// Initially, all numbers are not marked. Composite numbers are going to be marked true. Primes will stay false.
// This loop should not be necessary because vector is default initialized to false usually.
for (int nIdx = 0; nIdx < baMarked.size(); ++nIdx)
{
baMarked[nIdx] = false;
}
// 2. Initially, let p equal 2, the smallest prime number.
// 3. Enumerate the multiples of p by counting in increments of p from 2p to n,
// and mark them in the list (these will be 2p, 3p, 4p, ...; the p itself should not be marked).
// 4. Find the first number greater than p in the list that is not marked.
// If there was no such number, stop. Otherwise, let p now equal this new number (which is the next prime),
// and repeat from step 3.
int nMultiple {0};
for (int nNumber = 2; nNumber < nMax; ++nNumber)
{
// If the number is not marked (false), it is a prime number
if (false == baMarked[nNumber])
{
// Calculate all the multiples of that number and mark them as being a composite (not prime)
nMultiple = {2 * nNumber};
while (nMultiple <= nMax)
{
baMarked[nMultiple] = true;
nMultiple += nNumber;
}
}
}
// 5. When the algorithm terminates, the numbers remaining not marked in the list are all the primes below n.
cout << "The prime numbers between 1 and " << nMax << " are:\n";
for (int nNumber = 2; nNumber < nMax; ++nNumber)
{
if (!baMarked[nNumber])
cout << nNumber << " ";
}
cout << '\n';
return 0;
}
|
The output is:
The prime numbers between 1 and 100 are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Another version of the program is the following, which uses a vector:
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | #include "std_lib_facilities.h"
bool Sived(int i_nNumber, vector<int> i_naSived)
{
for (int nSived : i_naSived)
{
if (nSived == i_nNumber)
return true;
}
return false;
}
int main() {
vector<int> naPrimes {};
//cout << "Enter an integer greater than 1 that defines the maximum of a range for which primes are searched.\n";
//int nMax;
//bool bValidInput {false};
//while (!bValidInput)
//{
// if (cin >> nMax && nMax > 1)
// bValidInput = true;
// else
// cout << "Enter an integer greater than 1 (followed by 'Enter')\n";
//}
vector<int> naSived {};
int nComposite {0};
int nCount {1};
for (int nNumber = 2; nNumber <= 100; ++nNumber)
{
if (!Sived(nNumber, naSived)) {
naPrimes.push_back(nNumber);
// Add multiples of the current prime to the sived vector
for (int nMultiplier = 1; nMultiplier * nNumber <= 100; ++nMultiplier) {
nComposite = nNumber * nMultiplier;
naSived.push_back(nComposite);
cout << nComposite << " ";
if (nCount % 10 == 0) {
cout << '\n';
}
nCount++;
}
//if (nCount-1 % 10 == 0)
cout << "\n\n";
//else
// cout << "\n";
}
}
cout << "Found prime numbers between 1 and " << 100 << ": \n";
int nPrime {2};
for (int nIdx = 0; nIdx < naPrimes.size(); ++nIdx)
{
nPrime = naPrimes[nIdx];
cout << nPrime << " ";
if ((nIdx+1) % 25 == 0) // Line break after 25 primes
cout << '\n';
}
cout << '\n';
return 0;
}
|
The following output shows the sieved number blocks for every iteration of the outer for loop. The amount of sieved numbers reduces because most of them are already marked as not being prime.
2 4 6 8 10 12 14 16 18 20
22 24 26 28 30 32 34 36 38 40
42 44 46 48 50 52 54 56 58 60
62 64 66 68 70 72 74 76 78 80
82 84 86 88 90 92 94 96 98 100
3 6 9 12 15 18 21 24 27 30
33 36 39 42 45 48 51 54 57 60
63 66 69 72 75 78 81 84 87 90
93 96 99
5 10 15 20 25 30 35
40 45 50 55 60 65 70 75 80 85
90 95 100
7 14 21 28 35 42 49
56 63 70 77 84 91 98
11 22 33
44 55 66 77 88 99
13 26 39 52
65 78 91
17 34 51 68 85
19 38
57 76 95
23 46 69 92
29 58 87
31 62 93
37 74
41 82
43 86
47
94
53
59
61
67
71
73
79
83
89
97
Found prime numbers between 1 and 100:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Exercise 14¶
Modify the program described in the previous exercise to take an input value max and
then find all prime numbers from 1
to max
.
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 52 53 54 55 56 57 58 59 60 61 62 | #include "std_lib_facilities.h"
// Sieve of Eratosthenes algorithm:
// 1. Create a list of consecutive integers from 2 through n: (2, 3, 4, ..., n).
// 2. Initially, let p equal 2, the smallest prime number.
// 3. Enumerate the multiples of p by counting in increments of p from 2p to n,
// and mark them in the list (these will be 2p, 3p, 4p, ...; the p itself should not be marked).
// 4. Find the first number greater than p in the list that is not marked.
// If there was no such number, stop. Otherwise, let p now equal this new number (which is the next prime),
// and repeat from step 3.
// 5. When the algorithm terminates, the numbers remaining not marked in the list are all the primes below n.
int main()
{
cout << "Enter an upper limit up to that primes are searched.\n";
// 1. Create a list of consecutive integers from 2 through n: (2, 3, 4, ..., n).
// The indices will represent the numbers and true or false will specify if a number is marked, meaning it is no prime.
int nMax {100};
cin >> nMax;
vector<int> baMarked(nMax+1); // Plus 1 because nMax should also be check if it is prime
// Initially, all numbers are not marked. Composite numbers are going to be marked true. Primes will stay false.
// This loop should not be necessary because vector is default initialized to false usually.
for (int nIdx = 0; nIdx < baMarked.size(); ++nIdx)
{
baMarked[nIdx] = false;
}
// 2. Initially, let p equal 2, the smallest prime number.
// 3. Enumerate the multiples of p by counting in increments of p from 2p to n,
// and mark them in the list (these will be 2p, 3p, 4p, ...; the p itself should not be marked).
// 4. Find the first number greater than p in the list that is not marked.
// If there was no such number, stop. Otherwise, let p now equal this new number (which is the next prime),
// and repeat from step 3.
int nMultiple {0};
for (int nNumber = 2; nNumber < nMax; ++nNumber)
{
// If the number is not marked (false), it is a prime number
if (false == baMarked[nNumber])
{
// Calculate all the multiples of that number and mark them as being a composite (not prime)
nMultiple = {2 * nNumber};
while (nMultiple <= nMax)
{
baMarked[nMultiple] = true;
nMultiple += nNumber;
}
}
}
// 5. When the algorithm terminates, the numbers remaining not marked in the list are all the primes below n.
cout << "The prime numbers between 1 and " << nMax << " are:\n";
for (int nNumber = 2; nNumber < nMax; ++nNumber)
{
if (!baMarked[nNumber])
cout << nNumber << " ";
}
cout << '\n';
return 0;
}
|
Output of the program for the input 50
is:
Enter an upper limit up to that primes are searched.
50
The prime numbers between 1 and 50 are:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
Exercise 15¶
Write a program that takes an input value n
and then finds the first n
primes.
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 52 53 54 | #include "std_lib_facilities.h"
// Check if the number can be divided by a prime number smaller than itself
bool IsPrime(int i_nNumber, vector<int> i_naPrimes)
{
for (int prime : i_naPrimes)
{
if (i_nNumber < prime || i_nNumber % prime == 0)
return false;
}
return true;
}
int main() {
vector<int> naPrimes {2};
cout << "Enter an integer greater than 1 that defines the number of primes from 1 to n that are searched.\n";
int nN;
bool bValidInput {false};
while (!bValidInput)
{
if (cin >> nN && nN > 1)
bValidInput = true;
else
cout << "Enter an integer greater than 1 (followed by 'Enter')\n";
}
int nNumber {1};
while (naPrimes.size() < nN)
{
if (IsPrime(nNumber, naPrimes))
{
naPrimes.push_back(nNumber);
}
nNumber++;
}
cout << "Found "<< nN << " prime numbers between 1 and " << naPrimes[naPrimes.size()-1] << ": \n";
int nPrime {2};
for (int nIdx = 0; nIdx < naPrimes.size(); ++nIdx)
{
nPrime = naPrimes[nIdx];
cout << nPrime << " ";
if ((nIdx+1) % 25 == 0) // Line break after 25 primes
cout << '\n';
}
cout << '\n';
return 0;
}
|
The output for 10
is :
Enter an integer greater than 1 that defines the number of primes from 1 to n that are searched.
10
Found 10 prime numbers between 1 and 29:
2 3 5 7 11 13 17 19 23 29
Exercise 16¶
In the drill, you wrote a program that, given a series of numbers, found the max and min of that series. The number that appears the most times in a sequence is called the mode. Create a program that finds the mode of a set of positive integers.
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 | #include "std_lib_facilities.h"
int main() {
cout << "Enter a series of positive integer values to get the mode (To finish, enter '|' or a another non integer character):\n";
vector<int> naValues;
for (int nValue; cin >> nValue; )
naValues.push_back(nValue);
sort(naValues); // sort series
// compute mode of the entered series:
int nCount {1};
int nMaxCount {1};
int nMode {0};
int nPrev {naValues[0]};
for (int nIdx = 1; nIdx < naValues.size(); ++nIdx)
{
// update the number count if the previous value is the same as the current one.
if (nPrev == naValues[nIdx])
{
nCount++;
} else {
nCount = 1; // reset counter if the current value is different than the previous one.
}
// update the mode if necessary
if (nMaxCount < nCount)
{
nMode = naValues[nIdx];
nMaxCount = nCount;
}
nPrev = naValues[nIdx];
}
cout << "The mode of the series is " << nMode << " with " << nMaxCount << " appareances.\n";
return 0;
}
|
Here are some inputs and the resulting output:
Enter a series of positive integer values to get the mode (To finish, enter '|' or a another non integer character):
1 2 3 3 4 5 6 7 8 8 8 9 10 11 |
The mode of the series is 8 with 3 appareances.
Enter a series of positive integer values to get the mode (To finish, enter '|' or a another non integer character):
1 5 4 2 2 8 7 9 |
The mode of the series is 2 with 2 appareances.
Enter a series of positive integer values to get the mode (To finish, enter '|' or a another non integer character):
30 60 20 1 2 1 1 2 60 80 50 20 |
The mode of the series is 1 with 3 appareances.
In case of two numbers having equal frequencies, the smaller one is picked because of the sorting.
Enter a series of positive integer values to get the mode (To finish, enter '|' or a another non integer character):
2 2 1 1 1 3 3 3 |
The mode of the series is 1 with 3 appareances.
Exercise 17¶
Write a program that finds the min, max, and mode of a sequence of string
s.
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 | #include "std_lib_facilities.h"
int main() {
cout << "Enter a sequence of strings to get the min, max and mode (To finish, press Ctrl-D):\n";
vector<string> straWords;
for (string strWord; cin >> strWord; )
straWords.push_back(strWord);
sort(straWords); // sort sequence
// get the min and max of the entered sequence:
string strMin {straWords[0]}; // first entry is the "minimum"
string strMax {straWords[straWords.size()-1]}; // last entry is the "maximum"
// compute mode of the entered sequence:
int nCount {1};
int nMaxCount {1};
string nMode {" "};
string nPrev {straWords[0]};
for (int nIdx = 1; nIdx < straWords.size(); ++nIdx)
{
// update the number count if the previous value is the same as the current one.
if (nPrev == straWords[nIdx])
{
nCount++;
} else {
nCount = 1; // reset counter if the current value is different than the previous one.
}
// update the mode if necessary
if (nMaxCount < nCount)
{
nMode = straWords[nIdx];
nMaxCount = nCount;
}
nPrev = straWords[nIdx];
}
cout << "The min of the sequence is " << strMin << " and the max is " << strMax << '\n';
cout << "The mode of the sequence is " << nMode << " with " << nMaxCount << " appareances.\n";
return 0;
}
|
Example output is:
Enter a sequence of strings to get the min, max and mode (To finish, press Ctrl-D):
moon
sun
earth
moon
saturn
^D
The min of the sequence is earth and the max is sun
The mode of the sequence is moon with 2 appareances.
Note that I needed to run this program in the debugger to get an output using Ctrl-D. This seems to be a bug (maybe in the C++ implementation of mac os?).
Exercise 18¶
Write a program to solve quadratic equations. A quadratic equation is of the form
ax2 + bx + c = 0
If you don’t know the quadratic formula for solving such an expression, do some research.
Remember, researching how to solve a problem is often necessary before a programmer can teach the computer how to solve it.
Use double
s for the user inputs for a
, b
, and c
. Since there are two solutions to a quadratic equation,
output both x1
and x2
.
The quadratic equation and its derivation can be found at Wikipedia.
Enter the coefficients 'a', 'b' and 'c' as double to get the results of a quadratic equation (Followed by 'Enter'):
1 3 1
The solution of 1x^2 + 3x + 1 = 0 is real:
x1 = -0.381966
x2 = -2.61803
Check also that the result is correct using `wolfram alpha <https://www.wolframalpha.com/input/?i=1x%5E2+%2B+3*x+%2B+1+%3D+0>`_
Another example from `Wikipedia <https://en.wikipedia.org/wiki/Quadratic_equation#Completing_the_square>`_\ :
Enter the coefficients 'a', 'b' and 'c' as double to get the results of a quadratic equation (Followed by 'Enter'):
2 4 -4
The solution of 2x^2 + 4x + -4 = 0 is real:
x1 = 0.732051
x2 = -2.73205
The program is also able to compute imaginary solutions (\ `wolfram alpha <https://www.wolframalpha.com/input/?i=x%5E2+%2B+2*x+%2B+3+%3D+0>`_\ ):
Enter the coefficients 'a', 'b' and 'c' as double to get the results of a quadratic equation (Followed by 'Enter'):
1 2 3
The solution of 1x^2 + 2x + 3 = 0 is imaginary:
x1 = -1 + 1.41421i
x2 = -1 - 1.41421i
Exercise 19¶
Write a program where you first enter a set of name-and-value pairs, such as Joe 17
and Barbara 22
.
For each pair, add the name to a vector
called names
and the number to a vector
called scores
(in corresponding positions, so that if names[7]=="Joe"
then scores[7]==17
). Terminate input with NoName 0
.
Check that each name is unique and terminate with an error message if a name is entered twice.
Write out all the (name,score) pairs, one per line.
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 | #include "std_lib_facilities.h"
bool Duplicate(string i_strName, vector<string> i_straNames)
{
for (string strName : i_straNames)
{
if (strName == i_strName)
{
return true;
}
}
return false;
}
int main() {
cout << "Enter a set of name-and-value pairs, such as 'Joe 17' and 'Barbara 22 (Terminate the input using 'NoName 0' followed by 'Enter'):\n";
string strName {" "};
int nScore {0};
vector<string> straNames(0);
vector<int> naScores(0);
bool bDuplicate {false};
while (!bDuplicate && (cin >> strName >> nScore) && ("NoName" != strName || 0 != nScore)) // Terminate input with NoName 0
{
// Check that each name is unique and terminate with an error message if a name is entered twice.
if (Duplicate(strName, straNames))
{
cout << "Duplicate detected! Names must be unique.\n";
bDuplicate = true;
// return -1; // depending on what terminate means (terminate program or terminate input?)
}
else
{
straNames.push_back(strName);
naScores.push_back(nScore);
}
}
// Write out all the (name,score) pairs, one per line.
for (int nIdx = 0; nIdx < straNames.size(); ++nIdx)
{
cout << "(" << straNames[nIdx] << "," << naScores[nIdx] << ")\n";
}
return 0;
}
|
The program results in the following:
Enter a set of name-and-value pairs, such as 'Joe 17' and 'Barbara 22 (Terminate the input using 'NoName 0' followed by 'Enter'):
Joe 17
Barbara 22
NoName 0
(Joe,17)
(Barbara,22)
In the case of a duplicate name the output is:
Enter a set of name-and-value pairs, such as 'Joe 17' and 'Barbara 22 (Terminate the input using 'NoName 0' followed by 'Enter'):
Joe 17
Barbara 22
Joe 18
Duplicate detected! Names must be unique.
(Joe,17)
(Barbara,22)
Notice, to finish, the user needs to entery NoName 0
exactly:
Enter a set of name-and-value pairs, such as 'Joe 17' and 'Barbara 22 (Terminate the input using 'NoName 0' followed by 'Enter'):
Joe 17
Barbara 22
John 21
NoName 1
NoName 0
(Joe,17)
(Barbara,22)
(John,21)
(NoName,1)
Exercise 20¶
Modify the program from exercise 19 so that when you enter a name, the
program will output the corresponding score or name not found
.
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | #include "std_lib_facilities.h"
bool Duplicate(string i_strName, vector<string> i_straNames)
{
for (string strName : i_straNames)
{
if (strName == i_strName)
{
return true;
}
}
return false;
}
void PrintName(string i_strName, vector<string> i_straNames, vector<int> i_naScores)
{
for (int nIdx = 0; nIdx < i_straNames.size(); ++nIdx)
{
if (i_straNames[nIdx] == i_strName)
{
cout << "Score for " << i_strName << " is " << i_naScores[nIdx] << '\n';
return;
}
}
cout << "name not found\n";
return;
}
int main() {
cout << "Enter a set of name-and-value pairs, such as 'Joe 17' and 'Barbara 22 (Terminate the input using 'NoName 0' followed by 'Enter'):\n";
string strName {" "};
int nScore {0};
vector<string> straNames(0);
vector<int> naScores(0);
bool bDuplicate {false};
while (!bDuplicate && (cin >> strName >> nScore) && ("NoName" != strName || 0 != nScore)) // Terminate input with NoName 0
{
// Check that each name is unique and terminate with an error message if a name is entered twice.
if (Duplicate(strName, straNames)) {
cout << "Duplicate detected! Names must be unique.\n";
bDuplicate = true;
// return -1; // depending on what terminate means (terminate program or terminate input?)
} else {
straNames.push_back(strName);
naScores.push_back(nScore);
}
}
cout << "\nThe entered names are:\n";
// Write out all the (name,score) pairs, one per line.
for (int nIdx = 0; nIdx < straNames.size(); ++nIdx)
{
cout << "(" << straNames[nIdx] << "," << naScores[nIdx] << ")\n";
}
cout << "\nWrite a name to get the score: ";
while (cin >> strName)
{
PrintName(strName, straNames, naScores);
cout << "Write a name to get the score: ";
}
return 0;
}
|
Enter a set of name-and-value pairs, such as 'Joe 17' and 'Barbara 22 (Terminate the input using 'NoName 0' followed by 'Enter'):
Joe 17
Barbara 22
NoName 0
The entered names are:
(Joe,17)
(Barbara,22)
Write a name to get the score: Joe
Score for Joe is 17
Write a name to get the score: Barbara
Score for Barbara is 22
Write a name to get the score: John
name not found
Write a name to get the score: ^D
Exercise 21¶
Modify the program from exercise 19 so that when you enter an integer,
the program will output all the names with that score or score not found
.
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 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 | #include "std_lib_facilities.h"
bool Duplicate(string i_strName, vector<string> i_straNames)
{
for (string strName : i_straNames)
{
if (strName == i_strName)
{
return true;
}
}
return false;
}
void PrintName(string i_strName, vector<string> i_straNames, vector<int> i_naScores)
{
for (int nIdx = 0; nIdx < i_straNames.size(); ++nIdx)
{
if (i_straNames[nIdx] == i_strName)
{
cout << "Score for " << i_strName << " is " << i_naScores[nIdx] << '\n';
return;
}
}
cout << "name not found\n";
return;
}
void PrintScoreNames(int i_nScore, vector<string> i_straNames, vector<int> i_naScores)
{
bool bScoreFound {false};
for (int nIdx = 0; nIdx < i_naScores.size(); ++nIdx)
{
if (i_naScores[nIdx] == i_nScore)
{
cout << i_straNames[nIdx] << '\n';
bScoreFound = true;
}
}
if (!bScoreFound)
cout << "No name with that score " << i_nScore << '\n';
return;
}
int main() {
cout << "Enter a set of name-and-value pairs, such as 'Joe 17' and 'Barbara 22 (Terminate the input using 'NoName 0' followed by 'Enter'):\n";
string strName {" "};
int nScore {0};
vector<string> straNames(0);
vector<int> naScores(0);
bool bDuplicate {false};
while (!bDuplicate && (cin >> strName >> nScore) && ("NoName" != strName || 0 != nScore)) // Terminate input with NoName 0
{
// Check that each name is unique and terminate with an error message if a name is entered twice.
if (Duplicate(strName, straNames)) {
cout << "Duplicate detected! Names must be unique.\n";
bDuplicate = true;
// return -1; // depending on what terminate means (terminate program or terminate input?)
} else {
straNames.push_back(strName);
naScores.push_back(nScore);
}
}
cout << "\nThe entered names are:\n";
// Write out all the (name,score) pairs, one per line.
for (int nIdx = 0; nIdx < straNames.size(); ++nIdx)
{
cout << "(" << straNames[nIdx] << "," << naScores[nIdx] << ")\n";
}
cout << "\nWrite a score to get the names with that score: ";
while (cin >> nScore)
{
PrintScoreNames(nScore, straNames, naScores);
cout << "Write a score to get the names with that score: ";
}
return 0;
}
|
The result of this program is:
Enter a set of name-and-value pairs, such as 'Joe 17' and 'Barbara 22 (Terminate the input using 'NoName 0' followed by 'Enter'):
Joe 18
Barbara 18
John 22
NoName 0
The entered names are:
(Joe,18)
(Barbara,18)
(John,22)
Write a score to get the names with that score: 18
Joe
Barbara
Write a score to get the names with that score: 20
No name with that score 20
Write a score to get the names with that score: 0
No name with that score 0
Write a score to get the names with that score: 22
John
Write a score to get the names with that score: ^D