Blog

Relearning MSX #29: Conditional statements in MSX-C

Posted by in How-to, MSX, Retro, Technology | October 08, 2015

We’ve seen already how to read from the keyboard, perform some basic operations, and print results on the screen. This may be enough for a few very especific situations, but even the simplest programs will at some point need to take decisions based on the value of a certain variable. This is where conditional statements come in.

The smallest component of a program: statements

Before I explain conditional statements we need to understand what a statement is. To put it simply, a statement in C is a piece of code that performs an operation. So far we’ve seen two types of statements:

  • Assignment statements (assigning a value to a variable):
    i = 1234;
    c = 'a';
    c = getch();
    
    
  • Calls to functions (performing an operation by calling a single function):
    putchar('a');
    puts("abc");
    
    

Note something very important: all of these end in a semicolon (;). While not technically correct, we could think of the semicolon as part of the statement.

These two types of statements are essential. We can’t write useful programs without them. However, they are not enough. We can’t code useful programs with just these two either. We need something else: conditional statements and loops.

Taking decisions: the if statement

In C, the most commonly used statement for taking decision is the if statement. It’s written in this form:

if (condition) statement

The meaning of this piece of code is: “if condition is true, then execute statement“. This is very similar to the IF statement in MSX-BASIC, but note that in C the keyword THEN doesn’t appear. Also, the condition must always be written inside parentheses.

The following example program reads a key press from the keyboard, and prints a text message if the character pressed is higher or equal to ‘s’:

IF.C (Click to enlarge)

IF.C (Click to enlarge)

As you can see in the program above, the statement following the if doesn’t have to be in the same line (as was the case in MSX-BASIC). In fact, most of the time we will place the statement in the following line and indented a few spaces to make it clear that the code depends on the if . There are many indent styles, and which one you use is up to you. I’m using the K&R style with 8-space indents.

The C if statement also accepts a second statement that will run if the condition isn’t met. In this case we write it in this form:

if (condition) statement1 else statement2

This code can be read as “if condition is true then execute statement1, and execute statement2 otherwise”. We can modify the previous program to illustrate this behaviour:

IFELSE.C (Click to enlarge)

IFELSE.C (Click to enlarge)

Notice that we put the else at the same level as the if it is part of and indent the statements that depend on these. This makes the program easier to read.

The whole if or if/else counts as a single statement, so we can put an if after another in order to check on more than one condition:

IFIF.C (Click to enlarge)

IFIF.C (Click to enlarge)

In the example above, the puts() statement will only run if both conditions are true:

  • The first if checks that the character read from the keyboard is higher than or equal to ‘1’. If it is, then the second if runs.
  • The second if checks that the character is equal to or lower than ‘5’. If it is then the puts() runs.

In situations like this we say that the second if is nested. When nesting if/else statements be aware that an else is always part of the if that immediately precedes it:

IFIFELSE.C (Click to enlarge)

IFIFELSE.C (Click to enlarge)

Grouping statements: compound statements

We’ve seen that using if/else we can run a statement or another depending on a condition. But what if we need to run more than one statement? In this case we have to group them in a group. In C we use the bracket characters ‘{‘ and ‘}’ for this purpose. Everything inside a pair of brackets will count as a single statement. We call these compound statements and the generic form to write them is like this:

{ statement1 statement2 statement3 }

Note that there’s no need to add a semicolon to mark the end of the compound statement. The closing bracket is enough for the compiler to know when the block ends.

Let’s see an example program that uses a compound statement:

BLOCK.C (Click to enlarge)

BLOCK.C (Click to enlarge)

The program above waits for the user to press a key, and if the character is equal to or higher than ‘s’ it runs the three statements in the block after the if. The whole block counts as a single compound statement that runs in order everything between the braces. This way of writing code is technically correct, but it’s difficult to read. We can rearrange the block by putting the opening brace immediately after the if, moving each statement into its own line, and then placing the closing brace one line below at the same indent as the if:

BLOCK2.C (Click to enlarge)

BLOCK2.C (Click to enlarge)

This version of the program works in exactly the same way as the previous one, but it’s easier to read and see the three operations that happen if the condition is true. This is the style I will be using in my programs, but feel free to use whichever format feels more natural to you.

In the case of an if/else this works in exactly the same way:

An if/else statement with two blocks. (Click to enlarge)

An if/else statement with two blocks. (Click to enlarge)

Comparing data: comparison operators

If you’ve been paying attention you may have noticed a couple of new operators in the programs above: “>=” and “<=”. We use these to compare two numeric values. C has several of these comparison operators, some of them similar to those in MSX-BASIC. Here’s the whole list:

Comparison operators in C

Comparison operators in C

Most of these are self explanatory, but the equality comparison operator deserves some explanation because it’s always a source of confusion for programmers who come from BASIC. As you probably know, when we want to compare two values in BASIC we use one equal sign:

IF X=Y THEN ...

BASIC also uses the equal sign to assign a value to a variable:

X=Y

This isn’t a problem in BASIC because the interpreter can always tell what we’re trying to do based on the context. This is not the case with C. In C, = is always the assignment operator, and == is always the comparison operator. Yes, this also means that in C we can assign a value to a variable inside a comparison expression (we’ll see how this works in the next post).

The following program illustrates this common mistake:

This program contains a bug that's very common (Click to enlarge)

This program contains a bug that’s very common (Click to enlarge)

The program above is intended to get a character from the keyboard and print “Yes” on the screen only if the character was ‘y’. However, what actually happens is that it always prints “Yes” no matter what key we press. The reason is that the expression inside the parentheses after the if isn’t comparing anything, but it’s assigning ‘y’ to the variable c. The expression has to be rewritten to use == instead of =:

The same program as before, after fixing the bug (Click to enlarge)

The same program as before, after fixing the bug (Click to enlarge)

If you write a program that isn’t working as expected, check your comparison operators. This is a common mistake, and it’s not always easy to spot.

Summary

In this post we’ve learnt about statements. We’ve seen how to make our programs behave in different ways depending on the result of a comparison using if/else, and we’ve seen a list of the comparison operators available. We’ve also learnt about compound statements.

In the next post…

In the next post we’ll see the result of conditions in more detail: what the C compiler handles as true and false, and how we can perform more complex comparisons.


This series of articles is supported by your donations. If you’re willing and able to donate, please visit the link below to register a small pledge. Every little amount helps.

Javi Lavandeira’s Patreon page

Leave a Reply

Your email address will not be published. Required fields are marked *