Lab 00 Feedback¶

Click <shift> <enter> in each code cell to run the code. Be sure to start with the #include directives to load the required libraries.

Preprocessor Directives¶

An #include directive is not a C++ statement; it is a preprocessor directive. It is an instruction to the compiler to include a file or library before compiling. Since it is not a C++ statement, it should not end with a semicolon.

In [1]:
#include <iostream> // does not end with a semicolon
#include <string>
#include <limits>

Array Indexing¶

Indexing starts at position 0, not 1. So, the first element of a 5 element array is at index 0, and the fifth (or last) element is at index 4.

In [2]:
int arr[5] = {1, 2, 3, 4, 5};

    std::cout << "Printing 5 array elements (indexes 0 to 4):" << std::endl;
    for (int i = 0; i < 5; i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl << std::endl;
Printing 5 array elements (indexes 0 to 4):
1 2 3 4 5 

The above loop iterates from 0 to 4 (5 iterations). The middle part of the loop (i < 5) is like a while loop condition. We loop while i is less than 5, so when i++ makes i equal to 5, the loop is not entered again.

If we say i <= 5, the loop will run past the end of the array.

// Index: 0  1  2  3  4      5  
arr[5] = {1, 2, 3, 4, 5}; //__ <-- Invalid memory access.

Reading Input with std::cin And std::getline¶

When using std::cin to read data from the console, the input is space delimited. This means that the input is read until a white space character like space or newline is encountered.

In [3]:
std::cout << "Understanding std::cin and std::getline" << std::endl;
std::string first_name;
std::string last_name;
std::cout << "Enter your first and last name: ";
std::cin >> first_name >> last_name;
std::cout << "Hello, " << first_name << " " << last_name << "." << std::endl;
Understanding std::cin and std::getline
Enter your first and last name: 
Hello, John Smith.

If we prompt for a name and age, and the user's name includes a space, the input will be split at the space.

In [4]:
std::string name;
int age = 0;
std::cout << "Enter your name and age: ";
std::cin >> name >> age;
std::cout << "Hello, " << name << ". You are " << age << " years old." << std::endl;
Enter your name and age: 
Hello, John. You are 25 years old.

Since age is an integer, if the user enters a non-integer value, std::cin will enter a fail state. We will have broken the input stream.

Try entering Mary Jane 25, and see what happens.

Since some names do include white space, we can use std::getline() to read an entire line of input, including white space.

In [5]:
std:: cout << "Enter your first name: ";
std::cin >> first_name;
std::cout << "Hello, " << first_name << "." << std::endl;

// With the std::cin.ignore line commented out, do we foresee any issues?
// std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Clear the input stream
    
std::cout << "Now enter your full name: ";
std::getline(std::cin, name);
std::cout << "Hello, " << name << ".\nHave a good day." << std::endl << std::endl;
Enter your first name: 
Hello, John.
Now enter your full name: Hello, .
Have a good day.

When using std::cin >> before std::getline(), what has happened to the input stream?
We seemed to have skipped the std::getline() input. Why?

cin stops reading at white space and does not consume the newline character.
getline() generally reads to the end of the line and does consume the newline character.

For example:

  • The user is prompted for a first name.
  • The user types Mary, and the presses <enter>.
  • The <enter> key inserts a newline character in the input stream.
  • The user is prompted for a full name.
  • The getline() function sees the newline character and thinks the input was an empty string.

Let's try the above example again, but use std::cin.ignore() to clear the input stream.

In [6]:
std:: cout << "Enter your first name: ";
std::cin >> first_name;
std::cout << "Hello, " << first_name << "." << std::endl;

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Clear the input stream
    
std::cout << "Now enter your full name: ";
std::getline(std::cin, name);
std::cout << "Hello, " << name << ".\nHave a good day." << std::endl << std::endl;
Enter your first name: 
Hello, John.
Now enter your full name: 
Hello, John Smith.
Have a good day.

Using a Loop to Print Even Numbers from 1 to 100¶

How many times does this loop iterate?

In [7]:
std::cout << "Printing even integers from 1 to 100:" << std::endl;

for (int i = 1; i <= 100; i++) {
    
    if (i % 2 == 0) {
        std::cout << i << " ";
    }
}
std::cout << std::endl << std::endl;
Printing even integers from 1 to 100:
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 

The loop iterates 100 times and at each iteration, it checks if the current i value is even.
But do we have to evaluate every consecutive integer to discover whether it's even?

How many times does this next loop iterate?

In [8]:
for (int i = 2; i <= 100; i += 2) {
    std::cout << i << " ";
}
std::cout << std::endl << std::endl;
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 

This second loop calculates the same correct result, while doing half as much work.

Using the MOD or REMAINDER Operator % to Print n Elements Per Line¶

Attempt 1¶

In [9]:
int n = 10;

// Print the indexes, 10 per line.
// But this isn't quite correct. What's wrong?
std::cout << "First attempt to print 10 indexes per line:" << std::endl;
for (int i = 0; i < 100; i++) {
    std::cout << i << " ";
    if (i % n == 0) {
        std::cout << std::endl;
    }
}
std::cout << std::endl << std::endl;
First attempt to print 10 indexes per line:
0 
1 2 3 4 5 6 7 8 9 10 
11 12 13 14 15 16 17 18 19 20 
21 22 23 24 25 26 27 28 29 30 
31 32 33 34 35 36 37 38 39 40 
41 42 43 44 45 46 47 48 49 50 
51 52 53 54 55 56 57 58 59 60 
61 62 63 64 65 66 67 68 69 70 
71 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 

But this isn't quite correct. What's wrong?
Zero is printed alone on the first line.

0 mod 10 = 0  // <-- The remainder is 0, but we don't want a newline right at the start.
1 mod 10 = 1
2 mod 10 = 2
3 mod 10 = 3
4 mod 10 = 4
5 mod 10 = 5
6 mod 10 = 6
7 mod 10 = 7
8 mod 10 = 8
9 mod 10 = 9
10 mod 10 = 0  // <-- Here is where we want to print our first newline.

Attempt 2¶

In [10]:
std::cout << "Second attempt to print 10 indexes per line:" << std::endl;
    n = 10;
    for (int i = 0; i < 100; i++) {
        std::cout << i << " ";
        if (i+1 % n == 0) {
            std::cout << std::endl;
        }
    }
    std::cout << std::endl << std::endl;
Second attempt to print 10 indexes per line:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 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 

This also isn't what we want. What's wrong?
Everything is printed on the same line.

Attempt 3¶

In [11]:
// Let's try one more time.
std::cout << "Third attempt to print 10 indexes per line:" << std::endl;
n = 10;
for (int i = 0; i < 100; i++) {
    std::cout << i << " ";
    if ((i + 1) % n == 0) { // Why does this change matter?
        std::cout << std::endl;
    }
}
std::cout << std::endl << std::endl;
Third attempt to print 10 indexes per line:
0 1 2 3 4 5 6 7 8 9 
10 11 12 13 14 15 16 17 18 19 
20 21 22 23 24 25 26 27 28 29 
30 31 32 33 34 35 36 37 38 39 
40 41 42 43 44 45 46 47 48 49 
50 51 52 53 54 55 56 57 58 59 
60 61 62 63 64 65 66 67 68 69 
70 71 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 


Operator % has precedence over operator +. So, i + 1 % n is interpreted as i + (1 % n), not (i + 1) % n.

0 + (1 % 10) = 1     (0 + 1) % 10 = 1
1 + (1 % 10) = 2     (1 + 1) % 10 = 2
2 + (1 % 10) = 3     (2 + 1) % 10 = 3
3 + (1 % 10) = 4     (3 + 1) % 10 = 4
4 + (1 % 10) = 5     (4 + 1) % 10 = 5
5 + (1 % 10) = 6     (5 + 1) % 10 = 6
6 + (1 % 10) = 7     (6 + 1) % 10 = 7
7 + (1 % 10) = 8     (7 + 1) % 10 = 8
8 + (1 % 10) = 9     (8 + 1) % 10 = 9
9 + (1 % 10) = 10    (9 + 1) % 10 = 0

Because 1 % 10 = 1, i + (1 % 10) is always just i + 1.