Brought to you by one of our trusted brand advertisers, the C++ Times is proud to present a skills supplement to today's edition. Trusted Ternary Advisors, a company dedicated to talent management for companies recruiting software developers, brings you this advertorial on developing with selective execution.
One of the toughest decisions that we make in our lives, right after determining whether to attend college, move or buy a house, marry our partner or have children, is the decision about whether to take an umbrella with us as we leave the house every day. If you take an umbrella, you know it will annoy you all day and won't rain. If you don't take an umbrella, then you are guaranteed it will rain.
Only slightly less important on a day-to-day basis is the choice of top to wear. Do I need a jacket? Should I wear a hoodie? Or, am I safe with a t-shirt? Just pondering the answer to these questions will put you in the same mental state as Prince Hamlet or Descartes.
C++ can get you out of a bind. Our program will act on the value of some given parameters (temperature
, is_dry
and precipitation
) to give helpful advice about how to leave our condo prepared for the climate.
There are a pretty clear set of criteria for choosing whether to take a jacket, throw on a hoodie or wear a t-shirt.
If the temperature is less than 45 degrees, then we wear a jacket. If the temperature is between 45 degrees and 60 degrees, then we will wear a hoodie (the best article of clothing ever invented). Finally, if it is above 60 degrees we will wear a t-shirt. Pretty straightforward.
Because I am a relatively cold-blooded person (not that kind of cold blooded!), we will say that the day is "warm" if the temperature is above 60 degrees.
Given those parameters, let's write a piece of code that will calculate the proper value for the top_to_wear
string variable. The top_to_wear
value should contain:
"jacket"
when the temperature is less than or equal to 45 degrees;"hoodie
" when the temperature is between 45 and 60 degrees (inclusive); and"t-shirt"
when the temperature is at least 60 degrees.
Given the values that we want to store in the top_to_wear
variable, what should be its type? I think that a std::string
seems appropriate. What other type could we use to store sequences of characters? Really, there's no other choice!
We can assume that we are performing our calculations based on the value of the temperature
variable that contains the ambient temperature. We'll leave it as an exercise of the imagination to determine how that variable is set. Perhaps our program reads the value from a sensor attached to the computer or perhaps our program reads the value from the internet. Either way, the temperature may not be a whole number. Because that's the case, we will want to make temperature
a double
.
The program should print:
It's _______ degrees outside; wear a _______.
with the appropriate values filling the ________
s. Later we will add functionality to alert the user when they should take an umbrella.
Here's what our program looks like so far:
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{48.0}; 6 7 std::cout << "It's " << temperature << " degrees outside; wear a " 8 << top_to_wear << ".\n"; 9 10 return 0; 11 }
and it's output is
It's 48 degrees outside; wear a .
We're off to a pretty good start.
We can use an if
statement to conditionally set the value of top_to_wear
to the proper value. Let's tackle the conditions from coolest to hottest. We wear a jacket when the temperature is less than 45 degrees.
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{48.0}; 6 7 if (temperature < 45.0) { 8 top_to_wear = "jacket"; 9 } else { 10 11 } 12 13 std::cout << "It's " << temperature << " degrees outside; wear a " 14 << top_to_wear << ".\n"; 15 16 return 0; 17 }
and it's output is
It's 48 degrees outside; wear a .
There's no change despite the additional code! Why not? Because the temperature
is 48
-- not less than 45; line 8 does not execute.
Thanks to the combination of the bool
ean expression in the if
statement on line 7 and the else
on line 9, if the program executes code that we put on line 10 (or really anywhere between the {
on line 9 and the }
on line 11), we can assume that what is true? Exactly! That the temperature
is greater than 45 degrees.
Therefore, to determine whether it is hoodie weather, all we need to add is an if
statement whose bool
ean expression determines whether the temperature is less than or equal to 60 degrees!
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{48.0}; 6 7 if (temperature < 45.0) { 8 top_to_wear = "jacket"; 9 } else { 10 if (temperature <= 60.0) { 11 top_to_wear = "hoodie"; 12 } else { 13 14 } 15 } 16 17 std::cout << "It's " << temperature << " degrees outside; wear a " 18 << top_to_wear << ".\n"; 19 20 return 0; 21 }
Can you see how we are using what we know about the state of a variable at a current position in the code to limit the complexity of the bool
ean expression in a conditional? Of course we could have written a more complicated expression to check that the temperature is greater than 45 and less than or equal to 60 at line 60, but we didn't need to!
The program prints
It's 48 degrees outside; wear a hoodie.
Awesome! Now we are getting somewhere. Because we are testing with the temperature
set to 48 degrees, the output is correct and tells us that we should wear a hoodie.
Great. Our program performs as expected. Let's test it before we send it to our users. If it is a cold day and the temperature is freezing, our temperature
variable contains the value 32
. The program outputs:
It's 32 degrees outside; wear a jacket.
Great! And, if it is an early Spring day, the temperature
might be 59:
It's 59 degrees outside; wear a hoodie.
So far we are on track to ship the application to our customer!
If it's a hot Midwest day in August, the temperature
is 95
(with 100% humidity, of course):
It's 95 degrees outside; wear a .
Uh oh. Our program failed to give good advice to the user. It looks like we forgot to handle a case!
Remember the code that we currently have:
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{95.0}; 6 7 if (temperature < 45.0) { 8 top_to_wear = "jacket"; 9 } else { 10 if (temperature <= 60.0) { 11 top_to_wear = "hoodie"; 12 } else { 13 // 14 } 15 } 16 17 std::cout << "It's " << temperature << " degrees outside; wear a " 18 << top_to_wear << ".\n"; 19 20 return 0; 21 }
What are we able to assume about the value of temperature
if the program were executing code on line 13 (or really anywhere between the {
on line 12 and the }
on line 14)? That the temperature is greater than 60 degrees. That's awesome because it matches exactly the conditions for recommending that the user wear a t-shirt! We can fix the bug without writing too much extra code!
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{95.0}; 6 7 if (temperature < 45.0) { 8 top_to_wear = "jacket"; 9 } else { 10 if (temperature <= 60.) { 11 top_to_wear = "hoodie"; 12 } else { 13 top_to_wear = "t-shirt"; 14 } 15 } 16 17 std::cout << "It's " << temperature << " degrees outside; wear a " 18 << top_to_wear << ".\n"; 19 20 return 0; 21 }
It's 95 degrees outside; wear a t-shirt.
The program works perfectly! Again, we could have written more complicated logic to determine when to set the variable top_to_wear
to have the "t-shirt"
value but, by process of elimination, we didn't need to. If the program is executing the code at line 13 we know that the only option for the top for the user to wear is a t-shirt!
Programmers often refactor their code. When you refactor code, you rewrite it so that it is more readable, more compact, more efficient -- you take a step back from the details and look at how you can make the code "better". To do that, we will learn a feature of C++ that is a blessing and a curse!
In general, there are two forms of if
statements in C++. The first is used when you have a set of code that you want to optionally execute under certain conditions:
1 #include <iostream> 2 3 int main() { 4 5 if (expression) { 6 // Code to execute when expression is true. 7 } 8 9 return 0; 10 }
The code on line 6 (or really anywhere between the {
on line 5 and the }
on line 7) will execute when expression
evaluates to true
.
Here's where we learn the power and pain of C++. The actual, precise form of the if
statement in a case like this is actually
1 #include <iostream> 2 3 int main() { 4 5 if (expression) 6 statement 7 8 return 0; 9 }
statement
can be anything that we want. For instance, we could assign a variable:
1 #include <iostream> 2 3 int main() { 4 int v{0}; 5 6 if (expression) 7 v = 5; 8 9 return 0; 10 }
That's great and I am sure that you are glad that we are wasting all this time on the minutiae of C++ syntax (remember the definition of that term?). So, why are we worried about these nits? C++ defines the if
statement in that way because of the way that C++ defines the term statement. Trust me, there is a payoff here!
Remember we defined statement a long time ago! We said that a statement was a complete instruction that defined an operation. Sometimes it requires more than one instruction to complete a logical operation. For instance, a complete logical operation might entail changing the value of two variables (adjusting the hours and minutes of a clock, say). C++ lets us combine two (or more) operations to define a complete complete logical operation by grouping them in a pair of {
and }
. Then, anything inside that pair C++ considers a statement! To distinguish between the different types of statements, C++ subdivides statements into categories: expression statements and compound statements.Don't worry, there are other types of statements, just wait!
So, by playing games with semantics, we get some really cool power!
C++ is like living in a funhouse and compound statements are like mirrors facing one another. Compound statements may themselves contain any kind of statement. In other words, compound statements may contain compound statements which may contain compound statements ... and so on!
Why is this important? I'll tell you: if
statements are ... wait for it ... just another category of statements (they are technically called selection statements). So, in
1 #include <iostream> 2 3 int main() { 4 5 if (expression) 6 statement 7 8 return 0; 9 }
we can replace statement
with another if
statement:
1 #include <iostream> 2 3 int main() { 4 5 if (expression) 6 if (expression) 7 statement 8 9 return 0; 10 }
In code like the above, the statement
on line 7 will only execute when both of the expressions are true
. That's pretty cool! (We'll see how to refactor code that follows that form below!)
We've talked about just one of the two forms of if
statements so far. What's the other? It's the form where you want to choose between executing two different sets of operations depending on a condition:
1 #include <iostream> 2 3 int main() { 4 5 if (expression) { 6 // 7 } else { 8 // 9 } 10 11 return 0; 12 }
When the expression
is true
, we execute the code between the {
on line 5 and the }
on line 7. When the expression
is false
, we execute the code between the {
on line 7 and the }
on line 9. Again, this description is slightly misleading. The actual, precise format of such if
statements is
1 #include <iostream> 2 3 int main() { 4 5 if (expression) 6 statement1 7 else 8 statement2 9 10 return 0; 11 }
Now, here's where we'll blow your mind! Combine our knowledge that an if
statement is just a statement like any other with the above format of the if
statement and you can see how we get the valid if
-else if
that is so familiar. Replace statement2
with an if
statement:
1 #include <iostream> 2 3 int main() { 4 5 if (expression) 6 statement1 7 else 9 if (expression) 10 statement3 11 12 return 0; 13 }
and remember that C++ does not care about the breaks between lines and we get
1 #include <iostream> 2 3 int main() { 4 5 if (expression) 6 statement1 7 else if (expression) 10 statement3 11 12 return 0; 13 }
and we can do a little cleanup and we get
1 #include <iostream> 2 3 int main() { 4 5 if (expression) 6 statement1 7 else if (expression) 10 statement2 11 12 return 0; 13 }
Woah!! An amazing outcome -- the else if
that is sometimes considered a special case syntax in other programming languages is built right in to C++! Amazing!
*** Danger, Will Robinson ***
Remember we saw code above that looked like this:
1 #include <iostream> 2 3 int main() { 4 int v{0}; 5 6 if (expression) 7 v = 5; 8 9 return 0; 10 }
? Never, ever write that code! Yes, you are saving yourself two keystrokes, but I promise you that it will eventually bite you! How do I know? Glance quickly (you are on your honor) at the following and tell me what it prints.
1 #include <iostream> 2 3 int main() { 4 int a{0}; 5 int b{1}; 6 int c{0}; 7 int d{0}; 8 9 if (b < a) 10 c = 1; 11 d = 1; 12 std::cout << "c: " << c << "; d: " << d << "\n"; 13 return 0; 14 }
Did you guess that it will print:
c: 0; d: 1
Yeah, I didn't think so! C++ does not care about indentation. You had good intentions, but ultimately the code is wrong. If you always enclose the statements conditionally executed in {
and }
pairs, you will never have this problem. (Obviously this advice does not apply when you are writing an else if
construction but that is an exception, not the rule.)
You've been warned!
What a long digression. Where were we? Oh, yeah, we were refactoring. Okay, so we have
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{95.0}; 6 7 if (temperature < 45.0) { 8 top_to_wear = "jacket"; 9 } else { 10 if (temperature <= 60.) { 11 top_to_wear = "hoodie"; 12 } else { 13 top_to_wear = "t-shirt"; 14 } 15 } 16 17 std::cout << "It's " << temperature << " degrees outside; wear a " 18 << top_to_wear << ".\n"; 19 20 return 0; 21 }
Now that we know how to write else if
s in a cool way, I think it might be more readable if we make our code use that syntax:
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{95.0}; 6 7 if (temperature < 45.0) { 8 top_to_wear = "jacket"; 9 } else if (temperature <= 60.0) { 10 top_to_wear = "hoodie"; 11 } else { 12 top_to_wear = "t-shirt"; 13 } 14 15 std::cout << "It's " << temperature << " degrees outside; wear a " 16 << top_to_wear << ".\n"; 17 18 return 0; 19 }
Ah, yes! Not only is that more compact, it is also more like what we would expect to say in natural language. Great refactoring!
Now we know what goes on above the waist. We still need to add code that helps our user determine whether or not to lug around their umbrella all day. The user only wants to carry their umbrella when it isn't dry outside, the form of precipitation is rain and it is warm. We will add to the list of variables of which our code has access to include a bool
ean, is_dry
that is true
if it is dry outside and a std::string
, precipitation
that describes the form of precipitation. precipitation
will contain the value "snow"
when it is snowing and "rain"
when it is raining.
Let's work on a case-by-case basis. The first case to consider is that we want to do if it is dry. Well, if it is dry, then we certainly don't need to tell the user to take an umbrella. But, if it isn't dry, then we may want to alert the user about the need for their handheld roof.
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{95.0}; 6 bool is_dry{false}; 7 std::string precipitation { "snow" } 8 9 if (temperature < 45.0) { 10 top_to_wear = "jacket"; 11 } else if (temperature <= 60.) { 12 top_to_wear = "hoodie"; 13 } else { 14 top_to_wear = "t-shirt"; 15 } 16 17 std::cout << "It's " << temperature << " degrees outside; wear a " 18 << top_to_wear << ".\n"; 19 20 if (is_dry) { 21 // No need to do anything. 22 } else { 23 24 } 25 return 0; 26 }
When our program gets to the code between the {
on line 22 and the }
on line 24, we can assume what? Well, we can assume that it is not dry! Before telling the user that they need to take an umbrella, we need to check two more conditions! First, we need to check whether the form of precipitation is rain:
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{95.0}; 6 bool is_dry{false}; 7 std::string precipitation { "snow" } 8 9 if (temperature < 45.0) { 10 top_to_wear = "jacket"; 11 } else if (temperature <= 60.) { 12 top_to_wear = "hoodie"; 13 } else { 14 top_to_wear = "t-shirt"; 15 } 16 17 std::cout << "It's " << temperature << " degrees outside; wear a " 18 << top_to_wear << ".\n"; 19 20 if (is_dry) { 21 // No need to do anything. 22 } else { 23 if (precipitation == "rain") { 24 } 25 } 26 return 0; 27 }
Yes, it may sound like a broken record, but think about the assumptions we can make when code between the {
on line 23 and the }
on line 24 are executing! Bingo! We know that it is not dry and that it is raining. The last thing to check before recommending an umbrella is whether it is warm. Our definition for warm (remember it?) is that the temperature is greater than 60:
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{95.0}; 6 bool is_dry{false}; 7 std::string precipitation {"snow"}; 8 9 if (temperature < 45.0) { 10 top_to_wear = "jacket"; 11 } else if (temperature <= 60.) { 12 top_to_wear = "hoodie"; 13 } else { 14 top_to_wear = "t-shirt"; 15 } 16 17 std::cout << "It's " << temperature << " degrees outside; wear a " 18 << top_to_wear << ".\n"; 19 20 if (is_dry) { 21 // No need to do anything. 22 } else { 23 if (precipitation == "rain") { 24 if (temperature > 60.0) { 25 std::cout << "Take an umbrella with you when you leave the house!\n"; 26 } 27 } 28 } 29 return 0; 30 }
Well done! Let's check our work:
It's 95 degrees outside; wear a t-shirt.
Perfect! We are wearing a t-shirt and not taking an umbrella! Although it's not dry, we are experiencing a rare summer snow storm! Let's make the data a little more realistic and make sure that our program works:
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{95.0}; 6 bool is_dry{false}; 7 std::string precipitation{"rain"}; 8 9 if (temperature < 45.0) { 10 top_to_wear = "jacket"; 11 } else if (temperature <= 60.) { 12 top_to_wear = "hoodie"; 13 } else { 14 top_to_wear = "t-shirt"; 15 } 16 17 std::cout << "It's " << temperature << " degrees outside; wear a " 18 << top_to_wear << ".\n"; 19 20 if (is_dry) { 21 // No need to do anything. 22 } else { 23 if (precipitation == "rain") { 24 if (temperature > 60.0) { 25 std::cout << "Take an umbrella with you when you leave the house!\n"; 26 } 27 } 28 } 29 return 0; 30 }
It's 95 degrees outside; wear a t-shirt.
Take an umbrella with you when you leave the house!
Excellent!
There's something incredibly unsightly about this code but I can't put my finger on it!
Oh yes, I see two things that bother me! No, make that three!
First, there is the code on line 21 that doesn't do anything! It would be nice if we could flip around the code and bring the code that we execute in the else
to the top -- that's really where the business gets done, after all! We know that the code between the {
on line 22 and the }
on line 28 gets executed when it is not dry. Is there an operator that we can apply to is_dry
that will tell us when it is not dry? YES! The !
operator. So, we could rewrite our code like
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{95.0}; 6 bool is_dry{false}; 7 std::string precipitation{"rain"}; 8 9 if (temperature < 45.0) { 10 top_to_wear = "jacket"; 11 } else if (temperature <= 60.) { 12 top_to_wear = "hoodie"; 13 } else { 14 top_to_wear = "t-shirt"; 15 } 16 17 std::cout << "It's " << temperature << " degrees outside; wear a " 18 << top_to_wear << ".\n"; 19 20 if (!is_dry) { 21 if (precipitation == "rain") { 22 if (temperature > 60.0) { 23 std::cout << "Take an umbrella with you when you leave the house!\n"; 24 } 25 } 26 } 27 return 0; 28 }
and get the same behavior without that empty line! More importantly, the code reads more naturally!
There is really only one case where the user needs to take their umbrella: When it is not dry and it is raining and when it is warm. Under any other circumstances, we can leave home without it. Hmm. Is there a C++ way to write an and that we could use? Why, yes, there is! Let's clean up the code with some &&
s and watch its elegance increase:
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{95.0}; 6 bool is_dry{false}; 7 std::string precipitation{"rain"}; 8 9 if (temperature < 45.0) { 10 top_to_wear = "jacket"; 11 } else if (temperature <= 60.0) { 12 top_to_wear = "hoodie"; 13 } else { 14 top_to_wear = "t-shirt"; 15 } 16 17 std::cout << "It's " << temperature << " degrees outside; wear a " 18 << top_to_wear << ".\n"; 19 20 if (!is_dry && precipitation == "rain" && temperature > 60.0) { 21 std::cout << "Take an umbrella with you when you leave the house!\n"; 22 } 23 return 0; 24 }
Oh my! That looks so much better.
We are one step away from just amazing code. This final form of refactoring may not seem entirely necessary in this case, but you may find the technique useful in the future -- hint, hint.
Sometimes it is better to do all the calculation together and then all the output together rather than mixing the two together. After all, that's how we describe programs in general: input, processing, output.
To do that, we can use flags. Flags are bool
ean variables whose value represents some state. In this case, let's use a flag to represent whether or not to take an umbrella. To do that, we will add a bool
ean variable named take_an_umbrella
. Because taking an umbrella represents the exception and not the rule, we will start by setting take_an_umbrella
to the default value of false
. Under most circumstances the user will not need to take an umbrella so it makes sense that we should set the default value accordingly:
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{95.0}; 6 bool is_dry{false}; 7 std::string precipitation{"rain"}; 8 bool take_an_umbrella{false}; 9 10 if (temperature < 45.0) { 11 top_to_wear = "jacket"; 12 } else if (temperature <= 60.0) { 13 top_to_wear = "hoodie"; 14 } else { 15 top_to_wear = "t-shirt"; 16 } 17 18 std::cout << "It's " << temperature << " degrees outside; wear a " 19 << top_to_wear << ".\n"; 20 21 if (!is_dry && precipitation == "rain" && temperature > 60.0) { 22 std::cout << "Take an umbrella with you when you leave the house!\n"; 23 } 24 return 0; 25 }
Now, we want to print our advice to the user about their umbrella toting depending on the value of the flag take_an_umbrella
:
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{95.0}; 6 bool is_dry{false}; 7 std::string precipitation{"rain"}; 8 bool take_an_umbrella{false}; 9 10 if (temperature < 45.0) { 11 top_to_wear = "jacket"; 12 } else if (temperature <= 60.) { 13 top_to_wear = "hoodie"; 14 } else { 15 top_to_wear = "t-shirt"; 16 } 17 18 std::cout << "It's " << temperature << " degrees outside; wear a " 19 << top_to_wear << ".\n"; 20 21 if (take_an_umbrella == true) { 22 std::cout << "Take an umbrella with you when you leave the house!\n"; 23 } 24 return 0; 25 }
That's good, but it could be better! How? We wrote take_an_umbrella == true
so that the expression in the if
statement was a bool
(by using the equality operator). But, that's really redundant (just like "really redundant"). After all, take_an_umbrella
is already a bool
ean! We can just drop the == true
part and get the same result. In fact, that's how you will write these type of statements in industry:
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{95.0}; 6 bool is_dry{false}; 7 std::string precipitation{"rain"}; 8 bool take_an_umbrella{false}; 9 10 if (temperature < 45.0) { 11 top_to_wear = "jacket"; 12 } else if (temperature <= 60.) { 13 top_to_wear = "hoodie"; 14 } else { 15 top_to_wear = "t-shirt"; 16 } 17 18 std::cout << "It's " << temperature << " degrees outside; wear a " 19 << top_to_wear << ".\n"; 20 21 if (take_an_umbrella) { 22 std::cout << "Take an umbrella with you when you leave the house!\n"; 23 } 24 return 0; 25 }
And it just reads so well: "If take_an_umbrella
then print the message for the user".
What have we forgotten? Ah, yes, we need to set take_an_umbrella
to true
under a certain set of conditions. The good news is that we already figured out how to write that:
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{95.0}; 6 bool is_dry{false}; 7 std::string precipitation{"rain"}; 8 bool take_an_umbrella{false}; 9 10 if (temperature < 45.0) { 11 top_to_wear = "jacket"; 12 } else if (temperature <= 60.) { 13 top_to_wear = "hoodie"; 14 } else { 15 top_to_wear = "t-shirt"; 16 } 17 18 if (!is_dry && precipitation == "rain" && temperature > 60.0) { 19 take_an_umbrella = true; 20 } 21 22 std::cout << "It's " << temperature << " degrees outside; wear a " 23 << top_to_wear << ".\n"; 24 25 if (take_an_umbrella) { 26 std::cout << "Take an umbrella with you when you leave the house!\n"; 27 } 28 return 0; 29 }
Notice:
- There are
{
}
s aroundtake_an_umbrella = true;
even though they aren't strictly necessary; - All the input is together, all the calculations are together and all the output is together -- nice!
We just can't resist one final tweak. If you write code like the following, you are in Pro Mode!
Think carefully about the answer to the following question: When is line 19 going to get executed? Thought about it? Good! Line 19 is executed when the expression !is_dry && precipitation == "rain" && temperature > 60.0
is true
. As a result, take_an_umbrella
is true
when !is_dry && precipitation == "rain" && temperature > 60.0
is true
.
Hmm. Coincidence? I think not! take_an_umbrella
is a bool
ean. The type of the value of the expression !is_dry && precipitation == "rain" && temperature > 60.0
is a bool
ean. Can you assign a bool
ean value to a bool
ean variable? You bet!
1 #include <iostream> 2 3 int main() { 4 std::string top_to_wear{""}; 5 double temperature{95.0}; 6 bool is_dry{false}; 7 std::string precipitation{"rain"}; 8 bool take_an_umbrella{false}; 9 10 if (temperature < 45.0) { 11 top_to_wear = "jacket"; 12 } else if (temperature <= 60.) { 13 top_to_wear = "hoodie"; 14 } else { 15 top_to_wear = "t-shirt"; 16 } 17 18 take_an_umbrella = !is_dry && precipitation == "rain" && temperature > 60.0; 19 20 std::cout << "It's " << temperature << " degrees outside; wear a " 21 << top_to_wear << ".\n"; 22 23 if (take_an_umbrella) { 24 std::cout << "Take an umbrella with you when you leave the house!\n"; 25 } 26 return 0; 27 }
Now that is some awesome looking code!