We took a look at C++'s unique ternary (as opposed to binary) operator, the ? : conditional operator. The following example illustrates quite well.
The challenge is to write code which calculates the maximum of two integers. Following are two solutions:
Solution 1 Solution 2
if (x > y)
max = (x>y) ? x : y;
max = x;
else
max = y;
Tonight, we considered loops in more detail. In particular, the while loop has the following syntax:
while (boolean expression)
statement;
Example. Write a program that takes a sequence of numbers from the keyboard and averages them.
//File: while.cpp
#include <iostream.h>
int main()
{
cout << "How many items would you like to average? " << endl;int number_of_items;
cin >> number_of_items;cout << number_of_items << "\n\n"; // echo input
int k = 0, sum = 0; // initialize counter and sum variables
while (k < number_of_items)
{
int number; // declare local variable, number
k++; // increment counter
cin >> number; // input next number
cout << number << endl; // echo inputsum += number; // add to accumulating sum
}// NOTE: The variable 'number' is unknown outside its scope,
// so, cout << number << endl; would give error message here.int average = 0;
if (k > 0)
average = sum / k;cout << "average = " << average << endl;
return 0;
}
// ALTERNATIVE (to output "real" average)
// float average = 0.0f;
// if (k > 0)
// average = static_cast<float> (sum) / k;NOTE: Remember that "real" constants are by default of type double, so float x = 1.2; instead of float x = 1.2f; would generate the following warning:
'initializing' : truncation from 'const double' to 'float'
We introduced the for loop which, as usual, makes counter-controlled loops somewhat easier to code. For example, the problem of averaging a list integers reduces to:
//File: for.cpp
#include <iostream.h>
int main()
{
cout << "How many items would you like to average? " << endl;int number_of_items;
cin >> number_of_items;cout << number_of_items << "\n\n"; // echo input
for (int k=0, sum=0; k<number_of_items; k++)
{
int number; // Local variable; undefined outside loop!cin >> number;
cout << number << endl; // echo inputsum += number;
}int average = 0;
if (k >0)
average = sum / k;//NOTE: The C++ standard states that since both k and sum were
//defined in the for loop, they are undefined outside the loop.cout << "average = " << average << endl;
return 0;
}
To summarize, the syntax for the for loop is:
for (initialization; test condition; incrementation)
statement;
This might lend itself nicely to the numerical calculation of integrals, for example, with intervals of width deltax_x; e.g.,
for (x = 0.0; x <= 12.5; x+=deltax)
{
....
}
As a final note, it is also possible to construct very strange looking for loops with nothing in the 3 categories:
//File: nulloop.cpp
#include <iostream.h>
#include <stdlib.h>
int main()
{
int k=0;
for (;;)
{
cout << k << endl;
k++;
if (k > 10) exit(EXIT_SUCCESS);
}
return 0;
}
Remember, though, that just because something is possible doesn't make it good programming practice!
Lab Exercise. Write a program that approximates the integral of 'x squared' between 0 and 1. (Answer: 1/3) Try it yourself, but you can then check my solution, integral.cpp if you like.
Example 1. Function int sum (int, int) takes two numbers and returns their sum as follows
//File: sum.cpp
#include <iostream.h>
int sum (int a, int b)
{
return (a + b);
}
int main ()
{
int x = 3, y = 7;
cout << "The sum of " << x << " and " << y << " is: " << sum(x,y) << endl;
return 0;
}
The parameters a and b are called formal parameters while the variables x and y are called actual parameters. The formal parameters are stand-in's for the actual parameters of the calling function. Furthermore, in this example, the formal parameters are value parameters; i.e., the actual parameters, x and y, provide values (3 and 7 respectively) to initialize the newly created memory locations, a and b. The RAM locations a and b are discarded when execution exits the function sum. Note that a and b occupy memory locations distinct from those of x and y; hence, operations within the function involving those two parameters can have no effect on the variables x and y in main().
Of course, there are times when it is desirable for the executing function to affect changes in the calling function. Indeed, since C and C++ do not provide facilities for creating procedures, the only alternative is to have provision for creating reference parameters. In Pascal, these are the VAR parameters or in/out parameters. Suppose we consider the following function designed to swap the two values passed to it. Note here the use of & to denote reference parameters. The formal parameters a and b take as values the addresses of the variables x and y respectively. So, when values are given to a and b within swap(), they are in effect simultaneously given to the variables x and y. Indeed, you could think of a and b as aliases for x and y within the function swap(). Using the language of pointers, a and b are pointers to x and y. Fortunately, we do not have to perform the pointer arithmetic directly; it is done for us.
Example 2. Write a function that takes two values and swaps them.
//File: swap.cpp
#include <iostream.h>
void swap (int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int x=15, y=25;
cout << "The numbers x and y are: "
<< x
<< " and " << y << " respectively." <<
endl;
swap (x, y);
cout << "After the swap, the numbers x and y are: "
<< x
<< " and " << y << " respectively." <<
endl;
return 0;
}
If you're interested in playing with the C version, just download cswap.cpp
Example 1. Write a program which creates an array called 'list', initializes it, and outputs it.
//File: array.cpp
#include <iostream.h>
int main()
{
int list[10]={10, 20, 30, 40, 50, 60, 70,
80, 90, 100},
k;
for (k=0; k<10; k++)
cout << list[k] << endl;
return 0;
}
Unlike Pascal, which asks the programmer to set the indexing, a C++ array, list[n] defaults to subscripts from 0 to n-1. So the above program establishes memory locations labeled list[0], list[1], ... list[9]. The for loop reflects this in the range of the counter, k; i.e., k begins at 0 and continues while k is less than 10. Note that several possible variations are acceptable. For example,
int list[10]={0} // initializes list[0]=0, list[1]=0, list[2]=0, ..., list[9]=0
int list[]={10, 20, 30, 40}; // establishes array of size 4
C and C++ arrays do not routinely perform range checking so that changing the for loop to read
for (k=0; k<=10; k++) // goes too far
cout << list[k] << endl;
compiles and runs but produces absurd results for list[10] (6618680 in my attempt).
Before moving on, it's probably wise to discuss the connection between arrays and pointers. First, note that arrays are always passed by reference, even without adding the & to the formal parameter. For example,
void sort (int a[], int n);
int main()
{
int list[10];
...........
sort (list, 10);
......
return 0;
}
does not copy the actual parameter, 'list', to the corresponding formal parameter, 'a'. Instead, 'a' references the 'list' array. In this case, the array, 'list', in main() is returned from function 'sort' in sorted order. I recommend that you save the following code to try on your own.
//File: pointers.cpp (For variations
involving formatting of output, look at pointers2.cpp
and pointers3.cpp
#include <iostream.h>
#include <iomanip.h>
int main()
{
int list[4]={10, 20, 30, 40},
*p,
k;
p = list; //NOTE: list is a constant pointer to list[0]
for (k=0; k<4; k++)
{
cout << setw(5) << list[k] <<
endl; //NOTE: setw(k) sets the field width to k columns
cout << setw(5) << *(p+k) <<
endl; //
This stream manipulator
is defined in the iomanip.h header file
cout << setw(5) << p[k] <<
'\n\n";
}
return 0;
}
Note that the identifier 'list' in the above program is a constant pointer to list[0]. So making the assignment p=list makes p point to list[0]. This initializes the pointer p so that, in the loop, the pointer p is advanced to point to successive elements of the array 'list'. Note that the connection between pointers and arrays is so close that the notations *(p+k) and p[k] are synonymous! By the way, if you want to see how to format double's check double.cpp.
Is it clear why the following assignment is illegal?
int list[4]={10, 20, 30, 40},
otherlist[4];otherlist = list; <------------- WHY IS THIS ILLEGAL?
.....
That assignment is illegal because otherlist is a constant pointer. It cannot be the left hand side of an assignment statement.
Finally, to conclude our discussion of the pointer-array connection, note that the prototype of the sort function given above has two equivalent forms:
void sort (int a[], int n);
void sort (int *p, int n);
Of course, your choice of forms will determine the appropriate notation in each implementation.