w w w . a q u a m e n t u s . c o m
Programming languages >> C++ programming [ overview ] [ OOP ] [ makefiles ] [ debugging ]

Overview

         Initial note: this is under construction, and I don't particularly like the layout anyway (it's carried over from undergrad days). You're warned..

         I've chosen C++ as my language of choice for two reasons: because it's what I'm most comfortable with, and because it's very widely used. I'm a game and graphics programmer at heart, so I'll explain a lot of things from a graphics standpoint.

         C++ is a very structured language. Variables require declaration (but you can declare them anywhere before you use them). There are procedures and functions, but to C++ they are all functions (procedures are a just functions with no return value). The execution of a C++ program begins at dawn, to be carried out this fourteenth day of--oh, wait, wrong context of "execution". The computer starts executing C++ code by calling the function main().

         The smallest C++ program that will compile (and of course not do anything) is this:

main() {
  return 0;
}

         So that, then, is the skeleton for all C++ programs. Here's a much more general outline for larger C++ programs:

#include < header_file.h >
#include "header_file.h"

#define global_constant value
int global_variable;

void function_with_no_returning_value() {
  
}

int function_with_integer_return_value() {
	int m;
  
	return m;
}

void function_with_parameters(int parameter1, int parameter2, int another_parameter) {
	
}

main(int argc, char **argv) {
  return 0;
}

I/O

         I/O in C++ appears really easy, then ends up being very involved and complicated. But it doesn't get there for a while, so you're not in too much trouble starting out. To get something to print out to the screen, use cout, like this:

cout << "Hello, world!" << endl;

         Yes, this looks funny. Most programming languages use parentheses to encapsulate the list of parameters to a function, yet we have "<<"s instead. cout happens to be a stream, and streams are cool because they can take any number of inputs in any kinds of formats (similar to printf!). But instead of the parentheses, there are those arrows -- this is one of the cool things in C++: operator overloading, a part of object- oriented programming (OOP). OOP is considered an advanced topic by just about everyone, so I won't go into it until the end of this page.

cout << "Hello, world!" << endl << "How are you today?" << endl;

         ..is an example of the variable parameters. (The "endl"s are end-of-lines; they are the equivalent of hitting 'return'. They also flush the stream, which you always want to do if you're using cout for debugging.)

         Input from the console is just as nice as output; instead of cout you now have cin, which is used like this:

cin >> a;

         ..where 'a' is some variable. Again, you see the ">>"s, but notice that they're backwards!! The way that I remember which is which is by where data is coming from and going to; on output the data is going from the variables into cout, and for input the data is coming from cin and going in the variable. cin is also a stream, so you can put as many arguments as you like on it (cin >> a >> b >> c; is perfectly legal).

         'cin' and 'cout' are functions defined in iostream.h, so you have to have a "#include < iostream.h >" before you use them. Note that you could also say "#include < iostream >" without the 'h' and it's a different file. Which should you use? As long as you stick to one throughout your project you're fine, but try to use the non-h version (it's a little bit newer).

         A quick example to show off console I/O:

#include < iostream.h >

main()
{
  int a;                                // declare a to be an integer
  cout << "Hello!  Give me a number between 0 and 5:";
  cin >> a;
  cout << endl;
  cout << "You entered " << a << endl;

  return 0;        // returns an error condition of 0, which is usually no error.
}

         File input works very similarly (it's also a stream), but you have to associate a variable with files. The two things to get file access working are:

  • you have to #include < fstream.h >
  • you have to have a variable of either type ifstream (reading) or ofstream (writing)

             One important difference between C++ and most other languages (at least ones that I've worked with) is how you tell the computer what kind of thing you're going to be reading out of the file, i.e. is it a character file? Is it a number file? Well, it turns out that in C++ you don't really tell it until you get the info from the file. The way that it knows is by looking at what kind of variable you read the file stream into. You can switch variable types in mid-file, which is very useful for databasing with file entries of mixed types.

    int c;
    ifstream infile ("filename.txt");
    infile >> c;
    

             And a quick example to show off file I/O:

    #include < iostream.h >
    #include < fstream.h >
    
    main() {
      ifstream infile ("filename.txt");  // listing file name in declaration automatically
                                         // opens the file.  If you don't do this, you have
                                         // to call the function infile.open("filename.txt")
      if (!infile) {
        cout << "File 'filename.txt' doesn't exist!" << endl;
        return 1;     // returns an error condition of 1.
      }
    
      char c;               // declare c as a character
      cout << "Copying 'filename.txt' to 'filename.bak'...";
    
      ofstream outfile("filename.bak");
    
      infile >> c;
      while (infile) {              // this slightly strange construct checks for 
                                    // the end of the file gracefully.
        outfile << c;
        infile >> c;
      }
    
      infile.close();
      outfile.close();
    
      cout << "done." << endl;
    }
    

    Variables

             Variables are very straightforward in C++. The types that you'll use most frequently (with their sizes) are:

    char (1 byte)
    short (2 bytes)
    int (2-4 bytes depending on compiler)
    long (4 bytes)
    long long (8 bytes)
    float (8 bytes)
    double (10 bytes)
    

             Additionally, you can declare all the integer types as either signed or unsigned (signed is the default). A couple of special notes, however, that you're going to want to know about:

  • When dealing with characters (as in 'a' or '%'), you can only use the char variable, and only unsigned (this isn't specified). Another ramification of that is if you run the following code (or some variation on it, different compilers give yadda yadda yadda):
    char c;
    int i;
    cin >> c;
    i = c;
    cout << i;
    
    Suppose you gave it 4 as an input. It won't give you back 4, because c was declared a character, and 4 was immediately transposed into its ASCII value, which is not 4 (I don't remember what it is). This ASCII value is then copied over into i, and when it sees an integer value on a cout, it doesn't convert the ASCII back into the character, it assumes it's just a number.
  • Also, when dealing with fractional numbers (like 4.41) you can only use float or double; if you say int a = 4.41; 'a' gets the value of 4. This problem crops up especially when you have something that divides integer numbers, say when you want to take the input and divide it by 15. So you have something like:
    float result;
    int input;
    cin >> input;
    result = input/15;
    cout << result;
    
    But the problem is that you give it 12 and it tells you the result is 0. (Or 1, compiler, shcompiler.) What happened is that you have an int variable being divided by an int constant, which will have an int result when the computer's done with it. What you want it to have an int value divided by a float value so that the result is a float. So you have to tell the computer "I want floating point math!", like this:
    result = input/15.0;
    
    Yes, that stupid little ".0" makes that much of a difference. Entire countries have been brought to their knees by ".0"s in C++ programs.

             One of the very handy things about C++ is that you can initialize variables as you declare them (by default all initial values are "undefined" -- that means "random"). If you want it to have a value when you declare it, here's how:

    int c = 0;
    

    Conditional execution

             C++ has three ways to do conditional execution (that I can think of right now). The three ways are 'if', 'switch', and ':?' -- the only ternary operator in C++.

             The 'if' statement is really easy. Suppose you get this number from the user, and you want to know if they entered something greater than 10. The following code will test and act on this:

    cin >> a;
    if (a>10) {
    	cout << "What you entered is greater than 10!  Die!" << endl;
    }
    else {
    	cout << "What you entered is less than or equal to 10!  Die!" << endl;
    }
    

             And so this is very easy. The expression to evaluate has to be enclosed in parentheses, but other than that almost everything else about the if construct is optional. If you have only one statement to execute, you don't need the curly braces. You never have to put an else construct in there at all. The parsing skeleton for the 'if' statement looks like this:

    if () {
    	;
    }
    [ 
    else if () {
    	;
    }
    ]
    [
    else {
    	;
    }
    ]
    

             The next way to do conditional execution is the 'switch' statement. The 'switch' statement is really useful only for a large number of conditional blocks, like choosing what number the user entered on a menu. Since having 10 layers of nested if statements is ugly and hard to debug, the switch is a very useful alternative. Here's the general form of a switch statement:

    switch (< expression >) {
    	case < constant >:
          < statements >
          break;
    	case < constant >:
          < statements >
          break;
    	.
    	.
    	default:
          < statements >
          break;
    }
    

             You have to be very careful with the switch statement, though, because as soon as it finds one of the case statements that match the expression, it will execute until it hits a 'break' statement. The compiler won't catch it if you don't put it in, because there are situations in which you want multiple numbers to run the same code.

             The final conditional construct is C++'s only ternary operator. It works exactly like an if/else statement with only one line on each part. Here's an example:

    c = a < b ? 0 : 1 ;
    

             Which is the same as:

    if ( a < b )
    	c = 0;
    else 
    	c = 1;
    

             ..but as you can see, the code is much smaller, and harder to read. This comes in handy once in a while, but is fairly rare until you get to the guru level and deal with people who love this stuff (like me!). (By the way, this particular segment of code could be optimized with "c = a>=b".)

    Loops

             Looping is a very important part of programming because there are many things that you want to do on consecutive data. There are three ways to loop (that I can think of right now): for, while, and do.

             'for' is the most common loop. It is not like the for loops of other languages, however, because it is really a while in disguise. Here's the general format, and then an example:

    for ( < initial statements > ; < conditional evaluation > ; < incremental statements >) {
    	< statements >
    	.
    	.
    }
    
    // loop to calculate the sum of the numbers 1 through 10:
    int result = 0;
    int i;
    for (i = 1; i<=10; i=i+1)
    	result = result + i;
    

             There are some compactions to that code that I have to go over now, because you'll see them everywhere. First, the "i=i+1" has a nifty shortcut in C++. Since you could have outrageously long variable names, and you just want to increase it by 3, you'd normally have to type it twice. So, there's an operator in C++ that looks like this: +=. Instead of saying big_variable_name = big_variable_name + 3; you can now type big_variable_name += 3. Furthermore, almost every operator in C++ can do this! So, the following are all legal operators: -=, *=, /=, %=, <<=, >>=. There's yet another shortcut for incrementing or decrementing by one: ++ and --. There are called the [pre|post][increment|decrement] operators. Instead of saying i+=1 you can now say i++ or ++i. (The difference between the pre and post is when you evaluate it vs when you do that actual increment -- cout << ++t won't say the same thing as cout << t++, but t will have the same value afterwards.)

             After compacting, the above code becomes this:

    int result = 0;
    for (int i = 1; i<=10; i++)
    	result += i;
    

             Nifty, eh? It was the chair, eh... [Editor's note: I don't even remember what that was a reference to.]

    Branches

             Branching doesn't really happen in C++, if you're used to things like BASIC's GOTO statement. What C++ has is functions, and that's about it. (There is inded a C++ goto, but I advise ignoring it because it's bad style and hard to debug. If, however, you're diehard for the goto statement, you have to say goto < label >, and the labels are declared on their own line followed by a colon.) So instead, here's how to do functions in C++.

             A function is usually coded before main(), because if you put it anywhere else you have to let the compiler know where it is, and since that's not nice I'm not getting into it right now. The general form of a function is:

    < return type > function_name([< parameters >]) {
    	< statements >
    	.
    	.
    	return < return type variable > ;
    }
    

             If you don't want a return type (i.e. a procedure, not a function) the return type is "void", and when you want to leave the function you execute "return;" without any parameter. The skeleton I gave above for general C++ programs is a pretty good display of how to use these, but here's an example anyways:

    // returns the factorial of n.  This is a recursive function:
    int factorial(int n) {
    	if (n<=1)
    		return 1;
    	else
    		return n*factorial(n-1);
    }
    

             And when you're down in main() or wherever and you want to call it, all you have to say is

    int result;
    result = factorial(6);
    

    chrisv@aquamentus.com
    January 19, 2002