C if, else, switch & ternary Conditional Control Tutorial

In this C tutorial we learn how to execute code based on certain conditions.

We cover the if, else if, else and switch statements as well as how to use the ternary operator (? :) and how to nest conditional statements.

Here's a table of contents of what you'll learn in this lesson:
(click on a link to skip to its section)

Let's jump right in.

What is conditional control flow

C allows us to control the flow of our program by evaluating conditions, and executing code based on the result.

As an example, let’s consider a program with a member area. If a user provides the correct login credentials, they will be allow to enter the member area. Otherwise, they have the option to try again or reset their password.

So we can imagine the code to look something like the following.

Example:
if username matches database username
and password matches database password
	then direct user to member area

otherwise
	tell user to try again
	or offer a way to reset password

The actual code for conditional expressions doesn’t look like this but the concept is the same.

C allows us to test conditions with the following conditional expressions.

  • An if statement
  • One or more optional else if statements
  • An optional else statement
  • A switch block

The if statement

An if statement will evaluate a condition, and execute a section of code if that condition proves true.

An if statement is written with the keyword if , followed by parentheses. Inside the parentheses we give our condition(s).

Then, we specify a code block with open and close curly braces. Inside the code block we write any code that must be executed if the condition evaluates to true.

Syntax:
if (conditional expression)
{
	// code to execute if
	// condition is true
}

The if conditional statement is not terminated with a semicolon. Instead the final curly brace represents the termination of the statement.

Example:
#include <stdio.h>

int main()
{
    if(1 < 2)
    {
        printf("Condition is true\n");
    }

    printf("Code outside and below if statement\n");

    return 0;
}

In the example above, we check to see if the number 1 is less than 2. Because the condition proves true, the code inside the code block is executed and a message is printed to the console.

Because the program executes sequentially, it will print the next message outside and below the if statement once it’s done with the if statement itself.

If we change the condition to be false, the code inside the if statement’s code block will not execute.

Example:
#include <stdio.h>

int main()
{
    if(1 < 1)
    {
        printf("Condition is true\n");
    }

    printf("Code outside and below if statement\n");

    return 0;
}

This time, only the code outside and below the if statement executed. The condition proved false so the compiler skipped the if statement’s code block.

Test multiple if conditions

We can evaluate multiple conditions inside the parentheses by using logical operators .

To test if one condition and another is true, we use the && operator which signifies AND.

Example:
#include <stdio.h>

int main()
{
    int num = 10;

    if(num > 5 && num < 15)
    {
        printf("Condition is true\n");
    }

    return 0;
}

In the example above, we check if the value of num is greater than 5 and also less than 15.

To test if one condition or another is true, we use the || operator, which signifies OR.

Example:
#include <stdio.h>

int main()
{
    int num = 10;

    if(num < 5 || num >= 10)
    {
        printf("Condition is true\n");
    }

    return 0;
}

In the example above, we check if the value of num is less than 5 or greater than or equal to 10. Only one condition needs to be true for the code block to execute.

We can combine the two operators in an evaluation. When combining the two it’s recommended to wrap the tests in extra parentheses to avoid any complications.

Example:
#include <stdio.h>

int main()
{
    int num1 = 10,
        num2 = 20;

    if( (num1 > 50 && num1 < 100) || (num2 > 15 && num2 < 25) )
    {
        printf("Condition is true\n");
    }

    return 0;
}

Note how our two and conditions are wrapped in an extra set of parentheses.

This is how it works:

  • The compiler tests that both conditions inside the first set of parentheses are true (num1 > 50 && num1 < 100).
  • Because the conditions are enclosed with their own set of parentheses, the compiler knows to group them.
  • The condition proves false and the compiler sees it has an or check to do, so it moves on to the next set of conditions (num2 > 15 && num2 < 25).
  • This time the condition proves true so the code in the execution block can run.

We don’t always need to include the inner sets of parentheses, the compiler is smart enough to detect what we want.

However, its good practice to include them not only because it reads easier, but to avoid any potential misbehavior.

The else if statement

We can test multiple different individual conditions with an else if statement. An else if statement is just another if statement appended to the end of the first one.

To write an else if statement, we add a second if statement to the end of the first one, separated by the else keyword.

Syntax:
if (condition1)
{
	// code block
}
else if (condition2)
{
	// second code block
}

If the first condition evaluates to false, the compiler will go directly to the else if statement and test its condition(s).

Example:
#include <stdio.h>

int main()
{
    if (1 > 2)
    {
        printf("if executed\n");
    }
    else if (1 < 2)
    {
        printf("else/if executed\n");
    }

    return 0;
}

In the example above, our first condition evaluates to false so the compiler moves on to the else if statement. The else if statement evaluates to true so its code block is executed.

An else if statement can never be the first conditional statement in a set. There must always be an if statement before it.

We can append as many else if statements as we need. The compiler will evaluate each condition sequentially.

The else statement

The else statement is used as a catch-all fallback situation. Any condition that’s not handled by an if or else if statement will be caught in the else.

An else statement has no conditional test, so we don’t include parentheses for it. It’s simply added to the end of an if or else if statement by using the keyword else .

Syntax:
if (condition)
{
	// code block
}
else
{
	// catch all
	// code block
}
Example:
#include <stdio.h>

int main()
{
    int num = 1;

    if (num > 1)
    {
        printf("if executed\n");
    }
    else
    {
        printf("else executed\n");
    }

    return 0;
}

In the example above, the if condition evaluates to false. The compiler then moves down to the else statement and automatically executes the code inside of its code block.

An else statement can never be a standalone statement, it needs an if or else if statement before it.

The ternary operator ? :

The ternary operator is a shorthand method of writing a simple if/else statement. For an if/else statement to qualify to be converted into a ternary, it has to consist of the following.

  • An if and an else statement.
  • Only one execution statement in each code block.

As an example of the correct if/else statement for a ternary, let’s consider the following.

Example:
#include <stdio.h>

int main()
{
    if (2 > 1)
    {
        printf("if\n");
    }
    else
    {
        printf("else\n");
    }

    return 0;
}

The if/else statement in the example above has all the requirements to be turned into a ternary.

It has both an if and else statement, and it has only one execution statement in the code blocks for the if and else.

Now that we have an if/else to be converted, let’s look at how a ternary operator is written.

Syntax:
 (condition) ? if_execution : else_execution;

Let’s break it down step by step:

  • The condition is written first, either inside parentheses or not.
  • Following the condition is the question mark operator ( ? ). The statement then reads: is this condition true or false ?
  • After the question mark, we specify the single execution statement if the condition is true (the if execution statement).
  • Then, we use a colon operator ( : ) to separate the if and else execution statements.
  • Lastly, we specify the single execution statement if the condition is false (the else execution statement).

The ternary expression is terminated with a semicolon.

Now that we understand how the ternary is written, let’s convert our if/else statement from earlier into a ternary expression.

Example:
#include <stdio.h>

int main()
{
//    if (2 > 1)
//    {
//        printf("if\n");
//    }
//    else
//    {
//        printf("else\n");
//    }

    2 > 1 ? printf("if\n") : printf("else\n");

    return 0;
}

In the example above, we commented out the original if/else statement instead of deleting it so that we can use it as a reference for the ternary.

The condition is the same as the one in the if statement. We wrote the condition without parentheses to illustrate that it can be done.

We also use the same printf() statements as those in the if/else to illustrate which execution statements fit where.

The switch statement

Where the ternary operator is a different way of writing an if/else statement, the switch is a different way of writing an else if statement.

However, a switch is only useful when we want to evaluate direct comparisons such as x == y. We use it when we want to compare one main value against many others, like (x == a) || (x == b) || (x == c).

The syntax for a switch statement seems complex at first, so let’s look at the syntax and then break it down.

Syntax:
switch (mainValue)
{
	case checkAgainstMainValue:
		// statement(s)
		break;

	default:
		// default statement(s)
};

Let’s go through the syntax step by step:

  • The mainValue between parentheses is the one that will be compared to all other values.
    • In a statement like (x == a) || (x == b), the mainValue is x.
  • Inside the code block is where we specify all the values we want to check against the mainValue. We can have more than one of these cases.
    • We write the keyword case , followed by the value we want to check against the mainValue and a colon. In a statement like (x == a) || (x == b), the cases will be a and b.
    • After, or below, the colon we write the statement(s) we want to execute if the value matches the mainValue.
    • Then, with the break keyword, we tell the compiler that we’ve found what we were looking for and it can exit the switch statement.
    • The default case is used when none of the other cases matches the mainValue, like an else fallback statement.
Example:
#include <stdio.h>

int main()
{
    int num = 2;

    switch(num)
    {
        case 1:
            printf("The number is 1\n");
            break;
        case 2:
            printf("The number is 2\n");
            break;
        case 3:
            printf("The number is 3\n");
            break;
        default:
            printf("Sorry, the number doesn't match\n");
    }

    return 0;
}

In the example above we check the values 1, 2 or 3 is the same as the value in num. When we get a match, we print a message to the console and then break out of the switch.

Let’s write the same switch as an else if statement.

Example:
#include <stdio.h>

int main()
{
    int num = 2;

    if (num == 1)
    {
        printf("The number is 1\n");
    }
    else if (num == 2)
    {
        printf("The number is 2\n");
    }
    else if (num == 3)
    {
        printf("The number is 3\n");
    }
    else
    {
        printf("Sorry, the number doesn't match\n");
    }

    return 0;
}

When we compare the switch statement with the else if statement, the switch is cleaner and reads clearer.

For many beginner developers the switch statement is difficult to understand and write. You don’t strictly have to use the switch, but it is cleaner and does read easier.

The best way to get used to the switch statement, is just to practice writing it. So let’s have another example.

Example:
#include <stdio.h>

int main()
{
    char grade = 'B';

    switch (grade)
    {
        case 'A':
            printf("Excellent!\n");
            break;
        case 'B':
            printf("Very good\n");
            break;
        case 'C':
            printf("Well done\n");
            break;
        case 'D':
            printf("You passed\n");
            break;
        case 'F':
            printf("You failed\n");
            break;
        default:
            printf("Invalid grade\n");
            break;
    }

    return 0;
}

The example above is a more realistic scenario where the switch statement would be used. We’re simply comparing a standard set of grades to one a student has.

Nesting conditional statements

C allows us to use conditional statements inside other conditional statements, often referred to as nesting.

When a statement is nested within another statement, they will be evaluated hierarchically.

How to nest if, else if & else statements

To nest an if statement inside another if statement, we simply write it in its code block.

Syntax:
if (outerCondition)
{
	if (innerCondition)
	{
		// inner execution statement(s)
	}
}

The compiler will start by evaluating the outerCondition, if it proves true it will move on to the innerCondition and evaluate it.

Example:
#include <stdio.h>

int main()
{
    int num = 10;

    if (num < 20)
    {
        printf("outer if\n");

        if (num >= 10)
        {
            printf("inner if\n");
        }
    }

    return 0;
}

In the example above, the inner if statement will only be evaluated when the outer if proves true. In this case both proves true so both message print to the console.

It should be noted that if we nest more than three levels deep, we should consider a different solution.

Summary: Points to remember

  • We can control the flow of an application with conditional statements.
    • Statements will be checked sequentially and will execute if their conditions prove true.
  • An if statement tests if one or more statements are true and executes code if it is.
  • An else if statement is simply more if statements appended to the main if with an else keyword.
  • The else statement is a catch-all fallback for when none of the if or else if statements evaluate to true.
  • The ternary operator is a shorthand method to write a simple if/else statement.
    • A ternary is used when we have both an if and else statement and only single execution statements inside them.
  • We use the switch statement when we need to compare one value against many others.
  • Conditional statements can be nested inside other conditional statements.
    • If we need to nest more than 3 times, we should consider finding a different solution.