IT Services

C++ FAQ

Here are some answers to C++-related questions commonly asked at CUED.
If you can think of questions that should be added here,
mail Tim
Love (tl136). A more comprehensive list of C++
Frequently Asked
Questions is available, though it's not aimed at absolute beginners.

cin >>endl; - this can produce pages of
error messages. You can only use endl with cout because you
output new-line characters.

#include <iostream,cmath> - you need a separate
#include line for each file you include.

What do the compiler's error
messages mean? - sometimes it's not easy to tell - the messages can be confusing, though some compilers are more helpful than others. At least the message will give you a line number telling you where the compiler first got into trouble. The cause of the trouble may be earlier though. Here's an example

What is a "primary-expression"? It's unhelpful jargon. The line number given is
7, where it expected `;' before "else" (by the way, the emacs
editor shows the line number near the bottom of its screen). So should we
add a semi-colon just before "else"?
On another machine
with a newer compiler the error message is

which looks more vague than the other message, but is actually less confusing,
because the problem is that there are too many semi-colons in the program, not
too few (see the semicolons question for details - the problem is on line 5 of the code).

So don't expect to the compiler to exactly location and diagnose the problem.
The first error in your code may cause lots of further errors, so fix that first.

Sometimes the cause of the error may be a long time before the reported line-number. If you get an error message saying that there's a problem with your final line
of code

error: syntax error at end of input

the reason is likely to be that you have an opening brace - a "{" - early in your program
that isn't matched by a closing brace - a "}". The compiler won't realise this until it reaches the end of your file.

The trouble is that the giveMe function is supposed to return an integer (i.e. give
an integer as its result) but at the moment it returns nothing. Consequently the answer
variable in the main function won't be set to anything sensible. The warning message
will disappear if the giveMe function is changed to

The "for" statement creates an integer i that is used to control how many times the loop goes round. Because it's created inside the "for" statement,
its scope in ISO C++ extends only to the end of the body of the loop, so
by the time i=0; is reached, i no longer exists. With older C++ the i=0; line would have been legal because i's scope was wider.

half way down your program, and continue this way until you've worked out roughly where
the problem is.

You may have an "infinite loop" problem. Have a look at this code fragment.

int i=0;
while (i<5)
i++;

Here i starts with the value 0 and is incremented
each time the loop's executed until i is 5, after which the rest of
the code is run. But suppose the user writes

int i=0;
while (i<5);
i++;

Notice the extra semi-colon? It makes a lot of difference. In this situation ";" is a C++
command which does nothing, and it's this command (rather than i++;)
which is executed in the loop. Consequently i will always be 0 and
the loop never ends!

What are 'nan' and 'inf'?
- Sometimes when you print out the result of a calculation you will see inf or nan. inf is short for 'infinity' - you might get it if you do 1/0, for example. If you do 0/0 you might get nan - Not-a-Number. The solution is to check if a value is 0 before dividing by it.

Commas - you need them if you're creating several variables on the same line. For example, "int i,j;" creates 2 integers. Note that the semi-colon ends the statement. Equivalent would be "int i; int j;". You also need them to separate arguments when writing or calling functions. E.g. "pow(2.0,3.0);" calculates 2 cubed. Though commas can be used in other situations, beginners should stick to these uses.
That said, commas can be leglly used elsewhere. If you try to compile the following code

it won't work because there are 2 statements between "if" condition
and the "else" line, and the "if" condition only expects one.
You should bundle the 2 statements together by putting them inside curly brackets ({ and }), but it's also legal to put a comma between
the statements to make them into a single statement - i.e.

Try not to do this - it leads to confusion. Use curly brackets instead.

Semi-colons - Semi-colons are used when setting up a
"for" loop - the syntax is "for(...;...;...)", though
their main
use is to end statements. Note that an "if", "while" or
"for" statement doesn't end straight after the test condition.
It's not illegal to put a semi-colon there, but it's rarely what you
want. The following code is legal and
will print out "2+2 is 3"

...
if (2+2==3);
cout << "2+2 is 3" << endl;
...

Why? A semi-colon is also a null command (a command that does nothing), so
the "if" test controls whether or not the semi-colon null command
is run. The cout command isn't under the control of the "if" test
and so is always run. The following layout of the same code gives a better
impression of what the code actually does

...
if (2+2==3)
;
cout << "2+2 is 3" << endl;
...

What is an array? - When you have lots of variables that are related in some way, it's useful
to clump them together somehow. Arrays offer a way to do this as long as
the variables are all of the same type. For example, if you want to store
some integer information about each month in an array, you could use

int month[12];

to reserve space for 12 integers. The integers would have the names
month[0], month[1] ... month[11] because array indexing starts at 0. If you
don't want to start at 0 you could ignore the first value and just use
month[1], month[2] ... month[12], but you then need 13 integers so you must
create the array using

int month[13];

The items in the array are usually referred to as elements. They're
stored contiguously in memory, so if integers occupy 4 bytes, and the
first element starts at memory location 1000 (base 16), the layout of this
13-element array will be

and the array will occupy 13*4 = 52 bytes.

What is a structure? - Sometimes you want to clump variables together even though they're not all
the same type. For example, to clump together information about a football
team you might need to use integers, real numbers and text. A structure lets you bundle together all types of variables. Whereas in an array
each component is numbered, in a structure each field has a name.
The following code defines a structure

struct Team {
int points;
float goal_average;
string sponsor;
};

Note that this code doesn't in itself create a new variable but a
new type of variable. As well as being able to create standard,
simple variables of type int, float, etc, we've extended the language
so that we can now create a Team as well by doing

Team cambridge;

The fields of this variable can be individually accessed using
cambridge.points, cambridge.goal_average, and cambridge.sponsor.
Note that you can have arrays inside structures, and you can have structures
of arrays - Team teams[22]; would create an array of 22 Teams. Note also that classes can do everything that structures can do, and more.

The memory taken up by a structure may be more than the sum of the sizes of
the fields - for speed-efficiency reasons, there are sometimes gaps between fields.

What is casting? - Casting is a way to create a new "thing" from an old one. The new
"thing" is likely to have the same value as the old one, but it will be a
different type of thing. It's somewhat analogous to casting something in bronze - the new object is a copy of the original but is a different type of thing.
Why is casting sometimes necessary? In C++ if you divide one integer by another, you'll get an integer, so 1/2 will have the result 0. There are good reasons why this is so, but it's not always the result you want. How can you get the answer 0.5? As long as at least one of the values is a floating point number, the result will be a floating point number, so in this case you could do 1.0/2. More often the situation's not so easy. In this code

int i=1, j=2;
float answer;
answer=i/j;

answer will be 0. If i and j were floats we'd get the answer 0.5, but sometimes we're not in a position to make such a change. There are at least 4 ways to rewrite the answer=i/j; line to get the answer 0.5.

float tmp=i; answer=tmp/j; - this creates a new floating point variable tmp which has the same value as i. When this is divided by the integer j the result will be a floating point number. However, creating an extra variable like this is messy.

answer=(1.0*i)/j; - the 1.0*i expression creates a floating point value, which divided by the integer j will produce a floating point number.

answer=(float)i/j; - this is another way to produce a floating point equivalent of i. It's an old method of casting that's unsafe in some other situations.

answer=static_cast<float>(i)/j; - this is a newer, safer way of casting. Note that the position of the brackets matters. answer=static_cast<float>(i/j); would give the answer 0 because by the time the casting is done, the integer division has already happened.

How can I add one to a variable i? - Common ways are - i++; (or ++i;) and i=i+1;. If you mix these up and try i=i++; you're asking for trouble - the right-hand side is trying to change i and so is the assignment. As likely as not i won't change.

Write the function - in particular you need to say
what inputs (i.e. what type of "arguments" or "parameters") the function has to be given, and
what output is returned. In the following example the
function takes 2 floats and returns a float. The returned value can be used by
the code that calls the function.

Declare the function - before the compiler will let you call a
function it has to know the type and number of arguments it takes, so that
the compiler can tell you whether you're calling the function correctly.
You need to declare the function by providing a function prototype (otherwise
known as a "signature"). A prototype for the above function would be

float rectangle_perimeter(float width, float height);

(i.e. the same as the first line of the function but with an added semi-colon)
This doesn't call the code, it just tells the compiler about the
function. The names of the variables here don't matter. It's just as legal
to say

float rectangle_perimeter(float, float);

Call the function - when you call the function (i.e. execute it,
make it run) you need to
provide the right number and type of arguments. Arguments can be numbers
or variables. Here, rectangle_perimeter is called twice, giving
the same answer each time.

Note that you don't mention the type of the arguments when you
call a function - answer=rectangle_perimeter(float width, float height); is wrong. Note also that though the argument names here (width and height) match
the names of the arguments in the function code, that's coincidental and irrelevant.

Here's a complete program showing these features in action. You can hover the
point over the text to get descriptions of its purpose.

But it doesn't work as we wanted - the i in main doesn't
change. The problem is that
main's i is a different variable to the i in
triple. That the 2 variables have the same name
is a coincidence (if the i variable in the triple function was called j the code would work just as well). The only link between the 2 variables is that
when triple is called, triple's i gets its initial value from
main's i - i is being passed "by value".

If we want to change main's i we need to "call by reference" -
note the added ampersands.

If you run this, you'll find that the i variable in main changes. Note that you don't use an ampersand when you call the triple function.

In C++, what's the difference between "if" and "while"? -
Quite a lot. The following 2 fragments of code differ only in that one uses "if" and the other uses "while", but the behaviour is very different. Before reading the explanation that follows the code, try to guess what each fragment does.

"while" is the start of a loop - while the expression in the brackets is true, the execution of the code cycles round, checking the expression repeatedly. With "if" there's no loop - the code in the braces is run once if the expression is true, otherwise that code isn't run at all. So the first fragment causes "hello" to be printed once, and the second expression causes "hello" to be printed 5 times.

What does return 0; do at the end of the main function? -
Not much. Let's first review what return does in other functions.
In a function, return ends the running of the function's code and gives a value back to the
calling expression. For example, if you wrote a function called
squareroot that had return root; at the end of it,
then f=squareroot(4); would call squareroot, and
the value of root in the squareroot code would be put into the variable f.
If a program has return 0;
at the end of its main routine, the 0 is returned to whatever called the program. Mostly of the time this value is ignored, so you needn't worry about the value returned, but if you want to see the mechanism in action, open a Terminal window. We're going to use a program (written in C) called ls. It lists files and also returns a value from its main function that we can see.
Type ls to see what files are in the current folder. Suppose file1 exists,
but file2 doesn't.
Then

ls file1
echo $?

will display 0 (because the ls command does return 0; when it succeeds, and the command line has a variable called $? which stores the returned value). If you type

ls file2
echo $?

it will display 2 (because the ls command does return 2; when there's "serious trouble"). This return value is often ignored by users, but it's a good
habit to return something from main.

Note that

When a function is supposed to return an int, the compiler
will usually complain if you don't explicitly do so, but main is a
special case - the return isn't compulsory

If you have exit(2); anywhere in your code (not just in main) the program will end, and 2 will be returned to whatever called the program.

What are header files? What are
they for? What does using namespace std; mean? - Header files are files whose names usually end with .h and contain prototypes, definitions, etc so that you can use some extra routines. By default, C++ doesn't even let you use cout to print to the screen (cout is an "extra" routine), so most programs need to include header files. There are a few dozen standard header files, and you can write your own. Putting #include<iostream> in your program tells the compiler to read in the standard header file(s) for I/O (input/output). But that still
isn't enough to let you use cout. You also need to tell the compiler that the cout routine belongs to the standard part of the library of routines. If you put "using namespace std" at the top of your file, the compiler will look in the std (standard) section for routines.This is true for all the standard files
(cmath, etc). If you're not including any files, or if you're only using
non-standard files (ones you've written yourself for example) then you don't need "using namespace std;".
An alternative to having "using namespace std;" is to use std::cout instead of cout, std::endl instead of endl,
etc., but that's a bit tedious.

C-style string (character array) - The following won't work, though it's legal - char *str=(char*)c;. This creates a pointer str that will point to memory location 65 (the ASCII value of 'A').
If you try to read or write at that location, your program will crash. Try this
instead - char str[2]; str[0]=c; str[1]=0;. This creates space to store the string and ensures that it's appropriately terminated.

Why doesn't the PlotNormal.cc
Example compile? - It uses some extra files that are in special
places on the Teaching System, and not all of our compilers look for these
extra files. Save the file in your home folder as PlotNormal.cc, open a
Terminal Window (use the little icon at the foot of the screen), and type

Can I work away from the
DPO? - You can work on your own machine or use your machine to log into the
department's computers. Neither option is trouble-free yet

Working on your own machine - If you follow the instructions on our Installing C++ compilers page you'll have enough to do the Mich term work and the Mars Lander Exercise.
The MDP Resource CD provides some of what you need. The Start/Programming/Xcc ... menu options offer a set-up suitable for Mich term work and general C++ practise.
What's lacking with both of these options is a start command to set things up ready for the exercises. Also none of the Trading code is available for the Lent term exercise.

Working remotely - Our Remote 1AC++ Computing page shows you
how to do Michaelmas term's course remotely. More generally, our Remote Access page shows various ways that you can use CUED machines remotely.

How do random numbers
work? - random() returns a random integer in the range 1 to RAND_MAX.
By default the sequence of "random" numbers will be the same each time you run
your program. The srandom function controls where the sequence will
start. Doing srandom(time(0)) starts the sequence at a value
determined by the system clock. You should call this once before starting to
use random() otherwise your numbers won't be very random. You should
only call it once in a program - if you call it every time you call
random(), you'll not get random numbers.
You'll need #include <cstdlib> and using namespace std; at the top of the file
to access these random number routines.
The numbers produced by the random routine are only pseudo-random.
See
wikipedia's Random number generation page if you want more details.

I don't understand how to count things and store the frequencies in an array -
Suppose you have a function called RollDie that simulates the rolling of a die, returning an integer in the range 1 to 6. Suppose you wanted to call RollDie 1000 times and record how many 1s were thrown, how many 2s were thrown, etc. You could have a variable to store
the number of 1s thrown, another to store
the number of 2s thrown, etc. You'd have to set them to 0 intially. You
could do it like this

This works, but is tedious and gets more tedious when instead of 6 possible outcomes there are hundreds. Arrays can help.
Arrays are groups of variables of the same type. The line

int frequency[600];

creates an array called frequency with the space for 600 integers.
The first one is frequency[0], the second frequency[1], etc. We'll
store the frequency of zeroes in frequency[0], the frequency of 1s in frequency[1], etc. First we need to initialise them all to zero. We could do

frequency[0]=0;
frequency[1]=0;
...
frequency[599]=0;

but loops work well with arrays. We can set all 600 variables to 0 using

int i=0;
while (i<600) {
frequency[i]=0;
i=i+1;
}

The code to run the experiments and record results is shorter too. If we do

int result=RollDie();

and
result comes out to 3, then we need to add 1 to frequency[3]. More
generally, we need to add 1 to frequency[result], so the code reduces to

What books do you
recommend? - don't assume that if only you could find the right
book, suddenly everything will become clear. You might get lucky, but you'll
still need to write programs. There are many, many C++ books around - in public libraries, 2nd bookshops,
etc. Anything that's plain, pure C++ without extensive Mac/Windows add-ons should
be ok. Some books come with a CD to save you having to install compilers. "C++ How to Program" by Deitel, H.M and
Deitel, P.J. (the book mentioned in the course notes)
goes way beyond what you need (the index is over 50 pages long; arrays
aren't mentioned until p.300+) but it's thorough, colorful and has many
examples.

Why hasn't my score shown up in the
trading league tables? - Maybe you didn't use the TE_CloseTrading function, or you didn't run your program from within the shared 1ASoftwareDesign directory. You need to run it using geany's's Execute button (or from the command line) rather than just clicking on the icon.

In OurTradingMain.cc put the line ModelData data; before
the main function. This creates a variable that is potentially visible from other files. Note: this isn't usually a good thing to do.

Near the top of the file containing the graphics function (after the line that includes trading.h) put extern ModelData data; - this doesn't create a new variable, but lets you use the data variable that's external to this file

at the end of your main function. These lines create a window,
tell the computer which of your functions will draw into the window you've
created, then give control over to the computer. You won't need to change these lines. There's also a prototype

void mygraphics(int w, int h);

in OurTradingHeader.h and the mygraphics function itself
in OurTradingFunctions1.cc. Initially the function contains
just

but you can add to this to create axes and lines.
If the window appears but your data-points don't

Check that you're not drawing white lines on a white background

Check that the coordinates of the things you're drawing are within the
region shown on your graph (use cout to display the coordinates on screen!)

I can't find the details I want in the coursework web-page - the web-page comes in different versions depending on whether you want the trading details, the statistics details, both or neither. Read the early paragraphs.

What does the Ship icon actually
do? -
It copies the files dropped into it to an area of disc that you and your partner share. It also changes the 'permissions' on the files so that you and your partner can both read and change them. You can get to the shared area by clicking on the 1ASoftwareDesign folder within your 1ATrading folder. If instead of shipping you copy files into the 1ATrading folder, they won't be readable/modifiable by your partner.

Use the little terminal icon at the foot of the screen to start a new window

In the new window, type ~tpl/bin/fixsharedgeanyproject

Geany's Execute/Run button isn't working - it says it can't find a file - Reload the project file - i.e. use the Open option in the Project menu to open the 1ATrading.geany file that's in the same folder as the files you're working on.
If that fails (if at the bottom of the Geany window you see Terminal program can't execute, or it's trying to run the wrong program), do the following -

Exit from geany

Use the little terminal icon at the foot of the screen to start a new window. In the new window, type ~tpl/bin/fixprivategeanyproject

Remove the .config/geany folder in your home folder if you have one

Remove the geany_run_script.sh file (if you have one) in your project folder

Restart Geany and load in the project file

If that fails,

Use the little terminal icon at the foot of the screen to start a new window

In the new window, type cd 1ATrading (or cd 1ATrading/1ASoftwareDesign if you want to run the team version). You can now type ./Trading in the window whenever you want to re-run your program.

Have I finished? - You can find out for yourself. See the checklist. In particular: check that your calculated a, b, mean and variance are reasonable; check that your estimate of the final stock and balance matches the bank's; check that you've correctly created the file that stores the information about your trading.

My code compiles on the workstations but not on ARM - sqrt doesn't work - The maths libraries on the 2 systems aren't (in 2010 at least) quite the same. In the maths library there's a version of sqrt for floats and a version for doubles. If you provide integer parameters the maths library on the workstations copes, but on the ARM system the compiler doesn't know whether to promote the ints to floats or doubles. If you cast both ints to float your code will work on both systems.

Fails (multiple definition of 'i') because when the 2 compiled files are linked together they each have an 'i' that is visible to the other. Why? Because if a variable is declared as externand it's initialised, then memory for that variable will be allocated. So in this situation there's an 'i' in each file.

extern const int i=5;
int main()
{
;
}

extern const int i;

Compiles. There's only one 'i' variable in the resulting program - the 'i' in file 2 refers to the 'i' in file 1. If the line in file 2 was extern const int i=2;, linking would fail