When people talk about what computers are good at they often mention boring repeatitive computational tasks and it is certainly true that most scientific programmes involve the computer to almost the same calculation again and again. This is a loop and the two main ways to do loops in c++ are for and while.
ForAdd.cpp
4.1
1 #include<iostream> 2 3 using namespace std; 4 5 int main() 6 { 7 8 9 int high=100; 10 11 12 int total=0; 13 for(int i=0;i<=high;i++) 14 total+=i; 15 16 cout<<"Sum of the numbers from 0 to "<<high<<" is "<<total<<endl; 17 18 return 0; 19 }
ForAdd.cpp (4.1 is a programme for adding all the numbers from zero to 100; as you all know you don't need a computer for this, you just pair up 0 with 100, 1 with 99, 2 with 98 and so, so each pair makes a 100 and every number is paired except 50, so the answer is 5050. Lets pretend we don't know the trick: the loop is at lines 4.1.13/14 and is controlled by the for statement. The for statement has three arguements seperated by semicolons. Each is an expression and so the semicolon makes some sense; the first arguement declares and initializes a variable, in this case an int named i initialized to zero. The next statement is a boolean expression, the loop will continue as long as this is true, here the expression is i<=high which remains true until i gets to 101, at which point the loop is not executed and the programme continues with the next line, in this case the cout on line 4.1.16. The final statement is a command which is run at the end of each loop, here i++, increasing i each time. Now the i, declared where it is, is only scoped inside the loop, which is very useful since you may need to do lots of loops and it would be inconvient to end up with lots of variables declared for different loops: in fact, at line 4.1.15 i will have been deleted and the name i could be used again for something else.
One thing you have to realise is that the syntax of the if statement is designed for convenience and legibility as well as computational constraints. For example, the i could have been declared before the loop and the increament, i++ could have been written at the end of the loop where it actually occurs
ForAdd_4.2.cpp
4.2
1 #include<iostream> 2 3 using namespace std; 4 5 int main() 6 { 7 8 9 int high=100; 10 11 12 int total=0; 13 14 { 15 int i=0; 16 17 for(;i<=high;) 18 { 19 total+=i; 20 i++; 21 } 22 } 23 24 cout<<"Sum of the numbers from 0 to "<<high<<" is "<<total<<endl; 25 26 return 0; 27 }
In 4.2 the first and third arguement of the if statement are blank, the declaration and initialization are done at line 4.2.15 and the braces at lines 4.2.14/22 restrict the scope of i the same way it would be restricted if it have been declared in the if statement; the increment is now done at line 4.2.20. In fact, we will see later on that the while statement is identical to the if statement with the first and third arguement blank and they can both perform the same function. However, the particular convenience of the normal if statement is that it allows the three important parts, the declaration and initialization of the loop variable, the boolean expression that limits the loop and the principle change to the loop variable, to be kept in one place. In 4.2 you should also note the braces at lines 4.2.18/21, the bracket the loop, something we need to do when the loop contains more than one line of statement.
The next programme is just another if example, it examines the accuracy of the Euler method for solving the growth equation f'=rf. Euler's method is the simple approach of dividing time into time steps and making f increase by f' by the step size for each step, it basically uses the first order approximation in the Taylor expansion.
Growth.cpp
4.3
1 #include<iostream> 2 #include<cmath> 3 4 using namespace std; 5 6 int main() 7 { 8 9 double r=.25; 10 11 double x0=0; 12 double x1=5; 13 double f0=2; 14 15 16 deltaX=.1; 17 18 double f=f0; 19 for(double x=x0;x<=x1;x+=deltaX) 20 { 21 f+=r*f*deltaX; 22 cout<<x<<" "<<f<<" "<<f0*exp(r*(x-x0))<<endl; 23 } 24 25 return 0; 26 }
The for loop in this programme, lines 4.3.19-23, is pretty unremarkable, it has two statements in the loop so it uses braces and it the loop variable is a double which increases an amount deltaX at the end of each iteration.
There are a few other things to note about this programme. First, the cmath package is included at the start, this is so that we exp available at line 4.3.22; if we weren't using the std namespace this would be std::exp. Furthermore, notice that I avoid using numbers in the programme proper, instead defining parameters, like $r$, the rate, at the start, this is good practise, it makes it easier to change the parameters later, even if you don't think this will ever happen, you should declare parameters at the start, just in case. Finally running the programme just gives a long stream of numbers; it is nice to plot them. Perhaps the easiest way to do this is to redirect the output into a file.
4.4
1 $g++ Growth.cpp -o gr 2 $ ./gr > Growth.dat
So, in line 4.4.2 I have redirected the output to the file Growth.dat, a name I chose for convenience and not because I had to chose a name that coincided with the programme name. The redirect, a greater than symbol, >, is a unix command that sends what should have been printed on the screen into a file. Hence, the programme doesn't output to file, as far as it is concerned it is outputting to screen, however, this output is being redirected by the shell, the window where the output would have appeared. It is not difficult to add an output to file into the programme, however, for very simple output a redirect is often simpler. The redirect will create the Growth.dat if it doesn't exist, if it does, it will delete the previous contents; a similar redirect >> will create the file if it doesn't exist, but append to its current contents if it does.
Growth.dat is a simple text file comtaining the three columns of numbers. The file can be opened in emacs, it can be printed out using the unix command cat as in cat Growth.dat, the first few lines can be printed out using head Growth.dat or the last few using tail Growth.dat. awk could be used to do calculations on the columns. However, the obvious thing to do here would be to graph the data. Perhaps the quickest way to do that is to use gnuplot. Input gnuplot in the same directory as Growth.dat to enter gnuplot and then use
4.5
1 gnuplot> plot "Growth.dat" using 1:2 with lines 2 gnuplot> replot "Growth.dat" using 1:3 with lines
The first gnuplot command, line 4.5.1 tells it to plot the data in Growth.dat using columns 1 and 2 with the plot done with lines. The second line, line 4.5.2 is the same but it plots columns 1 and 3 and it has a replot command instead of a plot command, this means the graph is added on top of the previous one, instead of plotting a completely new graph. In gnuplot using can be abbreviated to us and with to w.
As mentioned above, the while is similar to the for loop and is used when it is not useful to include a declaration and increment. The syntax is while(boolean) followed by some statements enclosed in braces where, as with for and if, the braces aren't needed if there is only one statement. The loop continues as long as the boolean evaluates to true. Here is an example below where a letter is removed from a word with each iteration of the loop.
EraseString.cpp
4.6
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 int main() 5 { 6 string word; 7 cout<<"Input your favourite word!"<<endl; 8 cin >> word; 9 while(word.length()>0) 10 { 11 12 char letter=word.at(0); 13 word.erase(0,1); 14 cout<<letter; 15 16 if(word.length()!=0) 17 cout<<"*"; 18 19 } 20 21 cout<<endl; 23 23 return 0; 24 }
giving
4.7
1 Input your favourite word! 2 Elbow 3 E*l*b*o*w
This programme uses a few methods in the string class: word.length() returns the length of word and so word.length()>0 at line 4.6.9 is true until all the letters in word have been erased. In line 4.6.12 word.at(0) returns the first letter in word as a char and it is assigned to the char names letter; in the next line word.erase(0,1) erases one letter of word starting with the first, 0th, one. The purpose of the if in line 4.6.16 is to have the programme only print *s between the letters, not after the last one when word.length()==0.
Exercises 4