Skip to the content of the web site.

How to start a project

The wrong approach to starting a project is to try authoring the entire project before the first time you compile. This will lead to dozens if not hundreds of confusing and misleading errors, and it will be very frustrating trying to track them down.

Instead, you should complete the project in steps:

  1. Write down the include directives.
  2. Write the function declarations.
  3. Write a skeleton for each function definition.
    • After this step, it should compile.
  4. Make a some test code in main().
    • After this step, it should compile.
  5. Only after this works, do you start implementing the function being tested.
    • Only after this step, it should work correctly.

Each of these steps is described in detail below, followed by a small section for looking ahead.

1. Include directives

The first section of each project are the include directives. For your first projects, the only library you will need to include is the input-output stream library:

#include <iostream>

Later, you may require additional libraries, for example,

#include <cassert>
#include <cmath>

You can also include files in your current directory, but this will not be introduced until much later in the course.

2. Function declarations

Next, you will write down all function declarations. This includes the return type, the function name, and the parameters with their types:

// Function declarations
int main();
unsigned int factorial( unsigned int n );

You should have a declaration for each function you will author.

3. Skeletal function definitions

Next, you will define each of the functions you intend to author. Instead of starting immediately, write a skeletal function definition:

  • If the function returns an integer data type, use return 0;.
  • If the function returns a floating-point data type, use return 0.0;.
  • If the function returns a Boolean data type, use return false;.
  • If the function returns nothing (void), just have an empty function body.

By a skeleton, given a function declaration, we are creating a function definition that compiles, but does not actually do anything useful. It is into the body of this skeletal function definition that you will add code that actually solves the problem.

For example,

// Function definitions

// The main program
int main() {
	return 0;
}

// The factorial function
unsigned int factorial( unsigned int n ) {
	return 0;
}

You can view this program up to this point at http://cpp.sh/3jjzp.

Now, try compiling your program. Of course, it does nothing but you should take this step to make sure that you do not have a syntax error. Don't continue from this point until it compiles, because having syntax errors in your include directives, your function declarations or your skeletal function definitions will make finding problems with your code more difficult later. Also, now is a good time to start adding comments.

4. Write a simple test

Next, write a main function that tests your function.

// Function definitions

// The main program
int main() {
	std::cout << " 0! = " << factorial(  0 ) << " (should equal 1)" << std::endl;
	std::cout << " 1! = " << factorial(  1 ) << " (should equal 1)" << std::endl;
	std::cout << "10! = " << factorial( 10 ) << " (should equal 3628800)"
                                                                        << std::endl;
	return 0;
}

// The factorial function
unsigned int factorial( unsigned int n ) {
	return 0;
}

Now, if you compile this code, it should execute but you will see invalid output:

 0! = 0 (should equal 1)
 1! = 0 (should equal 1)
10! = 0 (should equal 3628800)

Of course this is wrong, but at least the test works, and now you can focus 100% of your energy on authoring the factorial function (or whichever project you are working on).

5. Start implementing the functions

You can now test your function, and if there is a problem, because everything else works, any errors will be as a result of your changes to the function you are working on right now.

// The factorial function
//  - return 0 if n! results in an overflow
unsigned int factorial( unsigned int n ) {
	if ( n <= 1 ) {
		return 1;
	} else if ( n == 2 ) {
		return 2;
	} else if ( n == 3 ) {
		return 6;
	} else if ( n == 4 ) {
		return 24;
	} else if ( n == 5 ) {
		return 120;
	} else if ( n == 6 ) {
		return 720;
	} else if ( n == 7 ) {
		return 5040;
	} else if ( n == 8 ) {
		return 40320;
	} else if ( n == 9 ) {
		return 362880;
	} else if ( n == 10 ) {
		return 3628800;
	} else if ( n == 11 ) {
		return 39916800;
	} else if ( n == 12 ) {
		return 479001600;
	} else {
		// n! is too big for 'unsigned int' if n >= 13
		return 0;
	}
}

Note: Do not write a function like this. This is as an example only and only meant to be somewhat funny.

Looking ahead

Later, when we have classes, you will require a sections for each of class declarations and class definitions, which will appear between the include directives and the function declarations, as well as a section for member function definitions, which will appear after the function declarations but before the function definitions; however, we will see all this at a later date.