Chapter 5
IN THIS CHAPTER
Comparing numbers and evaluating other conditions
Doing things based on a comparison
Repeating code in specific ways
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.
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:
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.
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'
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:
x == 10
When the computer finds this statement, it checks to see whether x
equals 10
.
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.
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:
x > 9
. In that case, the condition is true
if x
equals 10
, or 11
, or 12
, and so on.x >= 10
. This condition also is true if x
equals 10
, 11
, and so on. 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.
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)
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.
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.”
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.
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
.
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.
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.
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.
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 |
---|---|
|
|
|
|
|
|
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.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.
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:
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.
x
and i
.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.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.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.
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.
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
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.
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.
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.
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.
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.
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.
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!
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
.
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!
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.
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!"
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;
}
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.
#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.