More about Functions Top Input and OutputConditionals Contents

Conditionals

Conditionals implement decision points in a computer program. Suppose you have a program that performs some task on an image. You may well have a point in the program where you do one thing if the image is a JPEG and quite another thing if the image is a GIF file. Likely, at this point, your program will include a conditional expression to make this decision.

Before learning about conditionals, it is important to learn about logical expressions. Such expressions are the core of conditionals and loops.24

Logical expressions

A logical expression evaluates to a truth value, in essence true or false. For example, the expression x > 0 resolves to true if x is positive and false if x is negative or zero. In C, falsehood is represented by the integer 0 and truth by any other integer, usually 1. Recall that, together, these two values are known as BOOLEAN values.

One can assign truth values to integer variables:

      //test
      int c = -1;
      int z = (c > 0);
      printf("z is %d\n",z);     //should print z is 0

If c were positive, the variable z would be assigned a value of 1, which is interpreted as true. Since c is negative, however, it is assigned a value of zero, which is interpreted as false. The parentheses are added to the comparison to improve readability.

Logical operators

Let's review C's logical operators:

== equal to
!= not equal to
>= greater than or equal to
> greater than
< less than
<= less than or equal to
&& AND, both must be true
|| OR, one or both must be true
! a unary operator that reverses a truth value

The first six operators are used for comparing two things, while the next two operators are the glue that joins up simpler logical expressions into more complex ones. The last operator is used to reverse a logical value from true to false and vice versa.

Beginning programmers often confuse the = operator, which is the assignment operator, with the == operator, which is the equality operator. Remember, assignment is used to change the value of a variable while equality can be used to test the value of a variable (without changing its value). Fortunately, the GNU C compiler detects many attempts to use assignment when equality is intended and will complain appropriately.

Short circuiting

When evaluating a logical expression, C evaluates the subexpressions from left to right and stops evaluating as soon as it finds out that the entire expression is definitely true or definitely false. For example, when encountering the expression:

      x != 0 && y / x > 2

if x has a value of 0, the subexpression on the left side of the AND connective resolves to false. At this point, there is no way for the entire expression to be true (since both the left hand side and the right hand side must be true for an AND expression to be true), so the right hand side of the expression is not evaluated. Note that this particular expression protects against a divide-by-zero error.

Likewise, if the first subexpression in an OR expression is true, then the entire OR expression is true and there is no need to evaluate the second expression in the disjunction. For example, if the call to function f returns true, then the call to function g is never made:

    f(x) || g(x,y)

If expressions

C's if expressions are used to conditionally execute code, depending on the truth value of what is known as the test expression. One version of if has a single statement following the test expression:

Here is an example:

    if (strcmp(name,"John") == 0)               //0 means the same
        printf("I like that name!");

In this version, when the test expression is true (i.e., the statement following it is executed, causing the compliment. If the test expression is false, however the following statement is not evaluated. You can also use blocks. The following code is equivalent to the previous:

    if (strcmp(name,"John") == 0)               //0 means the same
        {
        printf("I like that name!");
        }

The advantage of blocks is that you can have more the one statement evaluated when the test expression is true. Novice programmers sometimes think that indentation is sufficient, as in:

    if (strcmp(name,"John") == 0)               //0 means the same
        printf("I like that name!");
        goodName = 1;

Since C doesn't care about indentation25, it assumes the assignment statement does not belong to the if at all and goodName is set to 1 regardless of whether name is "John" or not. Some programmers always use blocks even if there is a single statement to be executed. We will use that convention in this text, unless we are trying to save space.

Here is another form of if:

    if (strcmp(major,"Computer Science") == 0)
        {
        print("Smart choice!")
        }
    else
        {
        print("Ever think about changing your major?")
        }

In this version, if has two blocks, one following the test expression and one following the else keyword. As before, the first block is evaluated if the test expression is true. If the test expression is false, however, the second block is evaluated instead. Also as before, if the blocks have a single statement, the braces can be omitted.

if-elseif-else chains

You can chain if statements together using the else keyword, followed by an if statement, as in:

    if (bases == 4)
        {
        printf("HOME RUN!!!\n");
        }
    else if (bases == 3)
        {
        printf("TrIpLe!!\n");
        }
    else if (bases == 2)
        {
        printf("Double!\n");
        }
    else if (bases == 1) 
        {
        printf("single\n");
        }
    else
        {
        printf("out\n");
        }

The block that is eventually evaluated is directly underneath the first test expression that is true, reading from top to bottom. If no test expression is true, the block associated with the else is evaluated. Note that the else is not required; if no test expressions evaluate to true, then no blocks are executed.

What is the difference between if-elseif-else chains and a sequence of unchained ifs? Consider this rewrite of the above code:

    if (bases == 4)
        {
        printf("HOME RUN!!!\n");
        }
    if (bases == 3)
        {
        printf("TrIpLe!!\n");
        }
    if (bases == 2)
        {
        printf("double!\n");
        }
    if (bases == 1) 
        {
        printf("single\n");
        }
    else
        {
        printf("out\n");
        }

In the second version, there are four if statements and the else belongs to the last if. Does this behave exactly the same? The answer is, it depends. Suppose the value of the variable bases is 0. Then both versions print:

    out

However, if the value of bases is 3, for example, the first version prints:

    TrIpLe!!

while the second version prints:

    TrIpLe!!
    out

Why the difference? In the first version, a subsequent test expression is evaluated only if all previous test expressions evaluated to false. Once a test expression evaluates to true in an if-elseif-else chain, the associated block is evaluated and no more processing of the chain is performed. Like the AND and OR BOOLEAN connectives, an if-elseif-else chain short-circuits.

In contrast, the sequences of ifs in the rewrite are independent; there is no short-circuiting. When the test expression of the first if fails, the test expression of the second if succeeds and TrIpLe!! is printed. Now the test expression of the third if is tested and fails as well as the test expression of the fourth if. But since the fourth if has an else, the else block is evaluated and out is printed.

It is important to know when to use an if-elseif-else chain and when to use a sequence of independent ifs. If there should be only one outcome, then use an if-elseif-else chain. Otherwise, use a sequence of ifs.

Explore further

Other constructs in the same vein as the if statement are switch or case statement and the embedded if expression (sometimes known as the ternary operator). Search the web to find out more.

Practice with BOOLEAN expressions

Here is some practice on writing complex BOOLEAN expressions. Your task is to convert the English description into a C BOOLEAN expression. The variables to be used in the expressions are:

An old dog is one with an age greater than seven years while an old cat has an age greater than or equal to nine years. A cat and a dog are young if they are younger than three years old.

Write a boolean expression that captures:

Dogs that are large and have spots or cats that are white but do not have blue eyes.

Highlight the following line to see the answer:

Answer: (animal == "dog" && size == "large" && hasSpots) || (animal == "cat" && coatColor == "white" && eyeColor != "blue")

lusth@cs.ua.edu


More about Functions Top Input and OutputConditionals Contents