Saturday, February 13, 2010

c++ programming notes!

lesson 1.

1.0 compiling your first program

Before we can write our first program (which we will do very soon), we need to know two things about development environments.

First, although our programs will be written inside .cpp files, the .cpp files themselves will be added to a project. Some IDEs call projects “workspaces”, or “solutions”. The project stores the names of all the code files we want to compile, and also saves various IDE settings. Every time we reopen the project, it will restore the state of the IDE to where we left off. When we choose to compile our program, the project tells the compiler and linker which files to compile and link. It is worth noting that project files for one IDE will not work in another IDE.

Second, there are different kinds of projects. When you create a new project, you will have to pick a project type. All of the projects that we will create in this tutorial will be console projects. A console project means that we are going to create programs that can be run from the dos or linux command-line. By default, console applications have no graphical user interface (GUI) and are compiled into stand-alone executable files. This is perfect for learning C++, because it keeps the complexity to a minimum.

Traditionally, the first program programmers write in a new language is the infamous hello world program, and we aren’t going to deprive you of that experience! You’ll thank us later. Maybe.

A quick note about examples containing code

Starting with this lesson, you will see many examples of C++ code presented. Most of these examples will look something like this:

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

If you select the code from these examples with your mouse and then copy/past it into your compiler, you will also get the line numbers, which you will have to strip out manually. Instead, click the “copy to clipboard” link at the top of the example. This will copy the code to your clipboard without the line numbers, which you can then paste into your compiler without any editing required.

Visual Studio 2005 Express

To create a new project in Visual Studio 2005 Express, go to the File menu, and select New -> Project. A dialog box will pop up that looks like this:

VC2005 Project Dialog

Select the Win32 project type, and Win32 Console Application will automatically be selected for you. In the Name field, you will enter the name of your program. Type in HelloWorld. In the Location field, pick a directory that you would like your project to be placed into. We recommend you place them in a subdirectory off of your C drive, such as C:\VC2005Projects. Click OK, and then Finish.

On the left side, in the Solution Explorer, Visual Studio has created a number of files for you, including stdafx.h, HelloWorld.cpp, and stdafx.cpp.

Initial Visual C++ program

In the text editor, you will see that VC2005 has already created some code for you. Select and delete the _tmain function, and then type/copy the following into your compiler:

1.#include "stdafx.h"
2.#include
3.
4.int main()
5.{
6. std::cout << "Hello world!" <<>
7. return 0;
8.}

What you end up with should look like this:

Visual C++ hello world program

To compile your program, either press F7 or go to the Build menu and choose “Build Solution”. If all goes well, you should see the following appear in the Output window:

Successful build

This means your compile was successful!

To run your compiled program, press ctrl-F5, or go the Debug menu and choose “Start Without Debugging”. You will see the following:

Program run

That is the result of your program!

Important note to Visual Studio users: Visual studio programs should ALWAYS begin with the following line:

#include "stdafx.h"

Otherwise you will receive a compiler warning, such as c:\test\test.cpp(21) : fatal error C1010: unexpected end of file while looking for precompiled header directive

Alternately, you can turn off precompiled headers. However, using precompiled headers will make your program compile much faster, so we recommend leaving them on unless you are developing a cross-platform program.

The example programs we show you throughout the tutorial will not include this line, because it is specific to your compiler.

Code::Blocks

To create a new project in Code::Blocks, go to the File menu, and select New Project. A dialog box will pop up that looks like this:

Code::Blocks Project Dialog

Select Console Application and press the Create button.

You will be asked to save your project. You can save it wherever you wish, though we recommend you save it in a subdirectory off of the C drive, such as C:\CBProjects. Name the project HelloWorld.

Code::Blocks Save Project Dialog

You will see “Console Application” under the default workspace:

Code::Blocks Project Closed

Open the tree under “Console Application”, open “Sources”, and double click on “main.cpp”. You will see that the hello world program has already been written for you!

To build your project, press ctrl-F9, or go to the Build menu and choose “Build”. If all goes well, you should see the following appear in the Build log window:

Successful build

This means your compile was successful!

To run your compiled program, press ctrl-F10, or go the Build menu and choose “Run”. You will see something similar to the following:

Program run

That is the result of your program!

Using a command-line based compiler

Paste the following into a text file named HelloWorld.cpp:

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

From the command line, type:

g++ -o HelloWorld HelloWorld.cpp

This will compile and link HelloWorld.cpp. To run it, type:

HelloWorld (or possibly .\HelloWorld), and you will see the output of your program.

Other IDEs

You will have to figure out how to do the following on your own:
1) Create a console project
2) Add a .cpp file to the project (if necessary)
3) Paste the following code into the file:

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

4) Compile the project
5) Run the project

If compiling fails

If compiling the above program fails, check to ensure that you’ve typed or pasted the code in correctly. The compiler’s error message may give you a clue as to where or what the problem is.

If you are using a much older C++ compiler, the compiler may give an error about not understanding how to include iostream. If this is the case, try the following program instead:

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

In this case, you should upgrade your compiler to something more compliant with recent standards.

If your program runs but the window closes immediately

This is an issue with some compilers, such as Bloodshed’s Dev-C++. We present a solution to this problem in lesson 0.7 — a few common cpp problems.

Conclusion

Congratulations, you made it through the hardest part of this tutorial (installing the IDE and compiling your first program)! You are now ready to learn C++!

lesson 2

2. 0 common c++ problems:

In this section, we’ll address some of the common issues that new programmers seem to run across with fairly high probability. This is not meant to be a comprehensive list of compilation or execution problems, but rather a pragmatic list of solutions to very basic issues. If you have any suggestions for other issues that might be added to this list, post them in the comments section below.

Problem 1: When executing a program from the IDE, the console window blinks and then closes immediately.

Answer 1: Some compilers (eg. Bloodshed’s Dev C++) don’t automatically pause the console screen after the program has finished executing. If this is the case with your compiler, the following two steps will fix your problem:

First, add the following line near the top of your program:

Second, add the following code at the end of the main() function (right before the return statement):

1.cin.clear();
2.cin.ignore(255, '\n');
3.cin.get();

This will cause your program to wait for you to press a key before continuing, which will give you time to examine your program’s output before your compiler closes the console window.

Other solutions, such as the commonly suggested system(”pause”) solution may only work on certain operating systems.

Problem 2: When compiling with Microsoft Visual C++, you get the following error: “c:\vcprojects\test.cpp(263) :fatal error C1010: unexpected end of file while looking for precompiled header directive”

Answer 2: This error occurs when the Microsoft Visual C++ compiler is set to use precompiled headers but one of your C++ code files does not include the stdafx header as the first line. To fix this problem, simply locate the file producing the error (in the above error, test.cpp is the culprit), and add the following line at the very top of the file:

1.#include "stdafx.h"

Alternatively, you can turn off precompiled headers.

Problem 3: When trying to use cin or cout, the compiler says cin or cout is an “undeclared identifier”

Answer 3: First, make sure you have included the following line near the top of your file:

In any function where you use use cin or cout, include the following line:

1.using namespace std;

Problem 4: When trying to use endl to end a printed line, the compiler says end1 is an “undeclared identifier”

Make sure you do not mistake the letter l (lower case L) in endl for the number 1. endl is all letters. I recommend using a font that makes it clear the differences between the letter lower case L, upper case i, and the number 1. Also the letter capital o and the number zero can easily be confused in many fonts. There is a huge list of programming fonts here.

Problem 4: My program compiles but it isn’t working correctly. What do I do?

Answer 4: Debug it! You can find information on how to debug programs in appendix A, specifically sections A.4 and A.5. You will probably find the debugging sections more comprehensible after reading a few more chapters, but I wanted to make you aware of their existence now for future reference.

lesson 3

Structure of a program

A computer program is a sequence of instructions that tell the computer what to do.

Statements and expressions

The most common type of instruction in a program is the statement. A statement in C++ is the smallest independent unit in the language. In human language, it is analogous to a sentence. We write sentences in order to convey an idea. In C++, we write statements in order to convey to the compiler that we want to perform a task. Statements in C++ are terminated by a semicolon.

There are many different kinds of statements in C++. The following are some of the most common types of simple statements:


.int x;
2.x = 5;
3.cout <<>

int x is a declaration statement. It tells the compiler that x is a variable. All variables in a program must be declared before they are used. We will talk more about variables shortly.
x = 5 is an assignment statement. It assigns a value (5) to a variable (x).
cout <<> is an output statement. It outputs the value of x (which we set to 5 in the previous statement) to the screen.

The compiler is also capable of resolving expressions. An expression is an mathematical entity that evaluates to a value. For example, in math, the expression 2+3 evaluates to the value 5. Expressions can involve values (such as 2), variables (such as x), operators (such as +) and functions (which return an output value based on some input value). They can be singular (such as 2, or x), or compound (such as 2+3, 2+x, x+y, or (2+x)*(y-3)).

For example, the statement x = 2 + 3; is a valid assignment statement. The expression 2+3 evaluates to the value of 5. This value of 5 is then assigned to x.

Functions

In C++, statements are typically grouped into units called functions. A function is a collection of statements that executes sequentially. Every C++ program must contain a special function called main(). When the C++ program is run, execution starts with the first statement inside of main(). Functions are typically written to do a very specific job. For example, a function named Max() might contain statements that figures out which of two numbers is larger. A function named CalculateGrade() might calculate a student’s grade. We will talk more about functions later.

Libraries

Libraries are groups of functions that have been “packaged up” for reuse in many different programs. The core C++ language is actually very small and minimalistic — however, C++ comes with a bunch of libraries, known as the C++ standard libraries, that provide programmers with lots of extra functionality. For example, the iostream library contains functions for doing input and output. During the link stage of the compilation process, the libraries from the C++ standard library are the runtime support libraries that are linked into the program (this will be discussed further in lesson 1.4).

Taking a look at a sample program

Now that you have a brief understanding of what statements, functions, and libraries are, let’s look at a simple hello world program.

Consider our hello world program:

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

Line 1 is a special type of statement called a preprocessor directive. Preprocessor directives tell the compiler to perform a special task. In this case, we are telling the compiler that we would like to use the iostream library. The iostream library contains code that tells the compiler what cout and endl do. In other words, we need to include the iostream library in order to write to the screen.

Line 3 declares the main() function, which as you learned above, is mandatory. Every program must have a main() function.

Lines 4 and 8 tell the compiler which lines are part of the main function. Everything between the opening curly brace on line 4 and the closing curly brace on line 8 is considered part of the main() function.

Line 5 is our first statement (you can tell it’s a statement because it ends with a semicolon). As you learned in the explanation for line 1, cout and endl live inside the iostream library. However, within iostream, they live inside a special compartment named std (short for standard). This using statement tells the compiler to look inside a compartment named std if it can’t find cout or endl defined anywhere else. In other words, this statement is also necessary so the compiler can find cout and endl, which we use on line 6.

Line 6 is our output statement. Cout is a special object that represents the console/screen. The <<>

Line 7 is a new type of statement, called a return statement. When an executable program finishes running, it sends a value to the operating system that indicates whether it was run successfully or not. The return value of main() is used for this purpose. This particular return statement returns the value of 0 to the operating system, which means “everything went okay!”. Non-zero numbers are typically used to indicate that something went wrong, and the program had to abort. We will discuss return statements in more detail when we discuss functions.

Conclusion

All of the programs we write will follow this template, or a variation on it. We will discuss each of the lines above in more detail in the upcoming sections.

Quiz

The following quiz is meant to reinforce your understanding of the material presented above.

1) What is the difference between a statement and an expression?
2) What is the difference between a function and a library?
3) What symbol do statements in C++ end with?

Quiz Answers

To see these answers, select the area below with your mouse.

1) Solution

A statement is a “complete sentence” that tells the compiler to perform a particular task. An expression is a mathematical entity that evaluates to a value. Expressions are often used inside of statements.

2) Solution

A function is a collection of statements that executes sequentially, typically designed to perform a specific job. A library is a collection of functions that is meant to be reused by many programs.

3 Solution

The semicolon (;)

lesson 4

4.0 comments

Types of comments

A comment is a line (or multiple lines) of text that are inserted into the source code to explain what the code is doing. In C++ there are two kinds of comments.

The // symbol begins a C++ single-line comment, which tells the compiler to ignore everything to the end of the line. For example:


1.cout << "Hello world!" <<>// Everything from here to the right is ignored.

Typically, the single line comment is used to make a quick comment about a single line of code.

1.cout << "Hello world!" <<>// cout and endl live in the iostream library
2.cout << "It is very nice to meet you!" <<>// these comments make the code hard to read
3.cout << "Yeah!" <<>// especially when lines are different lengths

Having comments to the right of a line can make the both the code and the comment hard to read, particularly if the line is long. Consequently, the // comment is often placed above the line it is commenting.


1.// cout and endl live in the iostream library
2.cout << "Hello world!" <<>
3.
4.// this is much easier to read
5.cout << "It is very nice to meet you!" <<>
6.
7.// don't you think so?
8.cout << "Yeah!" <<>

The /* and */ pair of symbols denotes a C-style multi-line comment. Everything in between the symbols is ignored.


1./* This is a multi-line comment.
2. This line will be ignored.
3. So will this one. */

Since everything between the symbols is ignored, you will sometimes see programmers “beautify” their multiline comments:


1./* This is a multi-line comment.
2. * the matching asterisks to the left
3. * can make this easier to read
4. */

Multi-line style comments do not nest. Consequently, the following will have unexpected results:


1./* This is a multiline /* comment */ this is not inside the comment */
2.// ^ comment ends here

Rule: Never nest comments inside of other comments.

Proper use of comments

Typically, comments should be used for three things. At the library, program, or function level, comments should be used to describe what the library, program, or function, does. For example:


1.// This program calculate the student's final grade based on his test and homework scores.

1.// This function uses newton's method to approximate the root of a given equation.

1.// The following lines generate a random item based on rarity, level, and a weight factor.

All of these comments give the reader a good idea of what the program is trying to accomplish without having to look at the actual code. The user (possibly someone else, or you if you’re trying to reuse code you’ve already written in the future) can tell at a glance whether the code is relevant to what he or she is trying to accomplish. This is particularly important when working as part of a team, where not everybody will be familiar with all of the code.

Second, within the library, program, or function described above, comments should be used to describe how the code is going to accomplish it’s goal.

1./* To calculate the final grade, we sum all the weighted midterm and homework scores
2. and then divide by the number of scores to assign a percentage. This percentage is
3. used to calculate a letter grade. */

1.// To generate a random item, we're going to do the following:
2.// 1) Put all of the items of the desired rarity on a list
3.// 2) Calculate a probability for each item based on level and weight factor
4.// 3) Choose a random number
5.// 4) Figure out which item that random number corresponds to
6.// 5) Return the appropriate item

These comments give the user an idea of how the code is going to accomplish it’s goal without going into too much detail.

At the statement level, comments should be used to describe why the code is doing something. A bad statement comment explains what the code is doing. If you ever write code that is so complex that needs a comment to explain what a statement is doing, you probably need to rewrite your code, not comment it.

Here are some examples of bad line comments and good statement comments.

Bad comment:


1.// Set sight range to 0
2.sight = 0;

(yes, we already can see that sight is being set to 0 by looking at the statement)

Good comment:


1.// The player just drank a potion of blindness and can not see anything
2.sight = 0;

(now we know WHY the player’s sight is being set to 0)

Bad comment:


1.// Calculate the cost of the items
2.cost = items / 2 * storePrice;

(yes, we can see that this is a cost calculation, but why is items divided by 2?)

Good comment:


1.// We need to divide items by 2 here because they are bought in pairs
2.cost = items / 2 * storePrice;

(now we know!)

Programmers often have to make a tough decision between solving a problem one way, or solving it another way. Comments are a great way to remind yourself (or tell somebody else) the reason you made a one decision instead of another.

Good comments:


1.// We decided to use a linked list instead of an array because
2.// arrays do insertion too slowly.

1.// We're going to use newton's method to find the root of a number because
2.// there is no deterministic way to solve these equations.

Finally, comment should be written in a way that makes sense to someone who has no idea what the code does. It is often the case that a programmer will say “It’s obvious what this does! There’s no way I’ll forget about this”. Guess what? It’s not obvious, and you will be amazed how quickly you forget. :) You (or someone else) will thank you later for writing down the what, how, and why of your code in human language. Reading individual lines of code is easy. Understanding what goal they are meant to accomplish is not.

To summarize:

  • At the library, program, or function level, describe what
  • Inside the library, program, or function, describe how
  • At the statement level, describe why.

Commenting out code

Commenting out sections of code (temporarily) can be useful in several cases:

1) You’re working on a new piece of code that won’t compile yet, and you need to run the program. The compiler won’t let you run if there are compiler errors. Commenting out the in-progress code will allow the program to compile so you can run it.

2) You want to change the way your program executes by commenting out individual lines of code. For example, you think a particular function call is crashing your program. Commenting out the function call and running your program may indicate whether that function was the culprit.

In our upcoming examples, we will remind Visual Studio Express users that they need to start their programs with #include "stdafx.h". However, we will typically comment out this line of code, because it will cause compile errors on other compilers. Visual Studio Express users must uncomment the line before they compile.

lesson 5

5.0 Variables

A statement such as x = 5 seems obvious enough. As you would guess, we are assigning the value of 5 to x. But what exactly is x? x is a variable.

A variable in C++ is a name for a piece of memory that can be used to store information. You can think of a variable as a mailbox, or a cubbyhole, where we can put and retrieve information. All computers have memory, called RAM (random access memory), that is available for programs to use. When a variable is declared, a piece of that memory is set aside for that variable.

In this section, we are only going to consider integer variables. An integer is a whole number, such as 1, 2, 3, -1, -12, or 16. An integer variable is a variable that can only hold an integer value.

In order to declare a variable, we generally use a declaration statement. Here’s an example of declaring variable x as an integer variable (one that can hold integer values):

1.int x;

When this statement is executed by the CPU, a piece of memory from RAM will be set aside. For the sake of example, let’s say that the variable x is assigned memory location 140. Whenever the program sees the value x in an expression or statement, it knows that it should look in memory location 140.

One of the most common operations done with variables is assignment. To do this, we use the assignment operator, more commonly known as equals, more commonly known as the = symbol. When the CPU executes a statement such as x = 5;, it translates this to “put the value of 5 in memory location 140″.

Later in our program, we could print that value to the screen using cout:


.cout <<>// prints the value of x (memory location 140) to the console

In C++, variables are also known as l-values (pronounced ell-values). An l-value is a value that has an address (in memory). Since all variables have addresses, all variables are l-values. They were originally named l-values because they are the only values that can be on the left side of an assignment statement. When we do an assignment, the left hand side of the assignment operator must be an l-value. Consequently, a statement like 5 = 6; will cause a compile error, because 5 is not an l-value. The value of 5 has no memory, and thus nothing can be assigned to it. 5 means 5, and it’s value can not be reassigned. When an l-value has a value assigned to it, the current value is overwritten.

The opposite of l-values are r-values. An r-value refers to any value that can be assigned to an l-value. r-values are always evaluated to produce a single value. Examples of r-values are single numbers (such as 5, which evaluates to 5), variables (such as x, which evaluates to whatever number was last assigned to it), or expressions (such as 2+x, which evaluates to the last value of x plus 2).

Here is an example of some assignment statements, showing how the r-values evaluate:

1.int y; // declare y as an integer variable
2.y = 4; // 4 evaluates to 4, which is then assigned to y
3.y = 2 + 5; // 2 + 5 evaluates to 7, which is then assigned to y
4.
5.int x; // declare x as an integer variable
6.x = y; // y evaluates to 7, which is then assigned to x.
7.x = x; // x evaluates to 7, which is then assigned to x (useless!)
8.x = x + 1; // x + 1 evaluates to 8, which is then assigned to x.

There are two important things to note. First, there is no guarantee that your variables will be assigned the same memory address each time your program is run. The first time you run your program, x may be assigned to memory location 140. The second time, it may be assigned to memory location 168. Second, when a variable is assigned to a memory location, the value in that memory location is undefined (in other words, whatever value was there last is still there).

This can lead to interesting (and by interesting, we mean dangerous) results. Consider the following short program:


01.// #include "stdafx.h" // Uncomment if Visual Studio user
02.#include
03.
04.int main()
05.{
06. using namespace std; // gives us access to cout and endl
07. int x; // declare an integer variable named x
08.
09. // print the value of x to the screen (dangerous, because x is uninitialized)
10. cout <<>
11.}

In this case, the computer will assign some unused memory to x. It will then send the value residing in that memory location to cout, which will print the value. But what value will it print? The answer is “who knows!”. You can try running this program in your compiler and see what value it prints. To give you an example, when we ran this program with an older version of the Visual Studio compiler, cout printed the value -858993460. Some newer compilers, such as Visual Studio 2005 Express will pop up a debug error message if you run this program from within the IDE.

A variable that has not been assigned a value is called an uninitialized variable. Uninitialized variables are very dangerous because they cause intermittent problems (due to having different values each time you run the program). This can make them very hard to debug. Most modern compilers will print warnings at compile-time if they can detect a variable that is used without being initialized. For example, compiling the above program on Visual Studio 2005 express produced the following warning:

c:\vc2005projects\test\test\test.cpp(11) : warning C4700: uninitialized local variable 'x' used

A good rule is to always assign values to variables when they are declared. C++ makes this easy by letting you assign values on the same line as the declaration of the variable:


1.int x = 0; // declare integer variable x and assign the value of 0 to it.

This ensures that your variable will always have a consistent value, making it easier to debug if something goes wrong somewhere else.

One common trick that experienced programmers use is to assign the variable an initial value that is outside the range of meaningful values for that variable. For example, if we had a variable to store the number of cats the old lady down the street has, we might do the following:


1.int cats = -1;

Having -1 cats makes no sense. So if later, we did this:


1.cout <<>" cats" <<>

and it printed “-1 cats”, we know that the variable was never assigned a real value correctly.

Rule: Always assign values to your variables when you declare them.

We will discuss variables in more detail in an upcoming section.

cin

cin is the opposite of cout: whereas cout prints data to the console, cin reads data from the console. Now that you have a basic understanding of variables, we can use cin to get input from the user and store it in a variable.


01.//#include "stdafx.h" // Uncomment this line if using Visual Studio
02.#include
03.
04.int main()
05.{
06. using namespace std;
07. cout << "Enter a number: "; // ask user for a number
08. int x;
09. cin >> x; // read number from console and store it in x
10. cout << "You entered " <<>
11. return 0;
12.}

Try compiling this program and running it for yourself. When you run the program, it will print “Enter a number: ” and then wait for you to enter one. Once you enter a number (and press enter), it will print “You entered ” followed by the number you just entered.

This is an easy way to get input from the user, and we will use it in many of our examples going forward.

Quiz
What values does this program print?


01.int x = 5;
02.x = x - 2;
03.cout <<>// #1
04.
05.int y = x;
06.cout <<>// #2
07.
08.// x + y is an r-value in this context, so evaluate their values
09.cout <<>// #3
10.
11.cout <<>// #4
12.
13.int z;
14.cout <<>// #5

Quiz Answers

1) Solution

The program outputs 3. x – 2 evaluates to 3, which was assigned to x.

2) Solution

The program outputs 3. y was assigned the value of x, which evaluated to 3.

3) Solution

The program outputs 6. x + y evaluates to 6. There was no assignment here.

4) Solution

The program outputs 3. The value of x is still 3 because it was never reassigned.

5) Hide Solution

The output is indeterminate . z is an uninitialized variable.


lesson 6
6.0 A first look at functions

A function is a sequence of statements designed to do a particular job. You already know that every program must have a function named main(). However, most programs have many functions, and they all work analogously to main.

Often, your program needs to interrupt what it is doing to temporarily do something else. You do this in real life all the time. For example, you might be reading a book when you remember you need to make a phone call. You put a bookmark in your book, make the phone call, and when you are done with the phone call, you return to your book where you left off.

C++ programs work the same way. A program will be executing statements sequentially inside one function when it encounters a function call. A function call is an expression that tells the CPU to interrupt the current function and execute another function. The CPU “puts a bookmark” at the current point of execution, and then calls (executes) the function named in the function call. When the called function terminates, the CPU goes back to the point it bookmarked, and resumes execution.

Here is a sample program that shows how new functions are declared and called:

01.//#include // Visual Studio users need to uncomment this line
02.#include
03.
04.// Declaration of function DoPrint()
05.void DoPrint()
06.{
07. using namespace std; // we need this in each function that uses cout and endl
08. cout << "In DoPrint()" <<>
09.}
10.
11.// Declaration of main()
12.int main()
13.{
14. using namespace std; // we need this in each function that uses cout and endl
15. cout << "Starting main()" <<>
16. DoPrint(); // This is a function call to DoPrint()
17. cout << "Ending main()" <<>
18. return 0;
19.}

This program produces the following output:

Starting main()
In DoPrint()
Ending main()

This program begins execution at the top of main(), and the first line to be executed prints Starting main(). The second line in main is a function call to DoPrint. At this point, execution of statements in main() is suspended, and the CPU jumps to DoPrint(). The first (and only) line in DoPrint prints In DoPrint(). When DoPrint() terminates, the caller (main()) resumes execution where it left off. Consequently, the next statment executed in main prints Ending main().

Functions can be called multiple times:

01.//#include // Visual Studio users need to uncomment this line
02.#include
03.
04.// Declaration of function DoPrint()
05.void DoPrint()
06.{
07. using namespace std;
08. cout << "In DoPrint()" <<>
09.}
10.
11.// Declaration of main()
12.int main()
13.{
14. using namespace std;
15. cout << "Starting main()" <<>
16. DoPrint(); // This is a function call to DoPrint()
17. DoPrint(); // This is a function call to DoPrint()
18. DoPrint(); // This is a function call to DoPrint()
19. cout << "Ending main()" <<>
20. return 0;
21.}

This program produces the following output:

Starting main()
In DoPrint()
In DoPrint()
In DoPrint()
Ending main()

In this case, main() is interrupted 3 times, once for each call to DoPrint().

Main isn’t the only function that can call other functions. In the following example, DoPrint() calls a second function, DoPrint2().

01.//#include // Visual Studio users need to uncomment this line
02.#include
03.
04.void DoPrint2()
05.{
06. using namespace std;
07. cout << "In DoPrint2()" <<>
08.}
09.
10.// Declaration of function DoPrint()
11.void DoPrint()
12.{
13. using namespace std;
14. cout << "Starting DoPrint()" <<>
15. DoPrint2(); // This is a function call to DoPrint2()
16. DoPrint2(); // This is a function call to DoPrint2()
17. cout << "Ending DoPrint()" <<>
18.}
19.
20.// Declaration of main()
21.int main()
22.{
23. using namespace std;
24. cout << "Starting main()" <<>
25. DoPrint(); // This is a function call to DoPrint()
26. cout << "Ending main()" <<>
27. return 0;
28.}

This program produces the following output:

Starting main()
Starting DoPrint()
In DoPrint2()
In DoPrint2()
Ending DoPrint()
Ending main()

Return values

If you remember, when main finishes executing, it returns a value back to the operating system (the caller) by using a return statement. Functions you write can return a single value to their caller as well. We do this by changing the return type of the function in the function’s declaration. A return type of void means the function does not return a value. A return type of int means the function returns an integer value to the caller.

01.// void means the function does not return a value to the caller
02.void ReturnNothing()
03.{
04. // This function does not return a value
05.}
06.
07.// int means the function returns an integer value to the caller
08.int Return5()
09.{
10. return 5;
11.}

Let’s use these functions in a program:

1.cout <<>// prints 5
2.cout <<>// prints 7
3.cout <<>// This will not compile

In the first statement, Return5() is executed. The function returns the value of 5 back to the caller, which passes that value to cout.

In the second statement, Return5() is executed and returns the value of 5 back to the caller. The expression 5 + 2 is then evaluated to 7. The value of 7 is passed to cout.

In the third statement, ReturnNothing() returns void. It is not valid to pass void to cout, and the compiler will give you an error when you try to compile this line.

One commonly asked question is, “Can my function return multiple values using a return statement?”. The answer is no. Functions can only return a single value using a return statement. However, there are ways to work around the issue, which we will discuss when we get into the in-depth section on functions.

Returning to main

You now have the conceptual tools to understand how the main() function actually works. When the program is executed, the operating system makes a function call to main(). Execution then jumps to the top of main. The statements in main are executed sequentially. Finally, main returns a integer value (usually 0) back to the operating system. This is why main is declared as int main().

Some compilers will let you get away with declaring main as void main(). Technically this is illegal. When these compilers see void main(), they interpret it as:

1.int main()
2.{
3. // your code here
4. return 0;
5.}

You should always declare main as returning an int and your main function should return 0 (or another integer if there was an error).

Parameters

In the return values subsection, you learned that a function can return a value back to the caller. Parameters are used to allow the caller to pass information to a function! This allows functions to be written to perform generic tasks without having to worry about the specific values used, and leaves the exact values of the variables up to the caller.

This is a case that is best learned by example. Here is an example of a very simple function that adds two numbers together and returns the result to the caller.

01.//#include // Visual Studio users need to uncomment this line
02.#include
03.
04.// add takes two integers as parameters, and returns the result of their sum
05.// add does not care what the exact values of x and y are
06.int add(int x, int y)
07.{
08. return x + y;
09.}
10.
11.int main()
12.{
13. using namespace std;
14. // It is the caller of add() that decides the exact values of x and y
15. cout <<>// x=4 and y=5 are the parameters
16. return 0;
17.}

When function add() is called, x is assigned the value 4, and y is assigned the value 5. The function evaluates x + y, which is the value 9, and then returns this value to the caller. This value of 9 is then sent to cout to be printed on the screen.

Output:

9

Let’s take a look at a couple of other calls to functions():

01.//#include // Visual Studio users need to uncomment this line
02.#include
03.
04.int add(int x, int y)
05.{
06. return x + y;
07.}
08.
09.int multiply(int z, int w)
10.{
11. return z * w;
12.}
13.
14.int main()
15.{
16. using namespace std;
17. cout <<>// evalutes 4 + 5
18. cout <<>// evalues 3 + 6
19. cout <<>// evalues 1 + 8
20.
21. int a = 3;
22. int b = 5;
23. cout <<>// evaluates 3 + 5
24.
25. cout <<>// evalues 1 + (2 * 3)
26. cout <<>// evalues 1 + (2 + 3)
27. return 0;
28.}

This program produces the output:

9
9
9
8
7
6

The first three statements are straightforward.

The fourth is relatively easy as well:

1.int a = 3;
2.int b = 5;
3.cout <<>// evaluates 3 + 5

In this case, add() is called where x = a and y = b. Since a = 3 and b = 5, add(a, b) = add(3, 5), which resolves to 8.

Let’s take a look at the first tricky statement in the bunch:

1.cout <<>// evalues 1 + (2 * 3)

When the CPU tries to call function add(), it assigns x = 1, and y = multiply(2, 3). y is not an integer, it is a function call that needs to be resolved. So before the CPU calls add(), it calls multiply() where z = 2 and w = 3. multiply(2, 3) produces the value of 6, which is assigned to add()’s parameter y. Since x = 1 and y = 6, add(1, 6) is called, which evaluates to 7. The value of 7 is passed to cout.

Or, less verbosely (where the => symbol is used to represent evaluation):
add(1, multiply(2, 3)) => add(1, 6) => 7

The following statement looks tricky because one of the parameters given to add() is another call to add().

1.cout <<>// evalues 1 + (2 + 3)

But this case works exactly the same as the above case where one of the parameters is a call to multiply().

Before the CPU can evaluate the outer call to add(), it must evaluate the inner call to add(2, 3). add(2, 3) evaluates to 5. Now it can evaluate add(1, 5), which evaluates to the value 6. cout is passed the value 6.

Less verbosely:
add(1, add(2, 3)) => add(1, 5) => 6

Effectively using functions

One of the biggest challenges new programmers encounter (besides learning the language) is learning when and how to use functions effectively. Functions offer a great way to break your program up into manageable and reusable parts, which can then be easily connected together to perform a larger and more complex task. By breaking your program into smaller parts, the overall complexity of the program is reduced, which makes the program both easier to write and to modify.

Typically, when learning C++, you will write a lot of programs that involve 3 subtasks:

  1. Reading inputs from the user
  2. Calculating a value from the inputs
  3. Printing the calculated value

For simple programs, reading inputs from the user can generally be done in main(). However, step #2 is a great candidate for a function. This function should take the user inputs as a parameter, and return the calculated value. The calculated value can then be printed (either directly in main(), or by another function if the calculated value is complex or has special printing requirements).

A good rule of thumb is that each function should perform one (and only one) task. New programmers often write functions that combine steps 2 and 3 together. However, because calculating a value and printing it are two different tasks, this violates the one and only one task guideline. Ideally, a function that calculates a value should return the value to the caller and let the caller decide what to do with the calculated value.

Quiz

1) What’s wrong with this program fragment?

01.void multiply(int x, int y)
02.{
03. return x * y;
04.}
05.
06.int main()
07.{
08. cout <<>
09. return 0;
10.}

2) What’s wrong with this program fragment?

01.int multiply(int x, int y)
02.{
03. int product = x * y;
04.}
05.
06.int main()
07.{
08. cout <<>
09. return 0;
10.}

3) What value does the following program fragment print?

01.int add(int x, int y, int z)
02.{
03. return x + y + z;
04.}
05.
06.int multiply(int x, int y)
07.{
08. return x * y;
09.}
10.
11.int main()
12.
13.{
14. cout <<>
15. return 0;
16.}

4) Write a function called doubleNumber() that takes one integer parameter and returns double it’s value.

5) Write a complete program that reads an integer from the user (using cin, discussed in section 1.3), doubles it using the doubleNumber() function you wrote for question 4, and then prints the doubled value out to the console.

Quiz Answers

To see these answers, select the area below with your mouse.

1) Hide Solution

multiply() is defined as returning void, which means it can’t return a value. Since the function is trying to return a value, this function will produce a compiler error. The function should return an int.

2) Hide Solution

multiply() calculates a value and puts the result in a variable, but never returns the value to the caller. Because there is no return statement, and the function is supposed to return an int, this will produce a compiler error.

3) Hide Solution

multiply is called where x = add(1, 2, 3), and y = 4. First, the CPU resolves x = add(1, 2, 3), which returns 1 + 2 + 3, or x = 6. multiply(6, 4) = 24, which is the answer.

4) Hide Solution

1.int doubleNumber(int x)
2.{
3. return 2 * x;
4.}

5) Hide Solution

01.#include
02.
03.int doubleNumber(int x)
04.{
05. return 2 * x;
06.}
07.
08.int main()
09.{
10. using namespace std;
11. int x;
12. cin >> x;
13. cout <<>
14. return 0;
15.}
16.
17.// The following is an alternate way of doing main:
18.int main()
19.{
20. using namespace std;
21. int x;
22. cin >> x;
23. x = doubleNumber(x);
24. cout <<>
25. return 0;


lesson 7.0
7.0

A first look at operators

Revisiting expressions

In the section Introduction to programming, we had defined an expression as “A mathematical entity that evaluates to a value”. However, the term mathematical entity is somewhat vague. More precisely, an expression is a combination of literals, variables, operators, and functions that evaluates to a value.

A literal is simply a number, such as 5, or 3.14159. When we talk about the expression “3 + 4″, both 3 and 4 are literals. Literals always evaluate to themselves.

You have already seen variables and functions. Variables evaluate to the values they hold. Functions evaluate to produce a value of the function’s return type. Because functions that return void do not have return values, they are usually not part of expressions.

Literals, variables, and functions are all known as operands. Operands are the objects of an expression that are acted upon. Operands supply the data that the expression works with.

Operators

The last piece of the expressions puzzle is operators. Operators tell how to combine the operands to produce a new result. For example, in the expression “3 + 4″, the + is the plus operator. The + operator tells how to combine the operands 3 and 4 to produce a new value (7).

You are likely already quite familiar with standard arithmetic operators, including addition (+), subtraction (-), multiplication (*), and division (/). Assignment (=) is an operator as well.

Operators come in two types:
Unary operators act on one operand. An example of a unary operator is the – operator. In the expression -5, the – operator is only being applied to one operand (5) to produce a new value (-5).

Binary operators act on two operands (known as left and right). An example of a binary operator is the + operator. In the expression 3 + 4, the + operator is working with a left operand (3) and a right operand (4) to produce a new value (7).

Note that some operators have more than one meaning. For example, the – operator has two contexts. It can be used in unary form to invert a number’s sign (eg. -5), or it can be used in binary form to do arithmetic subtraction (eg. 4 – 3).

Conclusion

This is just the tip of the iceberg in terms of operators. We will take an in-depth look at operators in more detail in a future section.