Department of Engineering

1B C++ Computing

C++

Documentation for IB Computing Exercises

Contents

This course consists of 4 problems and 4 lab sessions. You should try to complete the first problem in the first lab session, and the second problem in the second lab session, and so on. You can begin the work before the start of the lab session if you want to. The lab sessions are compulsory and there are penalties for lateness. All problems are worth 4 marks.You need 12 marks to qualify. When you think you have the correct answer to a problem, call your demonstrator over to mark your work.

The CUED Tutorial Guide to C++ Programming has more details about the language.

Editor and Development Environment

C++ source files are plain text, so you may use any text editor you wish (or use the geanyicon program you used in the first year), but these instructions assume you'll use Emacs, a standard editor. You'll compile your programs at the command line.

Clicking on the Start 1BComputing icon created a 1BC++ folder for you - a place to keep your source files for this course. To start editing a file called foo.cc, first open a terminal window (command line interface) if you don't already have one. Then run Emacs, passing the file name as a command line parameter:

 emacs foo.cc &

The '&' tells the terminal to run Emacs in the background (so that you can still type in the terminal). You can use the menu bar and tool bar to manipulate files, or you can use keystrokes. Ctrl-x Ctrl-s saves the current file (called a 'buffer'), and Ctrl-x Ctrl-f allows you to open another file (or create a new file) by typing the name. Ctrl-x Ctrl-c quits Emacs. Tab correctly indents the current line.

Compiling and Running

After editing your program, you need to save the file and compile it before running it. Running

  g++ -Wall -o foo foo.cc

will compile foo.cc into executable foo, and print any errors or warnings (with line numbers). Once you have successfully compiled, you can then run the program:

  ./foo

To avoid typing the compiler options every time, you can create a file called Makefile in the current directory containing a single line of text. This will create the file:

  echo "CXXFLAGS= -Wall" > Makefile

Then you can compile any source file something.cc to executable something using the make system, which will invoke g++ automatically:

  make something

Input and Output

If your program reads from standard input (cin), you can either type the input on the terminal after running the program (pressing the Enter key after each line), or pipe the input into the program from a file.

To avoid typing the same input over and over, you can store your input text in a file (e.g. foo.in), and have your program read from the file (instead of from the keyboard):

   ./foo < foo.in

Likewise, your program will, by default, print standard output (cout) to the terminal. You can instead redirect the output to a file:

   ./foo > foo.out

Passing by reference

If you want a C++ function to modify an argument, pass it by reference (add '&' to the argument type):

   void value_func(int param) { param += 2; }
   void ref_func(int& param) { param += 2; }
   int main() {
      int x = 2;
      value_func(x); // x is still 2
      ref_func(x);   // x is now 4
   }

See the FAQ entry for more details.

The vector class

In the exercises, you will need to store variables in arrays with sizes that change at run time. The vector template class, part of the C++ Standard Library, is just this sort of collection. To declare a vector with elements of type double:

   vector<double> v;

The type of element that the vector holds is written between the triangle brackets. The vector declared above, holding elements of type double, is initially empty. You can...

  • get the number of elements in the vector with the size() member function:
       cout << v.size() << endl;
    
  • append an element onto the back of the vector using the push_back(...) member function:
       v.push_back(3.14); // increases v.size() by 1
       v.push_back(2.71); // increases v.size() by 1
    
  • access the elements of the vector using '[]' (the index of first element is 0):
       cout << v[0] << endl;
       v[1] = 1.68;
    
  • declare a vector with a known size:
       vector<int> some_ints(10);  // 10 int elements, uninitialized
    
  • specify a default value in the declaration:
       vector<double> some_reals(10, 0.0);  // 10 real numbers, all zero
    
  • loop through the vector forwards...
       for (unsigned int i=0; i<v.size(); ++i) {
         cout << v[i] << " ";
      }
    
  • ...or backwards:
       for (int i=v.size()-1; i>=0; --i) {
         cout << v[i] << " ";
       }
    

Using class

In C++, you can group multiple variables together into a named type by defining a class:

   class Person {
   public:
     string name;
     int age;
     double height, weight;
   };

You can access the fields, called members, using the '.' operator, and you can assign variables of the same class type to each other:

   Person a, b;        // declare two variables of type Person
   a.name = "Foo Bar";
   a.weight = 70.0;
   a.height = 1.5;
   a.age = 21;
   b = a;              // all members of a are assigned from b
   cout << b.name <<  " is " <<  b.age <<  " years old, "
      <<  b.height <<  "m tall, and weighs " <<  a.weight <<  "kg" <<  endl;

You can pass class types to functions, and use them as return values. You can also declare a vector with class elements:

   vector<Person> people(7);
   people[3].age = 47;

Syntax of for loops

The for loop is an extremely flexible but occasionally confusing control structure:

   for  (initialiser ;  condition ; post) 
      body

It has four parts:

  • initializer: a statement that is executed exactly once before the loop begins
  • condition: an expression evaluated before each iteration of the loop; when condition is false, the loop ceases
  • body: a statement (terminated with ';') or block of statements (inside curly braces `{' ... `}') executed at each iteration
  • post: a statement executed after each iteration of body, before condition is reevaluated

Thus the above for loop is shorthand for this while loop:

   initialiser;
   while (condition)
   { 
     body
     post;
   }

Example for loops

Often you want an integer index to loop through consecutive range of values (for instance, for iterating through the elements of an array or vector).

  • What are the bounds of the interval? For instance, when looping through an array or vector with n elements, the interval covered by the index is [0,n), which is the same as [0,n-1].
  • Should the index go from low to high (forwards) or from high to low (backwards)?

The intialiser, condition, and post statement are determined by the answers to these questions.

A forward loop with index i covering the half-open interval [0,n):

   for  (int i = 0; i < n;  ++i) {
      ...
   }

A backward loop with index i covering the half-open interval [0,n):

   for(int i = n-1; i >= 0; --i)
   {
      ...
   }

A forward loop with index i covering numbers less than sqrt(n) :

   for (int i = 0; i*i < n;  ++i)
   { 
      ...
   }

A forward loop with index i covering even numbers up to and including n:

   for(int i = 0; i <= n;  i += 2)
   {
      ...
   }

A forward loop with index i over all elements of a vector called v:

   for(unsigned int i = 0; i < v.size();  ++i)
   {
      // current element is v[i]
   }

Exercises

Further Reading