Chapter 5

Directing the Application Flow

IN THIS CHAPTER

check Comparing numbers and evaluating other conditions

check Doing things based on a comparison

check Repeating code in specific ways

check Creating nested loops (loops within loops)

As you program in C++, many times you need to present the computer with a choice, allowing it to do one thing in one situation and something else in another situation. For example, you may have an application that asks for a user’s password. If the password is correct, the application continues; but if the password is incorrect, the application asks the user to reenter the password. After some number of times — usually three — the application performs yet another task when the user enters the incorrect password. Such situations are called conditions. In the case of the password, the condition is whether the password is correct.

You may also encounter situations in which you want several lines of code to run over and over. These are loops, and you can specify conditions under which the loop runs. For example, you may want to check the password only three times; and if the user fails to enter it correctly the third time, you may bar access to the system. This is a loop, and the loop runs under the condition that a counter has not exceeded the value of 3.

In this chapter, you consider different ways to evaluate conditions within your applications and cause different sections of code to run based on those conditions. The chapter helps you understand how you can use C++ commands called if statements, which are similar to what-if situations in real life. You also see how to use other C++ statements (such as do-while) to perform loops (repeating the same application sections a number of times).

To make the explanations clear, this chapter gives you real-world examples that you can feel free to incorporate into your life. The examples usually refer to groups of friends and how you can get money from them. So, you see, the benefits of this chapter are twofold: You find out how to program by using conditions and loops, and you find out how to make money off your unsuspecting friends.

Remember You don’t have to type the source code for this chapter manually. In fact, using the downloadable source is a lot easier. You can find the source for this chapter in the \CPP_AIO4\BookI\Chapter05 folder of the downloadable source. See the Introduction for details on how to find these source files.

Doing This or Doing That

As you go through life, you’re always faced with decisions. For example, when you bought this book, you faced the following decision: Should I buy this great For Dummies book that’s sure to tell me just what I need to know, or should I buy some other book?

When you’re faced with a decision, you usually have options that offer different results — say, Plan A and Plan B. Making a decision requires making a choice that results in the execution of either Plan A or Plan B. For example, if you approach a stoplight that has just turned yellow, you must either slam on the brakes or floor the accelerator. If you slam on the brakes, the car will stop just in time (you hope). If you floor the accelerator, the car will speed up and you’ll go sailing through the intersection just before the stoplight turns red. The choice is this: Press the brake, or press the accelerator. The plan looks like this:

  • If I press the brake, I will stop just in time.
  • If I press the accelerator, I will speed through the intersection.

Computers are faced with making decisions too, although their decisions are usually a little less exciting and don’t usually yield the possibility of police interaction. Computer decisions are also usually simpler in nature. That is, a computer’s decisions mostly focus around such issues as comparing numbers and strings of characters. For example, you may be writing a computer application for a bank. The user of your application (that is, the bank customer) has a choice of Plan A, Make a Deposit, or Plan B, Receive a Cash Withdrawal when interacting with an account. If the user chooses to make a deposit, your application adds to the account balance the amount of the deposit. If the user chooses to make a withdrawal, your application instead subtracts the withdrawal amount from the account balance.

In C++, decisions usually take the form of an if statement, which is code that starts with the if keyword followed by a condition, which is often a numerical condition wherein two numbers are compared and then two blocks of code appear: one that runs if the condition is satisfied and one that runs if it is not.

Evaluating Conditions in C++

Most decisions that the computer makes are based on conditions evaluated by comparing either two numbers or two characters. For numerical comparisons, you may compare a variable to a number, as in the following statement:

x > 10

This comparison evaluates whether the variable x holds a value greater than the number 10. If x is indeed greater than 10, the computer sees this condition as true. If x is not greater than 10, the computer sees the condition as not true (false).

Developers often use the word satisfied with conditions. For the condition x > 10, if x is greater than 10, developers say the condition is satisfied. It’s kind of like, “We’re satisfied if our IRS tax refund is five figures.” For this, if the condition is x > 9999, and you receive a $10,000 refund, the condition is satisfied.

For character comparisons, you may compare whether two characters are equal, as in the following statement:

mychar == 'A'

This comparison evaluates whether mychar contains the letter A. Notice that you use two equals signs, not just one. Using a single equals sign would assign the value A to mychar.

To test whether the character is not equal to something, you use the somewhat cryptic-looking != operator. Think of the ! as meaning not, as in

mychar != 'X'

Finding the right C++ operators

Each statement in the previous section uses an operator to specify the comparison to make between the numbers or the strings. Table 5-1 shows you the types of operators available in C++ and the comparisons that they help you make in your applications.

TABLE 5-1 Evaluating Numerical Conditions

Operator

What It Means

<

Less than

<=

Less than or equal to

>

Greater than

>=

Greater than or equal to

==

Equal to

!=

Not equal to

Some operators in this table — and how you use them — can be a bit annoying or downright frightening. The following list gives examples:

  • The operator that tests for equality is two equals signs. It looks like this:

    x == 10

    When the computer finds this statement, it checks to see whether x equals 10.

    Warning If you put just one equals sign in your statements, most C++ compilers will not give you an error — though a statement like x = 10 is not really a condition! Instead, x = 10 is an assignment, setting the variable x to 10. When code contains such a statement, the result of the evaluation is always the same, regardless of the value that x has.

  • The operator that tests for inequality is an exclamation mark followed by an equals sign. For the condition x != 10, the condition evaluates as true only if x is not equal to 10 (x is equal to something other than 10).
  • When you’re testing for greater-than or less-than conditions, the condition x > 10 is not true if the value of x is equal to 10. The condition x > 10 is true only if x is actually greater than, but not equal to, 10. To also test for x being equal to 10, you have two choices:

    • If you’re working with integers, you can test whether x > 9. In that case, the condition is true if x equals 10, or 11, or 12, and so on.
    • You can use the greater-than-or-equal-to operator to determine equality x >= 10. This condition also is true if x equals 10, 11, and so on.

    Remember To test for all whole numbers greater than or equal to 10, the condition x > 9 works only if you’re working with integers. If you’re working with floating-point numbers (refer to Book 1, Chapter 4, for information on the types of numbers you can work with in C++), the statement x > 9 won’t work the way you want. The number 9.1 is greater than 9, and it’s not greater than or equal to 10. So if you want greater than or equal to and you’re not working with integers, use the >= operator.

Combining multiple evaluations

When you make evaluations for application decisions, you may have more than one condition to evaluate. For example, you might say, “If I get a million dollars, or if I decide to go into debt up to my eyeballs, I will buy that Lamborghini.” In this case, you would buy the car under two conditions, and either can be true. Combining conditions like this is called an or situation: If this is true or if that is true, something happens.

To evaluate two conditions together in C++, you write them in the same statement and separate them with the or symbol (||), which looks like two vertical bars. Other programming languages get to use the actual word or, but C++ uses the strange, unpronounceable symbol that you might call The Operator Previously Known As Or. The following statement shows it performing live:

(i < 10 || i > 100)

Warning This condition is useful for some kinds of range checking for which you want to exclude the middle of a range and check only for the extremes. In this case, an i value of 50 (the middle of the range) would evaluate to false. If you use the or operator (||), accidentally ending up with a condition that is always true is easy. For example, the condition (x < 100 || x > 0) is always going to be true. When x is -50, it’s less than 100, so the condition is true. When x is 500, it’s greater than 0, so it’s true.

In addition to an or condition, you can have something like this: “If I get a million dollars and I feel really bold, I will buy a Lamborghini.” Notice that this uses the word and. In this case, you do it only if both situations are true. (Remember that with or, you do it if either situation is true.) In C++, the and operator is two ampersands: &&. This makes more sense than the or operator because the & symbol is often associated with the word and. The and comparison in C++ looks like this:

(i > 10 && i < 100)

This example checks to see whether a number is more than 10 and less than 100. That would mean the number is in the range 11 through 99.

Combining conditions by using the && and || operators is a use of logical operators.

Tip To determine whether a number is within a certain range, you can use the and operator (&&), as you see earlier in this chapter.

Warning With the and operator, accidentally creating a condition that is never true is easy. For example, the condition (x < 10 && x > 100) will never be true. No single number can be both less than 10 and simultaneously greater than 100.

Including Evaluations in C++ Conditional Statements

Computers, like humans, evaluate conditions and use the results of the evaluations as input for making a decision. For humans, the decision usually involves alternative plans of action, and the same is true for computers. The computer needs to know what to do if a condition is true and what to do if a condition is not true. To decide on a plan of action based on a condition that your application evaluates, you use an if statement, which looks like this:

if (x > 10)
{
cout << "Yuppers, it's greater than 10!" << endl;
}

This example translates into English as: If x is greater than 10, write the message

"Yuppers, it's greater than 10!"

In an if statement, the part inside the parentheses is called either the test or the condition. You usually apply condition to this part of the if statement and use the word test as a verb, as in “I will test whether x is greater than 10.”

Remember In C++, the condition for an if statement always goes inside parentheses. If you forget the parentheses, you get a compile error.

You can also have multiple plans of action. The idea is simply that if a condition is true, you will do Plan A. Otherwise, you will do Plan B. This is an if-else block, which appears in the next section.

Deciding what if and also what else

When you write code for a comparison, usually you want to tell the computer to do something if the condition is true and to do something else if the condition is not true. For example, you may say, “If I’m really hungry, I will buy the Biggiesupersizemondohungryperson french fries with my meal for an extra nickel; otherwise, I’ll go with the small.” In the English language, you often see this kind of logic with the word otherwise: If such-and-such is true, I will do this; otherwise, I will do that.

In C++, you use the else keyword for the otherwise situation. The IfElse example demonstrates how to use the else keyword, as shown in the following code:

#include <iostream>

using namespace std;

int main()
{
int i;
cout << "Type any number: ";
cin >> i;

if (i > 10)
{
cout << "It's greater than 10." << endl;
}
else
{
cout << "It's not greater than 10." << endl;
}

return 0;
}

In this code, you test whether a number is greater than 10. If it is, you print one message. If it is not, you print a different message. Notice how the two blocks of code are distinct. The first block immediately follows the if statement; it’s the code that runs if the condition is true. The next block is preceded by the else keyword, and this block runs if the condition is false.

Warning Think carefully about your else code block when dealing with numbers. If you are testing whether a number is greater than 10, for instance, and it turns out that the number is not greater than 10, the tendency of most people is to assume that it must, therefore, be less than 10. But that’s not true. The number 10 itself is not greater than 10, but it’s not less than 10, either. So the opposite of greater than 10 is simply not greater than 10. If you need to test the full range of numbers using a simple if statement, create an if statement that uses either >= or <= (refer to Table 5-1 for a listing of operators).

Going further with the else and if

When you are working with comparisons, you often have multiple comparisons going on. For example, you may say, “If I go to Mars, I will look for a cool red rock; otherwise, if I go to the moon, I will jump up really high; otherwise, I will just look around wherever I end up, but I hope there will be air.”

The IfElse2 example, shown in the following code, demonstrates how to combine the if and else keywords to check for multiple alternatives:

#include <iostream>

using namespace std;

int main()
{
int i;
cout << "Type any number: ";
cin >> i;

if (i > 10)
{
cout << "It's greater than 10." << endl;
}
else if (i == 10)
{
cout << "It's equal to 10" << endl;
}
else
{
cout << "It's less than 10." << endl;
}

return 0;
}

Here you can see having several different conditions, and only one can be true. The computer first checks to see whether i is greater than 10. If i is greater, the computer prints a message saying that i is greater than 10; but if it isn’t greater, the computer checks to see whether i equals 10. If so, the computer prints a message saying that i is equal to 10. Finally, the computer assumes that i must be less than 10, and it prints a message accordingly. Notice there is no condition for the final else statement (you can’t have a condition with else statements). But because the other conditions failed, you know, by your careful logic, that i must be less than 10.

Be careful when you are thinking through such if statements. You could have a situation where more than one condition can occur. For example, you may have something like the example shown in IfElse3:

#include <iostream>

using namespace std;

int main()
{
int i;
cout << "Type any number: ";
cin >> i;

if (i > 100)
{
cout << "It's greater than 100." << endl;
}
else if (i > 10)
{
cout << "It's greater than 10" << endl;
}
else
{
cout <<
"It's neither greater than 100 nor greater than 10."
<< endl;
}

return 0;
}

Think about what would happen if i is the number 150. The first condition, i > 100, is true. But so is the second condition, i > 10. The number 150 is greater than 100, and 150 is also greater than 10. So which block will the computer execute? Or will it execute both blocks?

The computer executes only the first condition that is satisfied. Thus, when i is 150, the computer prints the message "It’s greater than 100." It doesn’t print the other messages. In fact, the computer doesn’t even bother checking the other conditions at that point. It just continues with the application.

Repeating Actions with Statements That Loop

You see loops all the time. A child runs around in circles until getting quite dizzy and falling over (laughing, in all likelihood). While driving, you see a roundabout and navigate it successfully or go around for another try. During exercise, you perform a given number of repetitions to obtain a desired fitness result. All these examples reflect real-life loops. Computers also deal with loops, as defined in the following sections.

Understanding how computers use loops

Suppose that you’re writing an application to add all the numbers from 1 to 100. For example, you may want to know how much money you will get if you tell 100 people, “Give me one dollar more than the person to your left.” With a mastery of copy-and-paste, you could do something like this (with the first person giving you a dollar, the second giving you two dollars, the third giving you three dollars, and so on):

int x = 1; // First person.
x = x + 2; // Person two gives you 2, for a total of 3
x = x + 3; // Person three gives you 3, for a total of 6
x = x + 4; // Person four gives you 4, for a total of 10

and so on until you get to x = x + 100. As you can see, this code could take a long time to type, and you would probably find it a tad frustrating, too, no matter how quickly you can choose the Edit  ⇒  Paste command (or press Ctrl+V). Fortunately, the great founders of the computer world recognized that not every programmer is a virtuoso at the piano with flying fingers and that applications often need to do the same thing over and over. Thus, they created a helpful tool: the for loop. A for loop executes the same piece of code repeatedly a certain number of times. And that’s just what you want to do in this example.

Looping situations

Several types of loops are available, and in this section you see how they work. Which type of loop you use depends on the situation. The preceding section methods one loop type: the for loop. The idea behind a for loop is to have a counter variable that either increases or decreases, and the loop runs as long as the counter variable satisfies a particular condition. For example, the counter variable might start at 0, and the loop runs as long as the counter is less than 10. The counter variable increments (has one added to it) each time the loop runs, and after the counter variable is not less than 10, the loop stops.

Another way to loop is to simplify the logic a bit and say, “I want this loop to run as long as a certain condition is true.” This is a while loop, and you simply specify a condition under which the loop continues to run. When the condition is true, the loop keeps running. After the condition is no longer true, the loop stops.

Finally, there’s a slight modification to the while loop: the do-while loop. The do-while loop is used to handle one particular situation that can arise. When you have a while loop, if the condition is not true when everything starts, the computer skips over the code in the while loop and does not even bother executing it. But sometimes you may have a situation in which you would want the code to always execute at least once. In that case, you can use a do-while loop.

Table 5-2 shows the types of loops. As the chapter progresses, you see examples of using all three loop types.

TABLE 5-2 Choosing Your Loops

Type of Loop

Appearance

for

for (x=0; x<10; x++) { }

while

while (x < 10) { }

do-while

do { } while (x < 10)

You may want to use these loops in these situations:

  • for loop: Use a for loop when you have a counter variable and you want it to loop while the counter variable increases or decreases over a range. It’s a good choice if you know how many times you want the loop to execute.
  • while loop: Use the while loop when you have a condition under which you want your code to run. It’s a good choice when you want to perform the test at the beginning of the loop. The test may fail immediately, so the loop may not execute even once.
  • do-while loop: Use the do-while loop when you have a condition under which you want your code to run and you want to ensure that the loop always runs at least once, even if the condition is not satisfied. It’s a good choice when the code inside the loop prepares the variables that the test uses, so the loop must execute at least once.

Looping for

Using the for loop provides precise control over how many times the code performs a task. In addition, it’s extremely flexible because you also have control over how the counter variable updates. While you can use a for loop for situations when you don’t know how many times you need to perform a task, such as streaming content from the Internet, it still provides the basis for code that is less susceptible to errors because you always know precisely how long the loop will continue. With this in mind, the following sections tell you more about the for loop.

Performing a simple for loop

To use a for loop, you use the for keyword and follow it with a set of parentheses that contains information regarding the number of times the for loop executes.

For example, when adding the numbers from 1 to 100, you want a variable that starts with the number 1; then you add 1 to x, increase the variable to 2, and add the next number to x again over and over. The common action here that doesn’t change each time is the “add it to x” part, and the part that changes is the variable, called a counter variable.

The counter variable, therefore, starts at 1 and goes through 100. Does it include 100? Yes. And with each iteration, you add 1 to the counter variable. The for statement looks like this:

for (i = 1; i <= 100; i++)

This statement means that the counter variable, i, starts at 1, and the loop runs over and over while i is less than or equal to 100. After each iteration, the counter variable increments by 1 because of the i++ statement.

The following list describes the three portions inside the parentheses of the for loop:

  • Initializer: You use this first portion to set up the counter variable.
  • Condition: It’s the condition under which the loop continues to run.
  • Finalizer: In this third portion, you specify what happens after each cycle of the loop.

Remember Three items are inside the for loop, and you separate them with semicolons. If you try to use commas, your code will not compile.

Now the line of code from a few paragraphs back doesn’t do anything for each iteration other than add 1 to i. To tell the computer the work to do with each iteration, follow the for statement with a set of braces containing the statements you want to execute with each iteration. Thus, to add the counter variable to x, you would do this:

for (i = 1; i <=100; i++)
{
x += i;
}

Note that if the for loop only executes one statement, you don’t have to include the braces. This example would add i to x with each loop. Of course, you must create x and assign an initial value to it to make the loop work. The ForLoop example demonstrates the for loop in its final form, complete with the way to write the final value of x to the console after the loop is finished:

#include <iostream>

using namespace std;

int main()
{
int x = 0;
int i;

for (i = 1; i <= 100; i++)
{
x += i;
}

cout << x << endl;
return 0;
}

When you run this example, you see an output of 5050. Notice a few things about this block of code.

  1. You declare both variables that you’re working with: x and i.
  2. The for statement initializes the counter variable, specifies the condition under which it continues running, and tells what to do after each iteration. In this example, the for loop starts with i = 1, and it runs as long as i is less than or equal to 100. For each iteration, the computer adds the value of i to x; the process that adds the value to x is the code inside the braces.
  3. The computer adds 1 to i, which you specify as the third item inside the parentheses. The computer does this part, adding 1 to i, only after it finishes executing the stuff inside the braces.

Meddling with the middle condition

The middle portion of the for statement specifies a condition under which to continue doing the stuff inside the for loop. It must eventually evaluate to false or the loop will continue forever. In the case of the preceding example, the condition is i <= 100, which means that the stuff inside the braces continues to run as long as i is less than or equal to 100.

In this example, you want the loop to iterate for the special case in which i is 100, which still satisfies the condition i <= 100. If you instead say i < 100, the loop won’t execute for the case in which i equals 100. The loop will stop short of the final iteration. In other words, the computer would add only the numbers 1 through 99. And if your friends are gathering money for you, you’d be cheated out of that final $100. And, by golly, that could make the difference as to whether you pay rent this month.

Warning The question of when the loop stops can get kind of confusing. If you go crazy and tell the compiler that you want to add the numbers 1 up to but not including 100, you need a condition such as i < 100. If you say up to 100, it’s not clear exactly which you want to do — include the 100 or not. If that’s the case and you’re writing the application for someone else, you would want to ask for clarification. (Unless you’re the 100th friend, in which case you may get out of paying your dues.)

In the example you’ve been using, the condition i <= 100 and the condition i < 101 have essentially the same meaning. If the condition is i < 101, the application operates the same. But that’s true only because the example uses integers to count up to and including 100. If you instead add floating-point numbers, and increment the counter by 0.1 after each iteration, these two conditions (i <= 100 and i < 101) aren’t the same. With i <=100, i gets up to 99.5, 99.6, 99.7, 99.8, 99.9, and finally 100, after which the loop stops. But i < 101 would also include 100.1, 100.2, up to and including 100.9.

You can see that the two conditions are not the same by playing with the ForLoop2 example. When you run this example with a condition of i <= 100, the output is 50050. However, when you run this example with a condition of i < 101, the output is 51055.5. (Remember to rebuild the application after you make any changes to it.)

#include <iostream>

using namespace std;

int main()
{
double x = 0.0;

for (double i = 0.1; i <= 100; i += 0.1)
{
x += i;
}

cout << x << endl;
return 0;
}

Now notice the third item in the for statement: i+=0.1. Remember that this item is the same as i = i + 0.1. Therefore, this third item is a complete statement. A common mistake is to instead include just a partial statement, as in i + 0.1. Unfortunately, some compilers allow a partial statement to get through with only a warning. C++ is notorious for letting you do things that don’t make a whole lot of sense, though newer compilers tend to fix these errors.

Yes, it’s true: The entire statement i = i + 1 is considered to have a side effect. In medicine, a side effect is an extra little goodie you get when you take a pill that the doctor prescribes. For example, to cure your headache with medicine, one side effect may be that you experience severe abdominal pains — not something you want. But in computers, a side effect can be something that you may want. In this case, you want the counter to be incremented. The partial statement i + 0.1 returns only a value and doesn’t put it anywhere; that is, the partial statement doesn’t change the value of i — it has no side effects.

If you try this at home by replacing one of the for loops in the earlier examples with just i + 0.1, your loop runs forever until you manually stop the application. The reason for this action is that the counter always stays put, right where it started, and it never increments. Thus, the condition i <= 100 is always satisfied.

Remember The final portion of the for statement must be a complete statement in itself. If the statement simply evaluates to something, it will not be used in your for loop. In that case, your for loop can run forever unless you stop it.

Going backward

If you need to count backward, you can do that with a for loop as well. For example, you may be counting down the number of days remaining before you get to quit your job because you learned C++ programming and you are moving on to an awesome new job. Or you may be writing an application that can manipulate that cool countdown timer that they show when the space shuttle launches. Counting up just isn’t always the right action. It would be a bummer if every day were one day more before you get to quit your job and move to an island. Sometimes, counting backward is best.

To count backward, you set up the three portions of the for loop. The first is the initial setup, the second is the condition under which it continues to run, and the third is the action after each iteration. For the first portion, you set the counter to the starting value, the top number. For the condition, you check whether the number continues to be greater than or equal to the final number. And for the third portion, you decrement the counter (reduce its value by 1) rather than increment it. Thus, you would have this:

for (i=10; i>=5; i--)

This line starts the counter variable i at 10. (Note the lack of spaces between i, =, and 10—the compiler doesn’t care whether you use spaces or not, the spaces are there, or not, for you.) The for loop decrements i by 1 after each iteration, and thus i moves to 9, then 8, then 7, and so on. This process continues as long as i is at least 5. Thus, i counts 10, 9, 8, 7, 6, 5. The whole application might look like the ForCountdown example, shown here:

#include <iostream>

using namespace std;

int main()
{
for (int i=10; i>=5; i--)
{
cout << i << endl;
}

return 0;
}

When you run this code, you see the following output:

10
9
8
7
6
5

Using multiple initialization variables

If you need multiple counter variables, the for loop can handle it. Each portion of the for statement can have multiple items in it, separated by commas. For example, the following code uses two counter variables, as demonstrated in the ForLoopMultiVariable example:

#include <iostream>

using namespace std;

int main()
{
string A = "Hello";
string B = "1122334455";

for (int i = 0, j = 0; i < 5; i++, j += 2)
{
cout << A[i] << B[j] << endl;
}

return 0;
}

In this case, you work with two strings: A and B. String B is twice as long as string A, but you want to combine the two. So, you need to access the string index of B using j by incrementing it twice the amount of i. This type of processing can happen in C++, so it’s good to keep in mind the fact that using multiple variables in a for loop isn’t always bad. The output you see from this example looks like this:

H1
e2
l3
l4
o5

The problem with using multiple variables comes when you start to create really complex and convoluted code. Here is an example of when what is happening with the for loop becomes harder to understand:

for (int i = 0, j=10; i <= 5, j <=20; i++, j+=2)
{
cout << i << " " << j << endl;
x += i + j;
}

Look carefully at it because it’s a bit confusing (in fact, you learn a little something about the complexity shortly). To understand this example, look at each portion separately. The first portion starts the loop. Here, the code creates two counters — i and j; i starts at 0, and j starts at 10.

So far, easy enough. The second portion says that the loop will run as long as the following two conditions are true: i must be less than or equal to 5, and j must be less than or equal to 20.

Again, not too bad. The final portion says what must happen at the end of each iteration: i is incremented by 1, and j is incremented by 2.

Thus, you have two counter variables. And it’s not too bad, except that you might imagine doing something like this instead:

for (int i = 0, j=20; i <= 5, j >= 10 ; i++, j-=2)
{
cout << i << " " << j << endl;
x += i + j;
}

If you look carefully, you’ll notice that aside from i, j starts out at 20 and the loop runs as long as j is at least 10, and that with each iteration, 2 is subtracted from j. In other words, j is counting down by 2 from 20 to 10.

But i is counting up from 0 to 5. Thus, you have two loops: one counting up and one counting down.

Code can become extremely confusing—look at the following gem from the ForLoopComplex example:

#include <iostream>

using namespace std;

int main()
{
int x = 0;
for (int i=0, j=10; i<=5, j<=20;
i++, j+=2, cout << i+j << endl, x+=i+j)
{
}

return 0;
}

It’s hard to tell what it does just by looking at it. Running the code will give you an output of

13
16
19
22
25
28

The truth is, this kind of code is just too complicated — best to stick with simpler code. Although you may know what this code means, your coworkers will only get frustrated trying to decode it. And if you write code just for fun at home, six months from now — when you go back and look at this code — you might have trouble figuring it out yourself!

One thing to notice about this particular example is that the for conditions reside on two lines. At least the line isn’t so long that you need to scroll it within the editor. Using shorter code lines is usually helpful.

Tip Putting too much inside the for statement itself is easy to do. In fact, if you’re really clever, you can put almost everything inside the for loop and leave nothing but an empty pair of braces, as shown in the preceding example. But remember, just because your code is clever doesn’t mean that what you did was the best way to do it. Instead, sticking to the common practice of using only one variable in the for statement is a good idea (as is not using multiple statements within each portion).

Tip Keeping your applications clear so that other people can figure out what you were trying to do when you wrote the code is always a good idea. Some people seem to think that if they keep their applications complicated, they’re guaranteeing themselves job security. Oddly, all the people I know like that tend to leave their jobs and have trouble getting good references. (Imagine that!)

Technical stuff You may recall that with the ++, you can have both i++ and ++i. The first is a post-increment, and the second is a pre-increment. You may be tempted to try something like this: for (int i = 0; i <= 5; ++i). Although it looks cool and some people prefer it, the truth is that it doesn’t change anything. The ++i still takes place at the end of the loop, not at the beginning, as you might hope. Using pre-increment just makes code confusing; use i++ in your for loops and avoid ++i.

Working with ranges

A range is a series of values that go from one value to another value and include the values in between. For example, the range a through d is a, b, c, and d. An integer range of 1 through 5 is 1, 2, 3, 4, and 5. You see ranges in action multiple times in this book, but the main discussion appears in Book 5, Chapter 6. For now, this chapter works with an incredibly simple range.

To make this example work, you must configure GCC to use a minimum of C++ 17. Choose Settings  ⇒  Compiler to display the Compiler Settings dialog box shown in Figure 5-1. Select the Have G++ Follow the Coming C++ 1z (aka C++ 17) setting option; then click OK. If you don’t select this option, the example will fail to build properly. Remember that if you build a project using the wrong options, you must rebuild it by choosing Build  ⇒  Rebuild after setting the correct options.

Snapshot of configuring GCC to use the C++ 17 standard.

FIGURE 5-1: Configure GCC to use the C++ 17 standard.

Now that the compiler is configured, you can use the code that follows, which also appears in the ForLoopRange example, to test a for loop using a range. In this case, the range is from 1 through 5:

#include <iostream>

using namespace std;

int main()
{
int range[] = {1, 2, 3, 4, 5};

for (int i : range)
{
cout << i << endl;
}

return 0;
}

Don’t worry too much about what may appear to be confusing code; it all makes sense as you progress. The int range[] = {1, 2, 3, 4, 5}; line of code creates an array — a series of values within a single variable. Think of it as a box with partitions in which you can place a single value in each partition. Book 5, Chapter 1 tells you more about working with arrays.

Remember The for loop condition looks really strange. The condition looks like this: int i : range. The code creates an int value i that receives one value from the range for each iteration of the loop. The range (:) operator appears between the range declaration (i) and the range expression (range). This is a somewhat new feature of C++, and you’ll find it extremely useful for processing storage containers like arrays.

After i receives a value, the code outputs it to the screen using cout. What you see as output is the values 1 through 5 — each on a separate line. Of course, you might think this is all smoke and mirrors. So, try changing one of the values in the array and you see that the output changes to match the array content.

Placing a condition within the declaration

Sometimes you need to perform data manipulation within a for loop in a way that’s more convenient than trying to manipulate it in a code block. You can actually create a special kind of condition within a for loop declaration in which the condition does something like access a part of a string or array. The ForLoopCondition example demonstrates how to perform this task, as shown here:

#include <iostream>

using namespace std;

int main()
{
string hello = "Hello";
for (int i = 0; char c = hello[i]; i++)
{
cout << c << endl;
}
return 0;
}

Notice that the middle condition, which normally checks for a particular value or performs some other logical function, actually creates a new char variable, c, and places a letter from the hello string into it based on the value of i. After scratching your head for a while looking for the means of ending the loop, you determine that when the loop gets to the end of the string, it automatically ends.

Tip This is a handy way of working with all sorts of data when you don’t know how large the data is at the outset. The for loop continues processing the string until it runs out of letters, so you don’t have to worry about the string size.

Letting C++ determine the type

The previous section tells you about placing a condition within a for loop to manipulate data of uncertain size. The example assumes that the data is of a specific type, but you may not know the type. Starting with C++ 11 (which means that you must configure GCC with the Have G++ Follow the Combine C++ 1z (aka C++ 17) setting, as described in the “Working with ranges” section, earlier in this chapter), you can tell C++ to determine what type to use automatically. You do this using the auto keyword, as shown in the ForLoopCondition2 code here:

#include <iostream>

using namespace std;

int main()
{
string hello = "Hello";
int values[] = {1, 2, 3, 4, 5, 0};

for (int i = 0; auto c = hello[i]; i++)
{
cout << c << endl;
}

return 0;
}

As shown, the for loop will process the values in hello just as it did for the example in the previous section. However, this time you don’t specify that c is a char; you use auto instead. Now, try replacing hello with values in the for loop so that it looks like this:

for (int i = 0; auto c = values[i]; i++)
{
cout << c << endl;
}

Instead of outputting Hello one letter at a time, you now see the numbers 1 through 5, one on each line. So, the same for loop now works for data of two different types: string and int. Using this approach gives you additional flexibility at the cost of a little code readability.

Warning Notice that the for loop doesn’t output the 0 in the values array; rather, it uses the 0 to determine the ending point of the array. If you didn’t include this 0, the for loop would continue until it found a 0, which means you could see quite a bit of garbage onscreen.

Looping while

Often, you find that for loops work only so well. Sometimes, you don’t want a counter variable; you just want to run a loop over and over as long as a certain situation is true. Then, after that situation is no longer the case, you want to stop the loop.

For example, instead of saying that you’ll have 100 people line up and each one will give you one more dollar than the previous person, you may say that you will continue accepting money like this as long as people are willing to give it.

In this case, you can see that the condition under which the giving continues to operate is the statement “as long as they’re willing to give it.”

To do this in C++, you use a while statement. The while keyword is followed by a set of parentheses containing the condition under which the application is to continue running the loop. Whereas the general for statement’s parentheses include three portions that show how to change the counter variable, the while statement’s parentheses contain only a condition. The WhileLoop example demonstrates a simple while loop, as shown here:

#include <iostream>

using namespace std;

int main()
{
int i = 0;
while (i <= 5)
{
cout << i << endl;
i++;
}
cout << "All Finished!" << endl;
return 0;
}

This code runs while i is less than or equal to 5. Thus, the output of this application is

0
1
2
3
4
5
All Finished!

Remember Notice that you must declare i outside the while loop using int i = 0;. If you were to try to declare the while loop using while (int i <= 5), the compiler would complain.

The while loop is handy if you don’t have a particular number of times you need the loop to run. For example, consider a situation in which your application is reading data from the Internet. Unless you control the Internet data source, you don’t know how much data it can provide. (Many other situations can arise in which you don’t know how much data to read, but Internet applications commonly experience this problem.) Using a while loop, the code can continue reading data until your application has read it all. The Internet data source can simply stream the data to your application until the data transfer is complete.

Often, for this kind of situation, you create a Boolean variable called done and start it out as false. The while statement is simply

while (!done)

This line translates easily to English as “while not done, do the following.” Then, inside the while loop, when the situation happens that you know the loop must finish (such as the Internet data source has no more data to read), you set

done = true;

The WhileLoop2 example demonstrates how to do this sort of process, as shown here:

#include <iostream>

using namespace std;

int main()
{
int i = 0;
bool done = false;
while (!done)
{
cout << i << endl;
i++;
if (i > 5)
done = true;
}
cout << "All Finished!" << endl;
return 0;
}

In the case of the Internet data example, after you encounter no more data, you would set done to true. The variable used to control the loop condition must change or the loop will continue to run forever. In the case of your friends giving you money, after one of them refuses, you would set done to true.

Doing while

The while statement has a cousin in the family: the do-while statement. A loop of this form is similar to the while loop, but with an interesting little catch: The while statement goes at the end, which means the loop always executes at least one time. The DoWhileLoop example demonstrates how to use this kind of loop, as shown here:

#include <iostream>

using namespace std;

int main()
{
int i = 15;
do
{
cout << i << endl;
i++;
}
while (i <= 5);
cout << "All Finished!" << endl;
return 0;
}

Notice here that the loop starts with the do keyword, and then the material for the loop follows inside braces, and finally the while statement appears at the end. The idea is that you’re telling the computer “Do this while such-and-such is true,” where this is the stuff inside braces and the such-and-such is the condition inside parentheses. Because the condition is evaluated at the end, after everything else is done, the output from this example is a little different from the other while loop examples:

15
All Finished!

Warning If you had used a while loop here, the loop wouldn’t have executed at all because i is set to 15. However, because this is a do-while loop, you see the output of 15. Having the loop run at least once can be a problem sometimes, and if you don’t want that behavior, consider using a while loop instead of a do-while loop.

Breaking and continuing

Sometimes, you may write an application that includes a loop that does more than simply add numbers. You may find that you want the loop to end under a condition that’s separate from the condition in the loop declaration. Or you may want the loop to suddenly skip out of the current loop and continue with the next item in the loop when the item being processed is incorrect in some way. When you stop a loop and continue with the code after the loop, you use a break statement. When you quit the current cycle of the loop and continue with the next cycle, you use a continue statement. The next two sections show you how to do this.

Remember Even though the examples in the following sections rely on a for loop, the break and continue statements also work for while and do-while loops.

Breaking

Suppose that you are writing an application that reads data over the Internet, and the loop runs for the amount of data that’s supposed to come. But midway through the process, you may encounter some data that has an error in it, and you may want to get out of the for loop immediately.

C++ includes a handy little statement that can rescue you in such a situation. The statement is called break. Now, nothing actually breaks, and it seems a bit frightening to write an application that instructs the computer to break. But this use of the term break is more like in “break out of prison” than “break the computer.” But instead of breaking out of prison, it breaks you out of the loop.

The ForLoop3 example that follows demonstrates this technique. This sample checks for the special case of i equaling 5. You could accomplish the same result by changing the end condition of the for loop, but at least it shows you how the break statement works.

#include <iostream>

using namespace std;

int main()
{
for (int i=0; i<10; i++)
{
cout << i << " ";
if (i == 5)
{
break;
}
cout << i * 2 << endl;
}
cout << "All Finished!" << endl;
return 0;
}

In the preceding code, the first line inside the for loop, cout << i << " ";, runs when i is 5. But the final line in the for loop, cout << i * 2 << endl;, does not run when i is 5 because you tell it to break out of the loop between the two cout statements.

Also notice that when you break out of the loop, the application does not quit. It continues with the statements that follow the loop. In this case, it still prints the message "All Finished!"

Warning You can leave empty the second portion of the for statement (the condition) by simply putting a blank between the spaces. Then, to get out of the loop, you can use a break statement. However, doing this makes for messy code. You should treat messy code like you treat a messy house: Although sometimes not everyone minds it, the truth is that most people don’t care to see a messy house. And you really don’t want other people to see your messy house — or your messy code. Yes, as a programmer, being a little self-conscious is sometimes a good thing.

Continuing

In addition to the times when you may need to break out of a loop for a special situation, you can also cause the loop to end its current iteration; but instead of breaking out of it, the loop resumes with the next iteration.

For example, you may be, again, reading data from over the Internet, and doing this by looping a specified number of times. In the middle of the loop, you may encounter some bad data. But rather than quit out of the loop, you may want to simply ignore the current piece of bad data and then continue reading more data.

To do this trick, you use a C++ statement called continue. The continue statement says, “End the current iteration, but continue running the loop with the next iteration.”

The ForLoop4 example that follows shows a slightly modified version of the previous example, in the “Breaking” section. When the loop gets to 5, it doesn’t execute the second cout line. But rather than break out of the loop, it continues with 6, and then 7, and so on until the loop finishes on its own:

#include <iostream>

using namespace std;

int main()
{
int i;
for (i=0; i<10; i++)
{
cout << i << " ";
if (i == 5)
{
cout << endl;
continue;
}
cout << i * 2 << endl;
}
cout << "All Finished!" << endl;
return 0;
}

Nesting loops

Many times, you need to work with more than one loop. For example, you may have several groups of friends, and you want to bilk the individual friends of each group for all you can get. You may host a party for the first group of friends and make them each give you as much money as they have. Then, the next week, you may hold another party with a different group of friends. You would do this for each group of friends. You can draw out the logic like this:

For each group of friends,
for each person in that group
bilk the friend for all he or she is worth

This is a nested loop. But if you do this, don’t be surprised if this is the last time your friends visit your nest.

A nested loop is simply a loop inside a loop. Suppose that you want to multiply each of the numbers 1 through 10 by 1 and print the answer for each multiplication, and then you want to multiply each of the numbers 1 through 10 by 2 and print the answer for each multiplication, and so on, up to a multiplier of 10. Your C++ code would look like the ForLoop5 example:

#include <iostream>

using namespace std;

int main()
{
for (int x = 1; x <= 10; x++)
{
cout << "Products of " << x <<endl;
for (int y = 1; y <= 10; y++)
{
cout << x * y << endl;
}
cout << endl;
}
return 0;
}

In this example, you have a loop inside a loop. The inner loop can make use of x from the outer loop. Beyond that, nothing is magical or bizarre about this code. It’s just a loop inside a loop. And yes, you can have a loop inside a loop inside a loop inside a loop. You can also place any loop inside any other loop, like a while loop inside a for loop.

Notice you have a cout call before and after the inner loop. You can do this; your inner loop need not be the only thing inside the outer loop.

Warning Although you can certainly have a loop inside a loop inside a loop inside a loop, the deeper you get, the more potentially confusing your code can become. It’s like the dozens of big cities in America that are promising to build an outer loop (a road that surrounds the outside of the city to help move traffic faster). Eventually, that outer loop won’t be big enough, so the cities have to build another and another. That’s kind of a frightening prospect, so try not to get carried away with nesting.

Technical stuff If you put a break statement or a continue statement inside a nested loop, the statement applies to the innermost loop it sits in. For example, the ForLoop6 example that follows contains three loops: an outer loop, a middle loop, and an inner loop. The break statement applies to the middle loop, as shown here:

#include <iostream>

using namespace std;

int main()
{
for (int x = 1; x <= 3; x++)
{
for (int y = 1; y < 3; y++)
{
if (y == 2)
break;
for (int z = 1; z < 3; z++)
{
cout << x << " " << y;
cout << " " << z << endl;
}
}
}
return 0;
}

You can see that when y is 2, the for loop with the y in it breaks. But the outer loop continues to run with the next iteration.