Chapter 4 - Computation

Drill

  1. Write a program that consists of a while-loop that (each time around the loop) reads in two ints and then prints them. Exit the program when a terminating '|' is entered.
loop01.cpp
 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
  1. Change the program to write out the smaller value is: followed by the smaller of the numbers and the larger value is: followed by the larger value.
loop02.cpp
 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

  1. Augment the program so that it writes the line the numbers are equal (only) if they are equal.
loop03.cpp
 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
  1. Change the program so that it uses doubles instead of ints.
loop04.cpp
 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
  1. 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.
loop05.cpp
 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.
  1. 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, write the smallest so far after the number. If it is the largest so far, write the largest so far after the number.
loop06.cpp
 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.
  1. Add a unit to each double entered; that is, enter values such as 10cm, 2.5in, 5ft, or 3.33m. Accept the four units: cm, m, in, ft. Assume conversion factors 1m == 100cm, 1in == 2.54cm, 1ft == 12in. Read the unit indicator into a string. You may consider 12 m (with a space between the number and the unit) equivalent to 12m (without a space).
loop07.cpp
  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.

  1. Reject values without units or with “illegal” representations of units, such as y, yard, meter, km, and gallons.
loop08.cpp
  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
  1. 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.
loop09.cpp
  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
  1. Keep all the values entered (converted into meters) in a vector. At the end, write out those values.
loop10.cpp
  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
  1. Before writing out the values from the vector, sort them (that’ll make them come out in increasing order).
loop11.cpp
  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

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

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

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

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

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

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

  1. 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 dont 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
    // ...
}
  1. 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.

  1. 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 /, %, +, -
  1. What operators can be used on integers but not on floating-point numbers?
  Name Comment
a%b modulo (remainder) only for integer types
  1. 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
  1. When would a programmer prefer a switch-statement to an if-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 a string.
  • 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.
  1. 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;
    }
}
  1. 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.

  1. When should the for-loop be used and when should the while-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.

  1. 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')).

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

  1. 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
  1. What can you do to an int that you cannot do to a string?

The following operators can be applied to an int but not to a string.

  1. What can you do to a string that you cannot do to an int?
  1. 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];
  1. How do you write a for-loop that prints every element of a vector?

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.

  1. 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 ""
  1. 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 )
  1. What do vector’s member functions begin(), end(), and size() 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).

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

  1. 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 in std_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 library vectors (§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 in std_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 library vectors (§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 called i
  • 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 a string.
  • 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

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

currencyconverter.cpp
 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
CharacterLoop.cpp
 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().

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

bleep.cpp
 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:

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

meanmedian.cpp
 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
meanmedianexact.cpp
 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.

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

numberguessing.cpp
 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.
numberguessingMax7.cpp
 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.

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

digitconverter.cpp
 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
digitconverterextended.cpp
 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.

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

chessgrains.cpp
 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)?

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

rockpaperscissors.cpp
  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 vector 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 vector. 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.

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

primesmax.cpp
 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:

  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.
sieveoferatosthenes_simple.cpp
 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:

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

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

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

mode.cpp
 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 strings.

modestrings.cpp
 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 doubles 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.

name-and-value_pairs.cpp
 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.

name-and-value_pairs-name-score-output.cpp
 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.

name-and-value_pairs-score-to-names-output.cpp
 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