CS 225 Notes 4

Introduction

We will continue  looking in detail at a C++ program by looking at a specific example program. This program includes several ways to manipulate strings. We will focus on control structures and function definition and use.
 

Structures

But first, a side trip into another data type in C++. This will lead us eventually into classes.
We have already seen how to collect a bunch of data that is all the same type into arrays. But we can also collect data of different types together into a single unit. These are called structures. They are similar to Pascal records. The syntax for a structure is

struct foo {
   int foo_id;
   char foo_name[32];
   float foo_weight;
};

This is the declaration of the structure. It tells the compiler what the parts are and thus how big the structure is. In this case, the size of the structure is the sum of the sizes of an int, a 32 element array of characters and a float. Once you have declared a struct, you can use it anywhere (mostly) you can use other data types.
For example,

struct foo a; // a single structure called a
struct foo arr[10]; // an array of 10 structures
struct foo * foo_ptr; // a pointer to a structure

The way you get at the pieces in a struct depend on whether you have an actual variable or a pointer.
So, if we have

struct foo b, *foo_ptr;
foo_ptr = &b;  // & gets the address of the variable

We can set the value of foo_id by either

b.foo_id=8;
foo_ptr->foo_id = 8;

Arrays work the same way as with other data types.

struct foo foo_arr[10];
foo_arr[0].foo_id = 4;
foo_ptr = foo_arr;  // notice no ampersand

foo_ptr-> foo_id = 4;

To change the next one, we can either do arithmetic on the foo_ptr
foo_ptr++;
foo_ptr->foo_id=6;
or
(foo_ptr+1)->foo_id=6;

The second way doesn't actually change the pointer. Pointers to arrays of structures work the same way as they do when working with arrays of characters and anything else.
They type of foo_ptr->foo_id is integer so it can be used anywhere an integer can be used. Specifically,
cout << foo_ptr -> foo_id << endl;
prints the foo_id as an integer.

 There are several kinds of control structures in C++. There are the IF, WHILE, DO and FOR loops. There is also the conditional expression.

If statements

We have already seen an if statement. The general form is
if(expression)
   statement;
else
   statement;
There are lots of examples starting on page 71. First let's look at the expression.

C++ expressions

In control structures, an expression is anything that evaluates to either true or false. As we have seen, there are two definitions of truth and false. The first and older one is that 0 (zero) is false and any non-zero integer is true. The other one is the use of bool variables which have the values true or false. The integer definition is more flexible and is used in many ways. So we will look at that in more detail. We have seen that the assignment operator has a value. If you have the expression, a=b, then the value of the expression is b. In an if statement,
if(a=b) cout << "true";
will print true if the value of the expression is true. Since the value of a=b is the value of b, this expression is true if b is non-zero. The fact about assignment is used often in C++ to set a value and check it at the same time. A simple example is to save the value of a function call and check the value. If we have a function the gives us the number of users on the system at the current time, we can save the value and do something special.
if(  (a=user_count()) == 1) cout << " I'm all alone" << endl;

The expression part calls user_count() and copies the value to a. Since the value of the assignment is the right hand side, we then check the value returned by user_count() with 1 and if it is 1, we print the message.

There are a number of comparison operators in C++
 
 
 

Operator Meaning
= assignment
== comparison
< less than
> greater than
<= less than or equal to
>= greater than or equal to
!= not equal

These all assume that the values being compared are integers or floats or can be treated as a number. There are also a number of logical operators. See page 58.
 
 
 

Operator Meaning
&& and
|| (2 vertical bar characters) or
! (exclamation point)  not

These can be combined in many ways.
int a, b,c;
if ( (a < 6) && (b> 7) ) cout << "case 1 " << endl;
if ( (a < 6) || (b> 7) ) cout << "case 2 " << endl;
if (  ( (a < 6) && (b> 7 )  || (  (c -b < a) && !c  ) ) cout << "case 3 " << endl;

It is important to remember that in these cases, we use the fact that zero is false and anything else is true. Typically the value of a comparison operator is either 0 or 1.

Also be careful, there is a big difference between && and &. The single ampersand means do a bit wise logical and. See page 63.
 

While loops

We have seen several while loops already. See page 85. The structure looks like
while(expression) statement;

The statement part can be one or more actual statements. So, if there is one statement, it looks like

while (a < b) cout << a << endl;

If there are several statements

while( a<b) {
    cout << a << endl;
    a += 3;
} // end while

The evaluation of the expression is doen at the top of the loop, so if the expression is false, it won't run the loop even once.
 

Do loops

These are much like while loops, only the evaluation is done at the end. See page 95. The general form is
do
   statement
while (expression);

The statement is done at least once since we don't check until the bottom of the loop.

For loops

For loops are for running a loop a fixed number of times. See page 96. The form is
for(expr; expr2; expr3)
   statement

The first expression is the initialization. Examples include i=0, int i=6.
The second expression is the test expression. If it is true, then we do this time through the loop.
The third expression is the increment. It is commonly i++.
For example,
for(int i=0; i < 10; i++)  cout << i << endl;
This starts by creating an i variable and setting it to 0. Since 0 < 10, we run the body of the loop and 0 is printed. Then we do the increment and i becomes 1. We check again and 1 is < 10 so we print 1. and so on. After we print 9, i is incremented to 10. 10 is not less then 10 so we don't do the body of the loop.
So this prints 0-9.
This loop is equivalent to the while loop
int i = 0;
while (i < 10) {
   cout << i << endl;
   i++;
} // endwhile

You can leave off parts of the for loop. For example, if we already have a variable counter used for something and now we want
to use it a  loop variable, we can skip the initialization.

for( ; counter < 20; counter++)

We could also leave off the increment is we were doing different increments

for (; counter < 20;) {
   if (counter  == 15)
      counter *= 2;
   else
      counter++;
} // end
 

Infinite loops

Sometimes you want a loop that runs forever. This is done differently for different kinds of loops.
for(;;) { cout << "forever" << endl;}
while(true) { cout << "forever" << endl;}
do { cout << "forever" << endl;| while(true);

Getting out of a loop

Now that your stuck in a loop, you can get out a couple of ways. The best way is to do a break. So in a forever loop

while(true) {
   if( X < 25) break;
} // endwhile

This will stop if X >= 25.
This works on the other loops as well.

The continue  will go back to the top of the loop. in a while or do, this cause the expression to be evaluated. In a for loop it causes the increment to be done.