<< Prev Next >>
Code flow
Until now, our code executed from first line to last line passing through all lines. Sometimes we don't want this, as we want to perform some operations only if certain conditions are met. For this, we have control flow instructions, which will allow us to execute or not blocks of code based on certain conditions.
The most simple control flow instruction is if
- Code: Select all
if (expression1)
{
// Code executed if expression1 is true
}
else if (expression2)
{
// Code executed if expression1 is false and expression2 is true
}
else
{
// Code executed if all previous expressions are false
}
The switch control flow instruction allows more readable ifs. It's usually used when comparing a variable value with a set of predefined values:
- Code: Select all
switch(variable)
{
case value1:
// Code executed if variable == value1
break;
case value2:
// Code executed if variable == value2
break;
default:
// Code executed if none of the previous cases was executed
}
The use of break reserved word is to exit the switch() statement. If break is omitted, the execution will enter next case and execute its code as well. This can be interesting to use in very few cases, but breaks code readability so bad I don't recommend it.
The while loop is a loop control flow statement. This means the block of code enclosed between the while braces could execute more than once. This is very useful when we want to do an operation several times until a condition is fulfilled.
- Code: Select all
while(expression)
{
// This code will be executed as long as expression is true
}
In this case, the code inside the while has to modify somehow the evaluation of the expression (I'm not considering multi-threading or process inter-communication here). Otherwise you will get what's known as an infinite loop. This is when the loop is badly written and the loop never ends (the expression is always true). Also please note that if expression is false before entering the loop, the code inside the while will not be executed. Also keep this in mind if a program you wrote hangs: it could probably be because of an infinite loop!
Another way of writing a while loop is
- Code: Select all
do
{
// This code will be execute at least once
} while(expression);
This will execute the code inside the do-while loop at least once. This is because the expression is evaluated after the execution of the code inside and not before like in the normal while.
Another very used loop construct is the for loop. You can think of this as a special while loop where you do some stuff automatized, so you don't have to include extra code inside the loop
- Code: Select all
for(expression1; expression2; expression3)
{
// This code will execute as long as expression2 is true
}
expression1 is executed only once before the loop begins. expression2 is evaluated after each loop (think of it as the equivalent of while(expression)). expression3 is executed after each loop as well. Usually expression1 is used as an initialization. expression2 controls the end of the loop. expression3 is usually used as an increment operation.
The for loop suits better when we know we're going to loop a code a fixed number of times. For example, to calculate the average of an array of numbers, we can use a for loop:
- Code: Select all
#include <stdio.h>
// Pre-processor directive: defines
#define ARRAY_SIZE 8
int main()
{
int array[ARRAY_SIZE] = {2, 5, 9, 10, 45, 5, 1, 3};
int total = 0;
// We sum all the numbers on the array
int i;
for (i = 0; i < ARRAY_SIZE; i++)
{
total += array[i];
}
// We calculate the average value of the array and print it
float average = (float) total / (float) ARRAY_SIZE;
printf("The average of the array is %f\n", average);
return 0;
}
This is a typical usage of for loop. Note the usage of i as a counter. This is somehow standard: you use i, j, k, h... for indexes and/or counters.
The #define preprocessor directive allows us to use symbols instead of literals. This is NOT processed by the compiler, this is not real code. What the preprocessor actually does is replace all instances of the ARRAY_SIZE symbol by its value (8) before the file is passed to the compiler. This allows us fast modification of this value if needed, since we only have to modify the #define and not all occurences of the number 8.
So now some exercises to practice this new stuff
For all exercises:
- It's not allowed to use any external library to do the main task of the exercise (string.h is forbidden!
). - Use the #define directive instead of using literals.
- Write a program that given an array of 10 numbers, prints only the even numbers.
- Write a program that given an array of 10 numbers, prints only the odd positions.
- Write a program that given an array of 10 numbers, prints only the 2 first multiple of 3 numbers.
- Write a program that given one string, prints its length.
- Write a program that given 2 ASCII stings as an input, checks if they are exactly equal.
- Write a program that checks if one string is part of another (if it's a substring).
- Write a program that given an array of 10 numbers, it orders it ascendantly.
- Write a program that given 2 ASCII stings as an input, checks if they are exactly equal, but case-insensitive (that is, given "hello" and "HeLLo", it should say they are equal) This one could be a bit tricky
- Write a program that given two matrices float a[3][3] and float b[3][3], adds them.
Have fun and good luck!
<< Prev Next >>


