Department of Engineering

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.

Compiling    [ back to contents]

  1. Nothing's working anymore. Files aren't compiling, and when I try to save source code the files are empty. What do I do? - you might not have any disc space left. Read the Quota page
  2. What are the most common bugs? - 2 common ones this term are
    • 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.
  3. 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
    #include <iostream> using namespace std; int main() { if (2==2); cout << "2==2"<< endl; else cout << "2!=2"<< endl; }
    On some of our machines, the compiler will produce this error message.
    foo2.cc: In function `int main()': foo2.cc:7: error: expected primary-expression before "else" foo2.cc:7: error: expected `;' before "else"
    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
    foo2.cc: In function `int main()': foo2.cc:7: error: syntax error before `else'

    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.
  4. I get an error message saying "error: reference to 'count' is ambiguous" followed by lots of jargon. What's wrong? - If you've created a variable called count outside of any function it clashes with another variable called count that C++ uses internally. The solution (and it's a good general principle) is to create your count variable inside a function
  5. I get an error message saying that "The left side of '=' must be a modifiable lvalue" or "error: non-lvalue in assignment". What's a modifiable lvalue? - A value that can be modified and can be on the left of an assignment statement. A statement like "7 = i" (or "i = 7" if "i" is a const) would provoke such a message. Perhaps you have something like "if (7=i)" where you meant to have "if (7==i)".
  6. I get a warning message saying "suggest parentheses around assignment used as truth value". Is that anything to worry about? - Probably. If your code has a line like
       if (i=1)
    
    you are setting i to 1, not comparing i to 1. This isn't illegal (it's equivalent to "if(true)") but you probably meant to use 2 equals signs.
  7. I get a warning message saying " warning: control reaches end of non-void function". Is that anything to worry about? - Probably. Here's a complete program that might provoke that warning.
    int giveMe();
    
    int main() {
      int answer=giveMe();
    }
    
    int giveMe() {
      int i=0;
    }
    
    
    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
    int giveMe() {
      int i=0;
      return i;
    }
    
  8. What does "error: name lookup of `i' changed for new ISO `for' scoping" mean? - First, let's explain some terms. The scope of a variable is the region of code where the variable can be used. ISO is the "International Organization for Standardization", the body who standardised C++ in 1995. They slightly changed C++'s scoping rules.
    Consider the following code fragment
    for (int i=0;i<5;i++) cout << "looping"; i=0;
    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.
  9. I get a warning message saying something about 'using namespace std;' - just change your code the way the message suggests. If you want to know more about this, see the start of the C++ Namespaces document.

Executing    [ back to contents]

  1. My code compiles ok but it's not doing the right things - lines are being ignored etc - Some mistakes still produce legal code. For example,
    • cout < "Print this!"; prints nothing - the "<" should be "<<"
    • if (i=0) cout << "Print this!"; prints nothing - the "=" should be "=="
    • vals[i=5]; is legal, but should probably be vals[i]=5;
    • i^2 doesn't give the square of i - use i*i
    • if(1<i<100) doesn't do what mathematicians might expect - use if(1<i and i<100)
    • cin >>i,j,k; doesn't input values into 3 variables - use cin >>i >> j >> k;
    • #include <string> #include <iostream> using namespace std; int main () { std::string s="xy"+'z'; std::cout << s << std::endl; }
      compiles cleanly but doesn't produce an "xyz" string.
  2. My code compiles ok but when I run it nothing happens. What do I do? - Does your program run at all? Put
       cout << "Hello!" << endl;
    
    at the start of your main routine, and
       cout << "Goodbye!" << endl;
    
    at the end. If only the "Hello" appears, put
       cout << "Got here!" << endl;
    

    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!
  3. 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.
  4. When I compile with geany there are no error messages but it doesn't let me run the program. What's wrong? - Use the Build options in the menus.

Language features    [ back to contents]

  1. I'm confused about commas and semi-colons - Sometimes you can use a comma instead of a semi-colon, but they do different things - roughly speaking, commas separate and semi-colons terminate.
    • 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
      #include <iostream> using namespace std; int main() { if (2+2==4) cout << "2+2 is 4" << endl; cout << "So is 3+1" << endl; else cout << "2+2 isn't 4" << endl; }
      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.
      ... if (2+2==4) cout << "2+2 is 4" << endl, cout << "So is 3+1" << endl; ...
      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; ...
  2. 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
    arrays
    and the array will occupy 13*4 = 52 bytes.
  3. 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.

  4. 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.
  5. 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.
  6. How can I write my own functions? -
    • 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.
      float rectangle_perimeter(float width, float height) {
         return 2*width + 2*height;
      }
      
    • 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.
      float answer;
      answer= rectangle_perimeter(5,7);
      float width=5, float height=7;
      answer= rectangle_perimeter(width, height);
      
      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.

    float third(int number);

    int main() {
         int i=third(3);
    }

    float third(int num) {
         return num/3.0;
    }
  7. What's the difference between a function prototype and calling a function? - Let's use the sqrt function to discuss this. If you want to find the square root of 5 and put the answer in a variable called i that already exists, you do
    i=sqrt(5);
    
    This calls the function. The function runs and it gives an answer. It doesn't mention float or any other type of variable.
    Here's the prototype of the sqrt function.
    float sqrt ( float x );
    
    This describes the function, so that the compiler knows the number and type of inputs it should have. It doesn't call the function. It doesn't even check to see if the code for that function exists.
  8. What's the difference between "call by reference" and "call by value"? - Suppose we want to write a function that will triple the value of a given variable. We could try the following
    #include <iostream> using namespace std; void triple(int i); int main() { int i=3; cout << "In main, i is " << i << endl; triple(i); cout << "In main, i is now " << i << endl; } void triple(int i) { i=i*3; cout << "in triple, i becomes " << i << endl; }
    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.

    #include <iostream> using namespace std; void triple(int& i); int main() { int i=3; cout << "In main, i is " << i << endl; triple(i); cout << "In main, i is now " << i << endl; } void triple(int& i) { i=i*3; // here i is an alias for main's i }
    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.
  9. I want to create an array with a size the user types in. Can I do int i; cin >> i ; int array[i];? - Not in C++, but some compilers (e.g. g++, which we use) let you get away with it by default. Standard C++ does have ways to do this - e.g. by using <vector>
  10. How do I convert from a number to a string? - here's an example based on the C++ FAQ
    #include <iostream> #include <sstream> #include <string> std::string convertToString(double x) { std::ostringstream o; if (o << x) return o.str(); // some sort of error handling goes here... return "conversion error"; } int main() { double f=7.77; std::string s=convertToString(f); std::cout << "Length of " << f << " when converted to a string is " << s.size() << std::endl; }
  11. 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.
  12. 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.
  13. How do I convert from a string to a number? - here's an example based on the C++ FAQ
    #include <iostream> #include <sstream> #include <string> double convertFromString(const std::string& s) { std::istringstream i(s); double x; if (i >> x) return x; // some sort of error handling goes here... return 0.0; } int main() { double d; std::string s="3.14"; std::cout << "s= " << convertFromString(s) << " when converted to a double" << std::endl; }
  14. How do I convert a character to a string? - It depends what type of string you mean. Suppose you want to convert char c='A';
    • 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.
    • C++ string - Use string str; str=c;

CUED-specific issues    [ back to contents]

  1. When I run graphics programs I get "freeglut (glue): Unable to create direct context rendering for window 'GLUE' This may hurt performance. freeglut (glue): Unable to create direct context rendering for window 'GLUI' This may hurt performance.". What do I do? - Don't worry about it.
  2. 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 terminal icon at the foot of the screen), and type
      g++ -I/usr/local/include -I/usr/include/GL -L/usr/local/lib -o PlotNormal PlotNormal.cc -lglue -lglui -lglut -lGLU -lGL
    
    followed by
       ./PlotNormal
    
  3. 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.
  4. [1AC++] Can I work from the command line? - If you open a terminal window and use the cd command to move into the folder where your files are, you can compile from the command line by doing
       compile1AC++ filename[s]
    

General    [ back to contents]

  1. Why is C++ so hard? - because you haven't read the 1A C++ handout enough times.
  2. Why is the 1A C++ handout so long? - because C++ isn't easy.

1A Mich Term    [ back to contents]

  1. 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.
  2. I'm trying to do the exercises on my machine at home. It doesn't recognise random(). What shall I do? - You have an out-of-date compiler. Try using rand instead of random and srand instead of srandom.
  3. I don't understand how to count things and store the frequencies in an array new - 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
    int frequency_of_1s=0;
    int frequency_of_2s=0;
    int frequency_of_3s=0;
    int frequency_of_4s=0;
    int frequency_of_5s=0;
    int frequency_of_6s=0;
    
    Then you could roll the die 1000 times, each time adding one to the appropriate total. The code below does that.
    int experimentsDone=0;
    while(experimentsDone<1000) {
     int result=RollDie();
     if(result==1)
        frequency_of_1s=frequency_of_1s+1;
     if(result==2)
        frequency_of_2s=frequency_of_2s+1;
     if(result==3)
        frequency_of_3s=frequency_of_3s+1;
     if(result==4)
        frequency_of_4s=frequency_of_4s+1;
     if(result==5)
        frequency_of_5s=frequency_of_5s+1;
     if(result==6)
        frequency_of_6s=frequency_of_6s+1;
    
     experimentsDone=experimentsDone+1;
    }
    
    You could then print out the values at the end of the experiment.
    cout << frequency_of_1s << endl;
    cout << frequency_of_2s << endl;
    cout << frequency_of_3s << endl;
    cout << frequency_of_4s << endl;
    cout << frequency_of_5s << endl;
    cout << frequency_of_6s << endl;
    
    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
    int experimentsDone=0;
    while(experimentsDone<1000) {
      int result=RollDie();
      frequency[result]=frequency[result]+1;
      experimentsDone=experimentsDone+1;
    }
    
    Finally we need to print out the answers. Possible is
       cout << frequency[0] << endl;
       cout << frequency[1] << endl;
    ...
       cout << frequency[599] << endl;
    
    but lazier and better is
    i=0;
    while(i<600) {
      cout << frequency[i] << endl;
      i=i+1;
    }
    
    Here's a side by side comparison of the 2 versions. Even for only 6 possible outcomes "the loop and array" version is shorter.
    // initialising
    int frequency_of_1s=0;
    int frequency_of_2s=0;
    int frequency_of_3s=0;
    int frequency_of_4s=0;
    int frequency_of_5s=0;
    int frequency_of_6s=0;
    
    // initialising
    int frequency[7];
    int i=0;
    while (i<7) {
       frequency[i]=0;
       i=i+1;
    }
    
    // performing experiment
    int experimentsDone=0;
    while(experimentsDone<1000) {
     int result=RollDie();
     if(result==1)
        frequency_of_1s=frequency_of_1s+1;
     if(result==2)
        frequency_of_2s=frequency_of_2s+1;
     if(result==3)
        frequency_of_3s=frequency_of_3s+1;
     if(result==4)
        frequency_of_4s=frequency_of_4s+1;
     if(result==5)
        frequency_of_5s=frequency_of_5s+1;
      if(result==6)
        frequency_of_6s=frequency_of_6s+1;
    
      experimentsDone=experimentsDone+1;
    }
    
    // performing experiment
    int experimentsDone=0;
    while(experimentsDone<1000) {
      int result=RollDie();
      frequency[result]=frequency[result]+1;
      experimentsDone=experimentsDone+1;
    }
    
    // results
    cout << frequency_of_1s << endl;
    cout << frequency_of_2s << endl;
    cout << frequency_of_3s << endl;
    cout << frequency_of_4s << endl;
    cout << frequency_of_5s << endl;
    cout << frequency_of_6s << endl;
    
    // results
    i=0;
    while(i<7) {
      cout << frequency[i] << endl;
      i=i+1;
    }
    
  4. 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.

1A Lent Term    [ back to contents]

  1. How can I access the quiz again? - Go to the C++ quiz
  2. 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.
  3. I want to have ModelData data as a parameter to my graphics function, but it won't let me. How can I get the coordinate information into the graphics function? - - When GLUT (the graphics system that we use) needs to redraw a window it calls the function that you mentioned in the graphicsfunction call. That function has to accept exactly 2 integers, because that's how GLUT calls it - the integers are the current width and height of the window. The way we suggest you get the data into the graphics routine isn't generally recommended, but it works.
    • 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
  4. I'm getting funny errors about things not being found when I try to create a program. What's going on? -
    • Are you trying to "Build" the program using the Brick icon? That was ok for single-file programs, but now you need to use the Make option in the "Build" menu.
    • Have you saved all the changed files? "Build" auto-saves source files, but "Make" doesn't.
    • Have you tried to compile some of last term's files while having this term's project open in geany? If so, shut down geany and load in your project again.
    If all else fails, just shut down geany and restart it, re-loading the project file that's in your 1ATrading folder.
  5. After I call glueGo() none of the function calls work - glueGo needs to be the last thing you call - see the GLUE graphics page for details.
  6. I can't make the graphics work - The simplest description is on the GLUE page. For the Lent course, you've already been given the code to create a window. There is
      glueWindow();  
      graphicsfunction (mygraphics);
      glueGo();
    
    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
      void mygraphics(int w, int h) {
        color(BLUE);
        text("I wish I was a graph", 10, 100);
      }
    
    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!)
  7. 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.
  8. 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.
  9. In geany, what's the difference between Build, Compile, and Make? - Use Make to create a program from a multi-file project. Use Build if all the source code for your program is in one file. Compile will only create a *.o file from the current *.cc file (i.e. it won't create a new program)
  10. When I load a shared project in, it contains no source files. What do I do? - Perhaps you've accidentally removed the orginal project file, or confused geany by adding/removing source files. You can recreate it as follows
    • Use the little terminal icon at the foot of the screen to start a new window
    • In the new window, type ~tpl/bin/fixsharedgeanyproject
  11. 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.
  12. When I Make in my shared folder, it tries to use files from my private space. What's wrong? - Maybe you shipped your 1ATrading.geany file as well as your source file. Type ~tpl/bin/fixsharedgeanyproject in a Terminal window to fix things.
  13. It says "Must agree price every day" What does that mean? - It can mean a few things. For example you might be asking for the price on day 0, or asking for the price twice in the same day.
  14. Can I add new files to the ones provided in the Trading exercise, or change their names? - yes, but only if you know about Makefiles.
  15. 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.

1B IDP    [ back to contents]

  1. 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.
  2. I'm having trouble with const and extern - If you have
       int speed=3;
    
    in a file outside of all functions, then this variable can be accessed from other files as long as the other files have
       extern int speed;
    
    but if instead of int speed=3; in the first file you have
       const int speed=3;
    
    the variable isn't visible from other files. Here's a table showing some examples of how the contents of 2 files can interact.
    File 1File 2Outcome
    int i;
    int main()
    {
      i=5;
    }
    
    extern int i;
    Compiles. There's only one variable called 'i'.
    int i;
    int main()
    {
      i=5;
    }
    
    int i;
    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.
    extern int i;
    int main()
    {
      i=5;
    }
    
    int j;
    Fails (undefined reference to 'i') because File 1 expects an 'i' variable to be available from another file.
    extern int i;
    int i;
    int main()
    {
      i=5;
    }
    
    int j;
    Compiles. The int i; line takes precedence over the extern int i; line.
    static int i;
    int main()
    {
      i=5;
    }
    
    int i;
    Compiles. File 1's 'i' is private - there are 2 variables called 'i' but they don't clash
    const int i=5;
    int main()
    {
      ;
    }
    
    int i;
    Compiles. File 1's 'i' is private (const vars are static by default) .
    extern const int i=5;
    int main()
    {
      ;
    }
    
    int i;
    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 extern and 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
  3. When I try to 'Make' my code it's producing strange error messages - This may be because you have a space in a folder-name or file-name associated with the project files. Get rid of the spaces and try again.
  4. When I use the geany IDP icon it doesn't work. - you need to use Make in the Build menu: clicking on the Brick icon isn't enough.
  5. I've created a file in geany, but I can't compile it - Quit from geany, then drop the source file into geany
  6. Do I have to keep selecting and dropping my files into the geany icon? - No. If you do it once and don't create any new files (or add any #include lines) then you can repeatedly Save and Make. If you quit geany and run it again, it should resume from its previous state.

Advanced    [ back to contents]

  1. How can I see if a key's been pressed without having to wait for the user to press the Enter key? I want something like Windows' kbhit - The following works on the Linux Teaching System in a text window, but note that if you interrupt the program while it's in non-blocking mode, normal behaviour won't be restored.
    #include <iostream> #include <cstdlib> #include <unistd.h> #include <time.h> #include <termios.h> #include <sys/select.h> /* According to POSIX 1003.1-2001 */ using namespace std; int tty_mode = 0; struct termios orig_tty; struct termios new_tty; // Sets up terminal for one-char-at-a-time reads void cbreak (void) { if (tty_mode == 0) { tcgetattr(0, &orig_tty); tty_mode = 1; new_tty = orig_tty; } new_tty.c_lflag &= ~(ICANON | ECHO); new_tty.c_cc[VMIN] = 1; new_tty.c_cc[VTIME] = 0; tcsetattr(0, TCSANOW, &new_tty); } // Returns terminal to normal state after cbreak () void normal (void) { if (tty_mode == 1) { tcsetattr(0, TCSANOW, &orig_tty); new_tty = orig_tty; } } // Checks keyboard buffer (stdin) and returns key // pressed, or -1 for no key pressed int keypress (void) { static char keypressed; struct timeval waittime; int num_chars_read; fd_set mask; FD_SET(0, &mask); waittime.tv_sec = 0; waittime.tv_usec = 0; if (select (1, &mask, 0, 0, &waittime)) { num_chars_read = read (0, &keypressed, 1); if (num_chars_read == 1) return ((int)keypressed); } return (-1); } int main() { char c; normal(); cout << "type a character (normal mode): "; cin >> c; cbreak(); cout << "type a character (non-blocking): "; while ( keypress() == -1) { cout << "ok, I'll wait a second" << endl; sleep(1); } cout << "Thanks. Returning to normal behaviour" << endl; normal(); return 0; }
  2. How do I initialize static class members? - Here's an example
    #include <iostream> using namespace std; class fish { public: static int count; fish(void) { cout << "making a fish object" <<endl; count++; cout << "count = " << count << endl; } }; int fish::count=0; int main() { fish fish1, fish2; return(0); }
    Note that the "int fish::count=0;" line can't be inside the main (or any other) function.
  • © Cambridge University, Engineering Department, Trumpington Street, Cambridge CB2 1PZ, UK (map)
    Tel: +44 1223 332600, Fax: +44 1223 332662
    Contact: helpdesk