CIT020 Index > Lecture Notes - Chapter 2 (continued)

Chapter 2 (continued)

while vs. do

The main difference between a while and a do is that the while does the test before entering the loop. Thus, if the condition is false, the body of the loop will never been executed. The do, on the other hand, always executes the loop body at least once, because the test is at the end of the loop.

This is the main reason that programmers prefer while over do; it ensures that the program will do nothing gracefully if given incorrect input.

break and continue

In this class, you will never use break in a loop. That’s because you want your loops to have one entry point and one exit point. The more places you have to leave a loop, the more places there are for bugs to creep in. Similarly, you will not use continue inside of a loop; a well-placed if makes the overall code easier to read. Here is the loop on page 51, rewritten to those standards. Notice how much more compact and readable it becomes.

int count = 0;
while (count < 10)
{
    count += 1;
    if (count != 5)
    {
        cout << count << endl;
    }
}

Score Rater Program Revised

We will revise the program on pages 41 and 42 to ask for a player’s score and then give a rating based on that score.

ScoreRating
0Extremely poor
1-400Poor
401-800Good
801-1000Very Good

The first thing we’re going to do is make a plan for what the program should do. We need to specify the program’s input (what do we need from the user), its output (what should the user see on the screen), and the processing (how the program does its thing).

Input Variables
score (an integer)
POOR_SCORE (400)
GOOD_SCORE (800)
VERY_GOOD_SCORE (1000)
Output Variables
There are none for this program; it only outputs messages
Processing
  1. Ask user for the score.
  2. If score equals zero, output “Extremely poor.”
  3. If score is greater than zero and less than or equal to POOR_SCORE, output “Poor.”
  4. If score is greater than POOR_SCORE and less than or equal to GOOD_SCORE, output “Good.”
  5. If score is greater than GOOD_SCORE and less than or equal to VERY_GOOD_SCORE, output “Very Good.”

Notice that constants are considered to be input variables. Even though we don’t ask the user for them, they aren’t output variables and they aren’t the result of some other calculation.

Compound Conditions

The if conditions we use have more than one test. We want to see if the score is greater than zero and also less than or equal to POOR_SCORE. We represent the and condition with the && operation. In an and condition, both parts must be true for the entire condition to be true.

if (age >= 18 && age < 21)
{
   cout << "You can vote, but you cannot drink." << endl;
}

You can represent an or condition with the || operator. (It’s the symbol on the upper half of the backslash key.) In an or condition, the whole condition is true if either part of it is true.

if (age < 0 || age > 180)
{
   cout << "I think you entered your age wrong." << endl;
}

Given this information, we can translate our plan directly to C++. The line numbers at the left are for reference only; you don’t type them into your file.

1   int score = 0;
2   const int POOR_SCORE = 400;
3   const int GOOD_SCORE = 800;
4   const int VERY_GOOD_SCORE = 1000;
5   
6   cout << "Enter the score to rate: ";
7   cin >> score;
8   
9   if (score == 0)
10  {
11      cout << "Your score is extremely poor." << endl;
12  }
13  
14  if (score > 0 && score <= POOR_SCORE)
15  {
16      cout << "That is a poor score." << endl;
17  }
18  
19  if (score > POOR_SCORE && score <= GOOD_SCORE)
20  {
21      cout << "That is a good score." << endl;
22  }
23  
24  if (score > GOOD_SCORE && score <= VERY_GOOD_SCORE)
25  {
26      cout << "That is a very good score." << endl;
27  }
Lines 2-4
We define the limits for score ranges as constants. That way, if the limits change, we can do all our modifications in one place rather than having to plow through the entire program looking for the numbers.
Lines 9-11
Even though there’s only one statement as a consequence of the if, we still enclose it in braces. Even when there’s only one statement as a consequence of an else, we still enclose it in braces. There is only one exception to this rule. You do this for two reasons. First, when you modify your program and add more statements, you won’t have to add the braces. Second, if you always uses braces, you will never have the problem of pairing an else clause with an if statement as described on pages 42 and 43.
Line 14
We could say if (score && score <= POOR_SCORE) and depend on the fact that a non-zero value for score is true, but that would also let negative numbers go through! Whenever you are comparing a number to zero, say it explicitly.

Nested if Statements

The program works, which is good. If a program doesn’t work, nothing else matters. (Although entering scores less than zero or greater than 1000 will give you unusual results. Try it and find out.)

There’s a slight inefficiency here, though. We’re asking too many questions. Look at the following dialogue:

Joe:
“Are you under 18?”
Fred:
“No, I'm not.”
Joe:
“Are 18 or over and less than 21 years old?”
Fred:
“Didn’t you hear me? I already told you I wasn’t under 18, so that would make me at least 18, right?”
Joe:
“Ummmmm, yeah.”

Joe is asking for information he already has. Now let’s do the dialogue as you would ordinarily hear it:

Joe:
“Are you under 18?”
Fred:
“No, I'm not.”
Joe:
“Well, then, are you less than 21 years old?”
Fred:
“Yes.”
Joe:
“OK, then you can vote but you can’t drink.”

Similarly, the preceding code is asking too many questions. If we know that the score is not less than or equal to POOR_SCORE, then we certainly don’t need to ask if it’s greater than POOR_SCORE; we already know that. We can avoid asking redundant questions by nesting if statements inside one another. Here it is in English:

And here it is in C++

int score = 0;
const int POOR_SCORE = 400;
const int GOOD_SCORE = 800;
const int VERY_GOOD_SCORE = 1000;

cout << "Enter the score to rate: ";
cin >> score;

if (score == 0)
{
    cout << "Your score is extremely poor." << endl;
}
else
{
    if (score <= POOR_SCORE)
    {
        cout << "That is a poor score." << endl;
    }
    else
    {
        if (score <= GOOD_SCORE)
        {
            cout << "That is a good score." << endl;
        }
        else
        {
            if (score <= VERY_GOOD_SCORE)
            {
                cout << "That is a very good score." << endl;
            }
        }
    }
}

else-if

Again, the code works fine, but, as you see the code marches off to the right edge of the screen, because we have indented every time a new block is opened. Remember how I said earlier that you must always open a new block and indent when you get an if or else? Here is the exception:

When the consequence of an else clause is another if statement, you may put the else and if on the same line, and you do not need braces around the if.

If we follow this exception, the code becomes much easier to read:

if (score == 0)
{
    cout << "Your score is extremely poor." << endl;
}
else if (score <= POOR_SCORE)
{
    cout << "That is a poor score." << endl;
}
else if (score <= GOOD_SCORE)
{
    cout << "That is a good score." << endl;
}
else if (score <= VERY_GOOD_SCORE)
{
    cout << "That is a very good score." << endl;
}

Random Number Within a Range

On page 61, the book tells you how to generate a random number in the range 1 to 6. In general, if you want to generate a random number in the range low to high, use the following formula. The more mathematically inclined among you may wish to figure out how I derived this formula. The rest of you–trust me. I know what I’m doing.

randomNumber = low + (rand() % (high - low + 1));

Thus, to generate a random number between 18 and 65 (for a character’s age, for example), you would say:

int age = 0;
const int LOW_AGE = 18;
const int HIGH_AGE = 65;
srand( time( 0 ) );
age = LOW_AGE + (rand() % (HIGH_AGE - LOW_AGE + 1));