Hunter Liu's Website

1. Week 1 Tuesday: Errors

Table of Contents | 2. Week 1 Thursday: Integer Operations ≫

Creating a program loosely follows this pipeline of events: one comes up with pseudocode, writes C++ code based on the pseudocode, and then the compiler turns it into instructions for your computer to follow.

We’ll discuss pseudocode in greater length in the near future, when our programs become slightly more sophisticated than setting a few variables and printing a few things out to the screen. Our focus for today is instead on everything that can possibly go wrong in this pipeline.

Three Types of Errors

Let’s think about the ways in which someone can make mistakes when speaking or writing English. One can break this up into (roughly) three categories:

  1. Mechanical or syntactic errors: using words that don’t exist, improper usage of punctuation marks, and non-English glyphs or symbols are all examples of this. The person making these errors is likely trying to convey some meaning, but that meaning is lost behind these errors.
  2. Semantic errors: when someone says a sentence that “locally resembles” English, but cannot be globally resolved into something of real meaning. They might be using real English words with perfect grammar, but the order of these words may be nonsensical. (The blue eats “solemnly” bound tibula.)
  3. Communication errors: Perhaps the speaker says something with perfect grammar, and the words do produce real meaning. However, it’s still possible that the meaning produced does not line up with what the speaker intended to say. Perhaps the tone or connotation of the message was unexpected, or perhaps someone forgot about an Oxford comma. (I love my dogs, Jamie Fox and Ryan Reynolds.)

In much the same way, programmers can make analogous errors when trying to write C++. One should envision the programmer having a dialogue with the computer, and the three “layers” of errors represent three different stages at which issues can arise. Let’s recap what those are:

  1. Build errors
    The analogue of mechanical errors. This is when the compiler cannot understand the code you have written for one reason or another. In other words, a syntax error occurs when you have written invalid code; your intentions are lost behind the constraints of the language.
  2. Runtime errors
    This is when the compiler can understand the code you have written line-by-line, and it can even produce a set of instructions for the computer to run. However, when it goes and performs these instructions, the program crashes, bricks your computer, or asks the computer to do something it’s not allowed to do.
  3. Logical errors
    It’s possible that you’ve written impeccable code that your compiler understands and which will not destroy your computer. Nevertheless, what the code does may not line up with your intentions.

One can think about build errors as problems that occur in the “C++ Code to Machine Instructions” step of the pipeline, and of logical errors as problems that arise in the “Pseudocode to C++ Code” step of the pipeline. We don’t know enough C++ to really cause runtime or logical errors (even deliberately), but we can discuss the millions of syntax errors that we may run into.

Build Errors

C++ is a very limited language. The list of words that C++ compilers understand by default is extremely small; they fit on a single computer screen at this webpage. Of course, these words must come accompanied with some grammar — think about the curly braces around the main function, or the semicolons that end almost every line of code.

Notice that cout and endl aren’t there; not even main is there. This is because some very smart people wrote a library of code for other C++ programmers to use called the iostream library, and this teaches C++ words such as cout and endl (together with some grammatical rules) which, in turn, allow you and I to print “Hello World” to the screen.

This brings us to the first examples of build errors: when you try to use words that your C++ compiler doesn’t know. Let’s try running the following program and see what happens:

1int main() {
2    cout << "Hello world!" << endl; 
3    return 0; 
4} 

My compiler tells me, “main.cpp:2:5: error: ‘cout’ was not declared in this scope”. Pay attention to the little blurb at the front — it tells you exactly where it ran into the error (though this may take a different form in your IDE). This error happened in the main.cpp file on line 2 and character 5.

This is because we didn’t tell the compiler that we’re borrowing code from the iostream library!

1#include <iostream> 
2
3int main() {
4    cout << "Hello world!" << endl; 
5    return 0; 
6} 

My compiler still tells me that it has no clue what cout means. One of the great things about C++ is that it has a great number of libraries, but this is a double-edged sword: the word cout may mean one thing in the iostream library, but what’s to stop some other dude from defining cout to mean or do something else? What if you desperately needed to use the word cout yourself?

The solution was the creation of namespaces. One can think of this as a context in which to interpret the meaning of a word: for instance, the word “cell” means something different in biological and penitentiary contexts; “He swabbed the cells.” has a rather distinct meaning depending on the context.

The std namespace is the “standard” namespace, and it refers to the contents of the “C++ standard library”. C++ by default wants you to specify which context you are using cout in, but the line using namespace std; tells the compiler that everything in the std namespace will be in use.

1#include <iostream> 
2
3using namespace std; 
4
5int main() {
6    cout << "Hello world!" << endl; 
7    return 0; 
8} 

This code should now compile correctly!

Practise Problems

Here are a few practise problems to get us going. None of these code snippets compile; fix the code without breaking the intended functionality described in the comments. Try to build the faulty code, even without fixing the issues, and see if you can understand what the compiler’s error messages are telling you.

If you’re very astute, you may occassionally realise that the colours in your editor get a little wonky. That’s usually a pretty good sign that something’s wrong.

Problem 1.

 1#include <iostream>
 2
 3using namespace std;
 4
 5int main() {
 6    // prints "hello world" to the screen
 7    cout << "Hello World!" << endl;
 8
 9    return "0";
10}

Problem 2.

 1#include <iostream>
 2
 3using namespace std;
 4
 5int main() {
 6    // makes an integer containing my age, then
 7    // describes the age of my mother, who is twice as
 8    // old as i am.
 9    int my age = 37;
10    cout << "My mother is " << my age << " years old!" << endl;
11
12    return 0;
13}

Problem 3.

 1#include <iostream>
 2
 3using namespace std;
 4
 5int main() {
 6    // prints out the size of this PIC10A class.
 7    int class = 30;
 8    cout << "There are " << class << 
 9        " students in my PIC10A class. " << endl;
10
11    return 0;
12}

Problem 4.

 1#include <isotream>
 2
 3using namespace std;
 4
 5int main() {
 6    // converts the quantity "461 minutes" into a better
 7    // format.
 8    int minutes = 461;
 9    cout << minutes << " minutes." << endl;
10
11    int hours = 7;
12    int minutes = 461 - 7 * 60;
13    cout << "That's also " << hours << " hours and "
14         << minutes << " minutes." << endl;
15
16    return 0;
17}

Problem 5.

 1#include <iostream>
 2
 3using namespace std;
 4
 5int main() {
 6    // prints out the current date
 7    int year = 2024, month = 10, day = 01;
 8    cout << Today's date: 
 9         << month << "/" << day << "/" << year << endl;
10
11    return 0;
12}

Problem 6.

 1#include <iostream> 
 2
 3using namespace std;
 4
 5int Main() {
 6    // prints out my monthly and annual income 
 7    int annual = 12000; 
 8    cout << "Annual salary: " << annual << endl; 
 9    cout << "Monthly salary: " << annual / 12 << endl; 
10
11    return 0; 
12}