Hunter Liu's Website

19. Week 11: Final Exam

≪ 18. Week 10 Thursday: Pointers | Table of Contents

Here’s a brief recap of everything you need to know in preparation for the final exam this week! You can find details on each topic in the preceeding notes or on the class lecture slides.

Again, this is not a comprehensive list, and this may not be representative of the material covered by the exam. I just put together some topics that I think are (generally) important to watch out for.

A Common Coding Error

I have seen variants of this mistake in homework assignments, and it’s actually quite a subtle bug. In preparation for the final (and for when you code in the future), I think it’s important that you’re all aware of what’s going on.

Consider the following code, which attempts to replace occurrences of the letter a with a #. A user’s input adam would be converted to #d#m, hopefully.

 1#include <string> 
 2#include <iostream> 
 3
 4using namespace std; 
 5
 6int main() {
 7    string input; 
 8    cin >> input; 
 9
10    // loops through all of the characters in the
11    // user's input. If there's a lowercase 'a', 
12    // replace it with a '#'
13    for(int i = 0; i < input.size(); i++) {
14        char c = input.at(i); 
15
16        if(c == 'a') {
17            c = '#'; 
18        }
19    }
20
21    cout << input << endl; 
22    return 0; 
23}

The issue is that line 14 makes a copy of the character at index i. On line 17, this copy is overwritten with a #, but the user’s input string remains unchanged! In other words, the variable c and the variable input are completely separate — what happens to one is not “seen” by the other.

Here’s another variant of this error. This code is more involved — it has a string function that converts a string to all uppercase, and the main function attempts to convert all of a user’s inputs to full uppercase.

 1#include <string> 
 2#include <iostream> 
 3#include <vector> 
 4
 5using namespace std; 
 6
 7// takes a string as an argument, then converts all of its 
 8// characters to uppercase. 
 9void to_upper(string s) {
10    for(int i = 0; i < s.length(); i++) {
11        if(s.at(i) >= 'a' && s.at(i) <= 'z') {
12            s += 'A' - 'a'; 
13        }
14    }
15} 
16
17int main() {
18    // take a bunch of string inputs from the user 
19    int n; 
20    cin >> n; 
21
22    vector<string> inputs; 
23    for(int i = 0; i < n; i++) {
24        string temp; 
25        cin >> temp; 
26        inputs.push_back(temp); 
27    }
28
29    // convert all of the user's inputs to uppercase. 
30    for(int i = 0; i < inputs.size(); i++) {
31        to_upper(inputs.at(i)); 
32    }
33
34    // print everything out again 
35    for(int i = 0; i < inputs.size(); i++) {
36        cout << inputs.at(i) << endl; 
37    } 
38
39    return 0; 
40}

Similar to the first example, the to_upper function makes a copy of inputs.at(i) every time line 31 is run. Although the to_upper function modifies the string correctly, it’s modifying a copy of the string that was given to it. This change is not reflected in the main function. The fix, of course, is to make to_upper use pass-by-reference!