# Class 7: IF II

Section 2.2 of Absolute C++

Lecture

## Logical Operators

Consider a code fragment that reads in a value from the user and returns the "arcsine" or inverse sine of the value. We'll use the `asin` function from the `cmath` library to compute our value. Now, the arcsine is only defined for values between negative 1 and 1, so if the user enters a value outside of this range we should print an error message. Doing this with what we know so far is ugly:

`if (x <= 1.0)`
`{`
`  if (x >= -1.0)`
`  {`
`    cout << "arcsine of " << x << " = " << asin(x) << endl;`
`  }`
`  else`
`  {`
`    cout << "Error! Value outside of [-1,1]!" << endl;`
`  }`
`}`
`else`
`{`
`  cout << "Error! Value outside of [-1,1]!" << endl;`
`}`

We want to be able to say in our test condition that x must be less than or equal to 1 AND greater than or equal to -1. In C++ the operator `&&` is "and". So our program fragment becomes:

`if (x <= 1.0 && x >= -1.0)`
`{`
`  cout << "arcsine of " << x << " = " << asin(x) << endl;`
`}`
`else`
`{`
`  cout << "Error! Value outside of [-1,1]!" << endl;`
`}`

... which is substantially simpler. More to the point, this does a much better job of reflecting what we're thinking.

## `&&` as an operator on objects of type `bool`

At first glance, `&&` looks like something mysterious and new. It's not. It's an operator just like +, *, and >>, all of which we've used a lot already. It takes two objects of type `bool` and evaluates to an object of type bool. We have an intuitive idea of what "and" means, and it coincides with C++'s technical, exact definition of what `&&` means:

 Expression Result ```false && false``` `false` `false && true` `false` `true && false` `false` `true && true` `true`

So, something like `x <= 1.0 && x >= -1.0` makes sense because `x <= 1.0` evaluates to a `bool` and `x >= -1.0` evaluates to a `bool`, and then the `&&` operates on the two `bool` values.

## Boolean operators

There are three boolean operators, the now familiar `&&` (and), the `||` operator (or), and the `!` (not) operator.

The `||` operator is much like `&&`, it takes two objects of type `bool` and evaluates to an object of type `bool`. The result is `true` if either or both are `true`, and `false` otherwise.

 Expression Result `false || false` `false` `false || true` `true` `true || false` `true` `true || true` `true`

The `!` operator is a unary operator. Instead of operating on left and right-had values, it operates on a single value - the value following it on the right. It evaluates to the not of the value following, so if the value following is `true`, the `!` expression is `false`.

 Expression Result `!false` `true` `!true` `false`

## Combining boolean operations

Things get especially interesting when you combine boolean operators. For example: Suppose you want to write a program that reads a character from the user and prints "Letter" or "Not a Letter" depending on whether or not the user entered a character that's a letter. Your program will, more or less, look like this:

`  // Read char`
`  char c;`
`  cout << "Enter a letter: ";`
`  cin >> c;`
` `
`  // Decide: Letter or not a letter?`
`  if (`c` is a letter)`
`  {`
`    cout << "Letter" << endl;`
`  }`
`  else`
`  {`
`    cout << "Not a Letter" << endl;`
`  }`

But, of course, the problem is the test condition `c` is a letter. Letters come in two flavors, uppercase and lowercase. So a refinement of our program would be:

`  // Read char`
`  char c;`
`  cout << "Enter a letter: ";`
`  cin >> c;`
` `
`  // Decide: Letter or not a letter?`
`  if (`c` is an uppercase letter || `c` is a lowercase letter)`
`  {`
`    cout << "Letter" << endl;`
`  }`
`  else`
`  {`
`    cout << "Not a Letter" << endl;`
`  }`

Looking at our ASCII table, we see that uppercase letters have ASCII values from 65 to 90. So `c` is an uppercase letter boils down to ```(c >= 65 && c <= 90)```. Similarly, lowercase letters have ASCII values from 97 to 122. So `c` is a lowercase letter boils down to ```(c >= 97 && c <= 122)```. Put it all together and we get:

`  // Decide: Letter or not a letter?`
`  if ((c >= 65 && c <= 90) || (c >= 97 && c <= 122))`
`  {`
`    cout << "Letter" << endl;`
`  }`
`  else`
`  {`
`    cout << "Not a Letter" << endl;`
`  }`

Note that I wrapped my uppercase and lowercase tests in parentheses, because I wanted to be sure that the `&&`'s were evaluated before the `||`. Is that necessary? (Think about how you would decide this!) Even if it isn't, adding the ()'s makes the meaning clear to everyone. Check out this complete solution.

## Shortcut #1: Dropping {}'s from one-statement blocks

If your then-block (or else-block) consists of a single statement, you can drop the {}'s - but only if it consists of a single statement! This is just a form of shorthand to save you some keystrokes and a little bit of screen real estate. So, for example, in the previous code fragment we may remove the {}'s, since both blocks consist of a single statement.

`  // Decide: Letter or not a letter?`
`  if ((c >= 65 && c <= 90) || (c >= 97 && c <= 122))`
`    cout << "Letter" << endl;`
`  else`
`    cout << "Not a Letter" << endl;`

Once again, this is just a shortcut to save keystrokes and screen space, but you will see this shortcut often. If you try to drop the {}'s when you have more than one thing in the block, you'll run into trouble. In this case:

`  // Decide: Letter or not a letter?`
`  if ((c >= 65 && c <= 90) || (c >= 97 && c <= 122))`
`    cout << "Letter" << endl;`
`    cout << "Way to follow directions!" << endl;`
`  else`
`    cout << "Not a Letter" << endl;`

your compiler will complain and give you a "parse error". As far as the compiler is concerned, that "`else`" doesn't belong to any "`if`"! It's not impressed with the fact that the "```cout << "Way to follow directions!" << endl;``` is indented as if it belonged to the else-block. It interprets the above as

`  // Decide: Letter or not a letter?`
`  if ((c >= 65 && c <= 90) || (c >= 97 && c <= 122))`
`  {`
`    cout << "Letter" << endl;`
`  }`
`  cout << "Way to follow directions!" << endl;`

and thinks that we're dealing with an "`if`" from which the else-block has been dropped. Therefore, it is unhappy when it sees the "`else`" from out of nowhere!

## Shortcut #2: The `else if`

An example will probably make this clearer than any abstract discussion. Suppose I have a variable `x` of type `double` that I know is between 0 and 1, and suppose I want to print out for the user "`x is in [0,1/3]`", "`x is in [1/3,2/3]`", or "`x is in [2/3,1]`" depending on the value of `x`. Our first shot would probably be:

`  if (x <= 1.0/3.0)`
`  {`
`    cout << x << " is in [0,1/3]" << endl;`
`  }`
`  else`
`  {`
`    if (x <= 2.0/3.0)`
`    {`
`      cout << x << " is in [1/3,2/3]" << endl;`
`    }`
`    else`
`    {`
`      cout << x << " is in [2/3,1]" << endl;`
`    }`
`  }`

However, our "`cout`" statements are if-blocks and else-blocks consisting of a single statement, so Shortcut #1 tells us we can drop the {}'s surrounding those statements, which would give us:

`  if (x <= 1.0/3.0)`
`    cout < x < " is in [0,1/3]" < endl;`
`  else`
`  {`
`    if (x <= 2.0/3.0)`
`      cout < x < " is in [1/3,2/3]" < endl;`
`    else`
`      cout < x < " is in [2/3,1]" < endl;`
`  }`

However, an "`if`" statement is a single statement, so Shortcut #1 tells us that we can drop the {}'s surrounding the second "`if`" statement, which would give us:

`  if (x <= 1.0/3.0)`
`    cout < x < " is in [0,1/3]" < endl;`
`  else`
`    if (x <= 2.0/3.0)`
`      cout < x < " is in [1/3,2/3]" < endl;`
`    else`
`      cout < x < " is in [2/3,1]" < endl;`

However, the C++ compiler is not sensitive to to formatting, so it deosn't distingquish between "if-newline-else" and "if-space-else", so we could rewrite things to look like this:

`  if (x <= 1.0/3.0)`
`    cout < x < " is in [0,1/3]" < endl;`
`  else if (x <= 2.0/3.0)`
`    cout < x < " is in [1/3,2/3]" < endl;`
`  else`
`    cout < x < " is in [2/3,1]" < endl;`

People refer to the "`else if`" as if it were a new programming construct, but you see it is just the same code with the same meaning as our original ... it just looks a little prettier, saves keystrokes, and takes up a little less screen real estate. There's nothing new here! All we did was to take advantage of Shortcut #1 and to use some nice formatting. It sure looks prettier though. Once again, this is just a shortcut to save keystrokes and screen space, and to make your code easier to read - but you will see this shortcut often.

The "```if else```" formatting is particularly nice when you have disjoint cases to distinguish. For example, suppose you had a variable `d` of type `string` that contained a day of the week name (e.g. Thursday), and you had an `int` `k` that you wanted to set to the number of the day `d` (e.g. 5 for Thursday). Look at the difference between the code with no shortcuts and the code as an "```else if```". It makes a huge difference in terms of how easy the code is to understand!

Lecture Examples

## Problems

1.      Solving for the unknown quantity in F = m a. For this problem, Solution 1 is easier to come up with but more complicated to implement. Solution 2 is more subtle, but cleaner and less complicated to program.

2.      Date conversion program

Assoc Prof Christopher Brown