learn C with me - week 3 - flow control

Table of contents

quick note

Hey, it's me; I don't expected for this post to take so long, but school hit me like a fuckin train (again lol) and by it I had limited time to work on it and also it's shorter than usually, but I hope it will be still something worth reading containing valuable knowledge.
Have a nice day,
Laura

flow control

Flow control is function making programs truly exciting. It allows computer to decide on future endeavour based on earlier defined factors, like changing display theme to dark IF user already turned it on, or keep downloading movie WHILE there is a wifi connection. Flow control can be divided into two categories, first is called conditionals while the other one loops, but core of both of them are relational expressions evaluating either to true or false depending on the data we are providing.

relational expressions

In previous post we discovered mathematical operators and mathematical expressions, yet I forgot to explain the later one, so I will do this right now.
Expressions can be compared to sentences. Expression is a piece of code making sense (at least to the computer) on its own by evaluating to some result, but instead of dot at the end we put semicolon (;). Below are example expressions written in c.

                    
printf("hey\n");

int tehehe;

float pi = 3.14159;

e = x + y / 2;
                    
                

In flow control we can use pretty much any expression as long as it evaluates to ineger number, but the vast majority of the time we will use relational expressions evaluating either to 1 or 0.

While booleans are available in c, they were introduced in C99 and to not break things and make everything backwards compatible, they put them into stdbool library. You can use it if you really want to, but it's not mandatory. C still recognise 0 as false and any other value as true and I will stick to it in this post.

relational operators

Relational operators are pretty straightforward. They are used to compare values and always evaluate either to 0 or 1. Below is the list of them along with usage examples.

  1. == is equality operator
  2. >= is bigger than or equal to operator
  3. <= is lower than or equal to operator
  4. > is bigger than operator
  5. < is lower than operator
  6. != is unequal operator

They work on 2 values called left-hand value and right-hand value comparing them as you can see below.

                    
#include <stdio.h>
    int main(void)
    {
        int x = 10; //left-hand operator
        int y = 5; //right-hand operator
        
        printf("the value of x is %d and the value of y is %d\n", x, y);
        printf("Are x and y equal? %d\n", x == y);
        printf("Are x and y not equal? %d\n", x != y);
        printf("Is x higher than y? %d\n", x > y);
        printf("Is x higher than or equal to y? %d\n", x >= y);
        printf("Is x lower than y? %d\n", x < y);
        printf("Is x lower than or equal to y? %d\n", x <= y);
        
        return 0;
    }
                    
                

Output:

                    
the value of x is 10 and the value of y is 5
Are x and y equal? 0
Are x and y not equal? 1
Is x higher than y? 1
Is x higher than or equal to y? 1
Is x lower than y? 0
Is x lower than or equal to y? 0
Program ended with exit code: 0
                    
                

if

If statement allows us to create programs where execution path is dynamically changed based on the occurring circumstances. Thanks to if statements we can perform certain action only if requirements are met for example turning heating when temperature is below 21°C (sorry american friends) or open the door if the access card has been recognised. The usage is quite simple and looks like this:

                    
if(expression)
{
    //code block here
}
                    
                

In this example, code block will be executed only if expression value is other than 0.


We can create simple program for checking if two values are equal using if.

                    
#include <stdio.h>
int main(void)
{
    int x, y;
    printf("Please provide x value: ");
    scanf("%d", &x);
    printf("Please provide y value: ");
    scanf("%d", &y);

    if(x > y)
    {
        printf("The value of x (%d) is bigger than the value of y (%d).\n", x, y);
    }
    return 0;
}
                    
                

Now if you compile and run this code, you will be prompted to provide 2 numbers, x and y. Then you will receive a message if x is higher than y.


But what if we would like to check whether the x is higher than y OR if x is higher or equal to x?
Theoretically we could do something like this:

                    
#include <stdio.h>
int main(void)
{
    int x, y;
    printf("Please provide x value: ");
    scanf("%d", &x);
    printf("Please provide y value: ");
    scanf("%d", &y);

    if(x > y)
    {
        printf("The value of x (%d) is bigger than the value of y (%d).\n", x, y);
    }
    if(x >= y)
    {
        printf("The value of x (%d) is bigger than or equal to the value of y (%d).\n", x, y);
    }
    return 0;
}
                    
                

At first glance everything is just fine, program compiles without any errors and runs as expected;

                    
Please provide x value: 5
Now please provide y value: 5
The value of x (5) is bigger than or equal to the value of y (5).
Program ended with exit code: 0
                    
                

But then the edge case comes in. If we try to compare two different numbers then we will very likely receive two messages instead of one.

                    
Please provide x value: 11
Now please provide y value: 7
The value of x (11) is bigger than the value of y (7).
The value of x (11) is bigger than or equal to the value of y (7).
Program ended with exit code: 0
                    
                

Now you might ask yourself, if there is better way to do this, and fortunately the answer is yes!

else

Else works like "if if is not triggered, then do this and only this instead;". In contrast to if, else doesn't take any arguments. In fact, its only argument to run is signal that if statement failed and now it's my move


Previous code can be converted to something like this:

                    
#include <stdio.h>
int main(void)
{
    int x, y;
    printf("Please provide x value: ");
    scanf("%d", &x);
    printf("Please provide y value: ");
    scanf("%d", &y);

    if(x > y)
    {
        printf("The value of x (%d) is bigger than the value of y (%d).\n", x, y);
    }
    else
    {
        printf("The value of x (%d) is bigger than or equal to the value of y (%d).\n", x, y);
    }
    return 0;
}
                    
                

Now it seems like it's working

                    
Please provide x value: 5
Now please provide y value: 5
The value of x (5) is bigger than or equal to the value of y (5).
Program ended with exit code: 0
                    
                
                    
Please provide x value: 11
Now please provide y value: 7
The value of x (11) is bigger than the value of y (7).
Program ended with exit code: 0
                    
                

But wait a moment, let's try once again…

                    
Please provide x value: 2
Now please provide y value: 3
The value of x (2) is bigger than or equal to the value of y (3).
Program ended with exit code: 0
                    
                

Now we received only 1 message as intended, yet it's logically wrong, because 2 is not bigger than or equal to 3. It looks like we encountered logical error, but we can solve it as quickly as we created it.

else if

To solve this bug, we have to use else if which in addition to else checks whether the condition has been satisfied. Just copy the first version of the code and add else before 2nd if statement.

                    
#include <stdio.h>
int main(void)
{
    int x, y;
    printf("Please provide x value: ");
    scanf("%d", &x);
    printf("Please provide y value: ");
    scanf("%d", &y);

    if(x > y)
    {
        printf("The value of x (%d) is bigger than the value of y (%d).\n", x, y);
    }
    else if(x >= y)
    {
        printf("The value of x (%d) is bigger than or equal to the value of y (%d).\n", x, y);
    }
    return 0;
}
                    
                

Let's check it now.

                    
Please provide x value: 2
Now please provide y value: 3
Program ended with exit code: 0
                    
                

Now the bug has been solved successfully, however it's still not perfect. It would be nice to add some sort of catch-all statement in case all conditions failed, wouldn't it?
To achieve it we can just add another else statement which this time will be final solution, in case every other conditions failed.

                    
#include <stdio.h>
int main(void)
{
    int x, y;
    printf("Please provide x value: ");
    scanf("%d", &x);
    printf("Please provide y value: ");
    scanf("%d", &y);

    if(x > y)
    {
        printf("The value of x (%d) is bigger than the value of y (%d).\n", x, y);
    }
    else if(x >= y)
    {
        printf("The value of x (%d) is bigger than or equal to the value of y (%d).\n", x, y);
    }
    else
    {
        printf("The value of x (%d) is neither greater, nor equal to the value of y (%d).\n", x, y);
    }
    return 0;
}
                    
                

I think now it's good enough.

                    
Please provide x value: 2
Now please provide y value: 3
The value of x (2) is neither greater, nor equal to the value of y (3).
Program ended with exit code: 0
                    
                

But what if we wanted to add more conditions? Creating some sort of sieve with else-if statements looks tedious and you're absolutely right. This is why switch statement had been created.

switch

Switch is a bit different approach to the decision making. Instead of black and white, true or false, zero or one choice always leading to one from two paths, the switch can read the value and on the fly choose one from many path defined earlier. Here's how it works:

                    
switch(expression)
{
    case expressionResult:
    //code block
    break;
    case differentExpressionResult:
    //code block
    break;
    case anotherExpressionResult:
    //code block
    break;
    ...
}


                    
                

You can add as many different cases as you want as long as they can be result of expression, because creating case which cannot physically happen would be pointless.


Here is how we can create silly program for getting pronouns for each day of the week using switch statement:

                    
#include <stdio.h>
int main(void)
{
    //gather user input
    int weekDay;
    printf("What day of the week is today? (0-6): ");
    scanf("%d", &weekDay);
    weekDay %= 7; //use of modulo to make sure the value of weekDay never overflows in case user provides number higher than 6

    //retrieve and print pronouns based on the day of the week
    switch(weekDay)
    {
        case 0:
            printf("Pronouns of the day are:\n1.xe/xir\n2.ey/em\n3.kit/kitten\nHappy Sunday!\n");
        case 1:
            printf(""Pronouns of the day are:\n1.chir/chirp\n2.fuzz/fuzz\n3.magu/magic\nHappy Monday!\n");
        case 2:
            printf("Pronouns of the day are:\n1.cup/cake\n2.purr/purrself\n3.shell/shells\nHappy Tuesday!\n");
        case 3:
            printf("Pronouns of the day are:\n1.cu/cute\n2.space/ship\n3.dae/daem\nHappy Wednesday!\n");
        case 4:
            printf("Pronouns of the day are:\n1.uni/unicorn\n2.th3y/th3m\n3.sh3/h3r\nHappy Thursday!\n");
        case 5:
            printf("Pronouns of the day are:\n1.foo/bar\n2.oc/ocean\n3.rain/rainbow\nHappy Friday!\n");
        case 6:
            printf("Pronouns of the day are:\n1.h3/h1m\n2.bar/bazz\n3.ang/angel\nHappy Saturday!\n");
    }
    return 0;
}
                    
                

Let's try this now!

                    
What day of the week is today? (0-6): 1
Pronouns of the day are:
1.chir/chirp
2.fuzz/fuzz
3.magu/magic
Happy Monday!
Pronouns of the day are:
1.cup/cake
2.purr/purrself
3.shell/shells
Happy Tuesday!
Pronouns of the day are:
1.cu/cute
2.space/ship
3.dae/daem
Happy Wednesday!
Pronouns of the day are:
1.uni/unicorn
2.th3y/th3m
3.sh3/h3r
Happy Thursday!
Pronouns of the day are:
1.foo/bar
2.oc/ocean
3.rain/rainbow
Happy Friday!
Pronouns of the day are:
1.h3/h1m
2.bar/bazz
3.ang/angel
Happy Saturday!
Program ended with exit code: 0
                    
                

Something is definitely off. Why output is so long?
Ah yes, the break statement!
If we don't use the break; at the end of each case, then our code will "leak" down going through the every single case under the one it started at. You can see this here, where we put 1 and by it we started going through the switch from the Monday (1), while skipping Sunday (0). This is why switches are sometimes tricky, but it's not hard to deal with. We can repair everything just by putting break; at the end of every code block inside each case as below.

                    
#include <stdio.h>
int main(void)
{
    //gather user input
    int weekDay;
    printf("What day of the week is today? (0-6): ");
    scanf("%d", &weekDay);
    weekDay %= 7; //use of modulo to make sure the value of weekDay never overflows in case user provides number higher than 6

    //retrieve and print pronouns based on the day of the week
    switch(weekDay)
    {
        case 0:
            printf("Pronouns of the day are:\n1.xe/xir\n2.ey/em\n3.kit/kitten\nHappy Sunday!\n");
            break;
        case 1:
            printf(""Pronouns of the day are:\n1.chir/chirp\n2.fuzz/fuzz\n3.magu/magic\nHappy Monday!\n");
            break;
        case 2:
            printf("Pronouns of the day are:\n1.cup/cake\n2.purr/purrself\n3.shell/shells\nHappy Tuesday!\n");
            break;
        case 3:
            printf("Pronouns of the day are:\n1.cu/cute\n2.space/ship\n3.dae/daem\nHappy Wednesday!\n");
            break;
        case 4:
            printf("Pronouns of the day are:\n1.uni/unicorn\n2.th3y/th3m\n3.sh3/h3r\nHappy Thursday!\n");
            break;
        case 5:
            printf("Pronouns of the day are:\n1.foo/bar\n2.oc/ocean\n3.rain/rainbow\nHappy Friday!\n");
            break;
        case 6:
            printf("Pronouns of the day are:\n1.h3/h1m\n2.bar/bazz\n3.ang/angel\nHappy Saturday!\n");
            break;
    }
    return 0;
}
                    
                

Now the final output is just as it should be:

                    
What day of the week is today? (0-6): 1
Pronouns of the day are:
1.chir/chirp
2.fuzz/fuzz
3.magu/magic
Happy Monday!
Program ended with exit code: 0
                    
                

Noticed the modulo operation on weekDay at the beginning of the program?

                    
weekDay %= 7;
                    
                

Thanks to it, our program works even though user inputted number other than expected.

                    
What day of the week is today? (0-6): 42
Pronouns of the day are:
1.xe/xir
2.ey/em
3.kit/kitten
Happy Sunday!
Program ended with exit code: 0
                    
                

As shown above, even if you put 42 as a week of the day, program keeps going without any issues. The number 42 got divided by 7 which resulted in 0, because 42 is perfectly dividable by 7, so expression evaluated to 0 turning 42 into Sunday.

exercise

The conditional statements open whole new level of possibilities in terms of what program can do. Let's use it and create something funny, amusing or interesting.
Everything is up to you.

summary

When I started writing this post I had completely different vision for it, but as it is with many things in life, often it's better to go with the flow and dive into undiscovered.
I wanted to thank everyone who helps me in the process and read this series, because you are my reason to keep it going and keep writing every day.
Also because we are near christmas time and new year eve, I wanted to wish everyone good sleep, warm blanket and quality time with people you like.
Honestly at this point I don't know when next post will be published, but hopefully I will find some time to write it before the end of 2023.

Have a nice day or night and stay hydrated.
Warmly,
Laura