Chapter 5. Conditionals

Conditionals are statements which execute a statement or series of statements depending on if a condition or predicate is true. This chapter will cover if-else statements, while loops, until loops, do-while loops, for loops, and foreach loops.

5.0.1 Function - input

In order to test our conditional functions, it is advantageous to get keyboard input from the user of the program. This will require the use of a global function called input. The function requires 0 arguments. When input is called, it blocks program execution until keyboard input is given, terminated by the enter key. The function returns the input back as a string.

To test the input function, use the following program.

func main () {
    print ("Enter some input, then press enter: ");
    string entered = input ();
    printf ("You entered {0}\n", entered);
}

5.1 - if else Statements

The most basic way to control program flow is with the if-else conditional statements. If the condition is true, the if body will be executed. If the value was false, an optional else body can be executed.

To exhibit the functionality of if statements, let's create a program that prompts the user for a password. If the password is 123456 (correct), the program will display Password Accepted.

func main () {
    print ("Enter the password: ");
    string pass = input ();
    if (pass == "123456") {
        println ("Password Accepted!");
    }

The first two lines should make sense. A message is displayed to the user followed by the prompt for input. The third line of main starts the if statement. The expression inside of the parentheses is the condition that the statement operates on. In this program, the condition is the binary operation ==. It compares the the variable with the user input to the string 123456. If they are equal, it will display Password Accepted!, otherwise the program will do nothing.

As the name suggests, if statements can also have an else component. This is the part of the statement that will execute only if the condition returned false. For our password example, we might want to add an else component to tell the user that the password they entered was incorrect. Let's add this to the code example.

func main () {
    print ("Enter the password: ");
    string pass = input ();
    if (pass == "123456") {
        println ("Password Accepted!");
    } else {
        println ("Password was Incorrect!");
    }
}

Run this program a few times. If you give the input 123456, the program will output Password Accepted!. Any input other than 123456 will produce the output Password was Incorrect!.

5.1.1 Statement - else if

The code example we used in 5.1 uses a simple true or false switch. Either the true statement will execute or the false statement will execute. But what if you wanted to test multiple conditions? To do this, you can chain if statements together using an else if. This allows you to test multiple conditions and still have a final else component.

For example, say you wanted to create a program that asked for a number between 1 and 6, displaying a, b, c, d, e, or f based on the number. You would use an if statement to test for 1, then else if components for the rest of the numbers. The final else will execute if none of the conditions are met, telling you that the number was not between 1 and 6.

func main () {
    print ("Enter a number between 1 and 6: ");
    string num = input ();
    if (num == "1") {
        println ("a");
    } else if (num == "2") {
        println ("b");
    } else if (num == "3") {
        println ("c");
    } else if (num == "4") {
        println ("d");
    } else if (num == "5") {
        println ("e");
    } else if (num == "6") {
        println ("f");
    } else {
        printf ("{0} is not a number between 1 and 6!\n", num);
    }
}

5.1.2 Chaining Conditions

5.1 and 5.1.1 showed conditionals that operate based on a single condition. You can chain conditions together using the && logical and, as well as the || logical or operator. The logical and operator is a binary operator that returns true only if the condition on the left is true AND the condition on the right is true. The logical or operator is a binary operator that returns true if either or both conditions on the left and right are true.

func main () {
    if (true && true) {
        println ("1");
    }
    if (true && false) {
        println ("2");
    }
    if (true || true) {
        println ("3");
    }
    if (true || false) {
        println (4);
    }
    if (false || false) {
        println (5);
    }
}

Output:

1
3
4

5.2 - while Loops

Sometimes you may have a section of code that you would like to have repeated. This could be because it needs to be ran a certain amount of times, until a condition is met, or infinitely.

A simple example of what loops can do would be iterating over a series of numbers. This means displaying all the numbers between a start and an end. Here is an example of a while loop that displays all the numbers from 0 to 10.

func main () {
    int num = 0;
    while (num <= 10) {
        println (num++);
    }
    println ("All done.");
}

Output:

0
1
2
3
4
5
6
7
8
9
10
All done.

The code starts by setting the local variable num to 0. This is the variable that will hold the numbers we iterate over. The next line begins the while loop. The condition for the while loop is that num <= 10. Since num starts as 0, 0 is less than 10, so this returns true and the code executes. The code body prints the number, then increments num. This will keep going until num is 11, where the condition will be false and the loop will terminate.

5.3 - until Loops

The inverse of a while loop is an until loop. An until loop works the same way as a while loop, except it executes when a condition is false. This is the same as doing while (!<expression>). The reason until loops exist is to make certain loops easier to understand.

Here is the counter program rewritten using an until loop.

func main () {
    int num = 0;
    until (num > 10) {
        println (num++);
    }
    println ("All done.");
}

The until loop in this program keeps executing UNTIL the variable num is greater than 10.

5.4 - do while Loops

Another style of while loop is the do while loop. Unlike any other loop, it will execute the body once, then start checking the condition and looping. This ensures that the body of the loop will execute at least once.

To test out this anomaly, run the following program.

func main () {
    do {
        println ("Running.");
    } while (false);
}

Output:

Running.

Normally if this were a vanilla while loop, this code would never execute, since the condition would always be false. But because this is a do while loop, the body will be ran once, printing out Running. then exit.

5.5 - for Loops

A for loop is a loop that allows you to run a statement once, then execute a body and a repeating statement while a condition is true. This is often used for iterator loops, since the initial statement can be the declaration of a counter variable, the repeat statement can increment that variable, and the condition can check that variable against an upper bound.

Consider the iterative code in 5.2. There is the line that declares the variable num, a while loop to check the value of num, and the expression num++ in the body to increment it. This can be written much more concise and clear using a for loop.

func main () {
    for (int i = 0; i <= 10; i++) {
        println (i);
    }
    println ("All done.");
}

Output:

0
1
2
3
4
5
6
7
8
9
10
All done.

Inside the for loop, the first statement declares the variable i (i is often used as an iterator). This is the initial statement as it only needs to be done once. After the semicolon is the condition i <= 10. This means that our for loop need only execute until i is equal to or greater than 10. After the condition is the repeat statement, which executes AFTER the loop body runs.

5.6 foreach Loops

The foreach loop is used to iterate over an iterable object (object which implements the __iter__ method and can be turned into a list) to cycle through the elements in a list (see Chapter 4 for coverage of lists).

Using the foreach approach instead of a for loop can be a cleaner and faster alternative. The syntax for foreach is foreach (<var> in <iterable>) <body>. Let's create a program which iterates through a list of names and displays them to the terminal.

func main () { 
    list names = [ "John", "Jamie", "George", "Cameron", "Jackie" ];
    foreach (name in names) {
        printf ("Name: {0}\n", name);
    }
    println ("All done.");
}

Output:

Name: John
Name: Jamie
Name: George
Name: Cameron
Name: Jackie
All done.

When the foreach loop executes, it goes through each element in the given list, assigning that value to the variable names and executes the body.

5.7 More with loops

This section will just cover some more in depth topics about the power of looping in Hassium.

5.7.1 Loop Trick - Infinite Loops

Some loops can execute forever. This is called an infinite loop. For a loop to be a truly infinite loop, the condition must always return true no matter what. This can be a comparison of constants such as while (1 == 1) or much simpler, while (true).

Try running this code:

func main () { 
    int a = 0;
    while (true) {
        println (a++);
    }
}

This will output every number from 0 to 2,147,483,647, the maximum value a Hassium integer can hold.

5.7.2 Loops - break

By default, loops exit when their condition is met. But a loop can also exit prematurely using the break statement. This can be used for special cases when a loop should be aborted or for leaving infinite loops.

Test out the break function with the following code.

func main () {
    int num = 0;
    while (true) {
        println (++num);
        if (num == 6) {
            break;
        }
    }
    println ("All done.");
}

Output:

0
1
2
3
4
5
6
All done.

Inside of the while (true) body there is an if statement checking if the number has reached 6. If it has, the break statement is ran, and the loop terminates.

5.7.3 Loops - continue

In looping, the continue statement can be used to skip over the body of the loop, but still keep looping. This can be used for special conditions inside iterative loops.

Take the following example of a loop that counts from -5 to 5, dividing the number 10 by that number.

func main () {
    for (int i = -5; i <= 5; i++) {
        println (10 / i);
    }
}

Output:

-2
-2.5
-3.33333333333333
-5
-10
▒
10
5
3.33333333333333
2.5
2

The number in the middle space between -10 and 10 is a null, this is because Hassium tried to divide the number 10 by 0, which is an impossible operation. To work around this we can test if i is 0, and if so, skip it.

func main () {
    for (int i = -5; i <= 5; i++) {
        if (i == 0) {
            continue;
        }
        println (10 / i);
    }
}

Output:

-2
-2.5
-3.33333333333333
-5
-10
10
5
3.33333333333333
2.5
2

When the variable i was 0, Hassium skipped over the body of the loop and kept going.

5.8 - The Switch Statement

The switch statement is a way of chaining if and else statements together. An initial value is given, and that value is checked against each case inside of the switch statement. If the values are equal, the body of the case statement will execute. If no case statements execute, the default case will execute.

Let's write a program that accepts input from the user for a switch statement. Depending on the number entered, a different letter will output.

func main () {
    print ("Enter a number between 1 and 6: ");
    string num = input ();

    switch (num) {
        case "1" {
            println ("a");
        }
        case "2" {
            println ("b");
        }
        case "3" {
            println ("c");
        }
    }
}

5.9 - The Ternary Operator

Unlike the unary operators which have one operand and the binary operators that have two operands, the ternary operator has three operands. The ternary operator (represented as ?:) is similar to an if statement in practice. The first operand is a conditional expression. If this expression evaluates to true, the value second operand will be used, otherwise the value of the third operand will be used. The syntax of the ternary operator is <expression> ? <expression1> : <expression2>.

Let's write a program to test out this unique operator.

func main () {
    printf ("Enter the secret phrase: ");
    string response = input () == "123456" ? "Correct login!" : "Incorrect!";
    println (response);
}

Sample run 1:

Enter the secret phrase: 123456
Correct login!

Sample run 2:

Enter the secret phrase: something else
Incorrect!

Chapter 5 - Exercises

Exercise 5.1

Write a for loop that displays the numbers from 100 to 0.

Exercise 5.2

Create an infinite loop that displays a prompt >, takes in keyboard input, and displays it back to the user. The loop should terminate when the user enters STOP.

Sample run:

> apple
apple
> banana
banana
> STOP

results matching ""

    No results matching ""