Back To Basics - Part 5

Getting less basic by the month, Mark 'Maestro' Moxon takes us through a couple of control structures that will prove fundamental to your programming skills

If you've made it this far, you're in control. Seriously: give it a couple of months, and you'll be able to understand 90 per cent of the programs you see. And you'll be able to criticise them. And make loads of new friends with your new-found knowledge. That's a promise.

On the other hand, there's plenty to learn, like all the other control statements I hinted at last month. On with the show, maestro ...

A Case Study

After last month's foray into the exciting yet educational world of the IF-THEN construct, it's time to move on to the next stage: the CASE-ENDCASE construct. Time for a practical example? I think so.

Imagine we wanted to write a program which presented a number of mathematical problems, based around the four rules of arithmetic. When the program is run, it asks which rule we want to test, be it addition, subtraction, multiplication or division; the program asks a specific question, using the specified rule.

This program could be implemented using IF-THEN statements, but it would be a little clumsy, so what we need is CASE-ENDCASE. Before I explain how it works, have a look at Listing1.

Listing 1

REM >Listing1
:
ON ERROR REPORT:PRINT " at line ";ERL/10:END
MODE 0
:
PRINT "Which rule do you want to test?"
PRINT "   (A)ddition"
PRINT "   (S)ubtraction"
PRINT "   (M)ultiplication"
PRINT "   (D)ivision"
INPUT "Please enter A,S,M or D: "rule$
:
CASE rule$ OF
  WHEN "A"
    A=RND(10):B=RND(10)
    PRINT "What is ";A;" + ";B;" ";
    INPUT result
    IF result=A+B THEN PRINT "Correct" ELSE PRINT "Wrong"
  WHEN "S"
    A=RND(10):B=RND(10)
    PRINT "What is ";A;" - ";B;" ";
    INPUT result
    IF result=A-B THEN PRINT "Correct" ELSE PRINT "Wrong"
  WHEN "M"
    A=RND(10):B=RND(10)
    PRINT "What is ";A;" x ";B;" ";
    INPUT result
    IF result=A*B THEN PRINT "Correct" ELSE PRINT "Wrong"
  WHEN "D"
    B=RND(10):A=B*RND(10)
    PRINT "What is ";A;" / ";B;" ";
    INPUT result
    IF result=A/B THEN PRINT "Correct" ELSE PRINT "Wrong"
  OTHERWISE
    PRINT "Sorry, I don't know that rule."
ENDCASE
END

First of all, have a look at the way the CASE statement is constructed. The first line of it is in the form:

CASE <variable> OF

where the variable in this case is the letter we've entered: one of A, S, M or D. The next set of lines is in groups, each starting with a line like:

WHEN <match>:

Effectively, what happens is that the program searches through these WHEN statements, one after the other, until the variable in the CASE line matches the match in the WHEN line. When a match is found, the lines after the WHEN are executed (up until the next WHEN). If no match is found, then the lines after the OTHERWISE line are executed.

So, how does this work in our example? First, the program asks which rule we should be testing, and the user enters the relevant letter into the variable rule$. Now we start our CASE check, which does one of the following:

The ENDCASE line simply marks the end of the construct: this is how we know where to continue execution after one of the WHEN or OTHERWISE branches has been executed.

Mean-While

The next control statements you'll find useful are WHILE-ENDWHILE and REPEAT-UNTIL, which are closely linked. As the names suggest, these allow you to repeat sections of your programs again and again, dependent on certain conditions which you specify.

Let's have a look at WHILE-ENDWHILE first by considering Listing 2; this simple-looking program implements a very basic password protection system. Let's see how it works.

Listing 2

REM >Listing2
:
ON ERROR REPORT:PRINT " at line ";ERL/10:END
MODE 0
:
INPUT "What is your password? " pword$
WHILE pword$<>"AU"
  PRINT "Access denied."
  INPUT "Please re-enter your password " pword$
ENDWHILE
PRINT "Password accepted"
END

First, we get the password into pword$ in line 6. The construct between lines 7 and 10 executes in very much the same way as it reads: 'while the password is not "AU", print Access denied, get another password, and go back to check the password again.' The tricky part is looping back: this is what ENDWHILE does.

If the condition in line 7 is not met - in other words, the password entered is in fact correct - then none of the lines between the WHILE and ENDWHILE are executed, so if the correct password is entered, the program simply prints that the password is accepted, and it terminates. Otherwise the program goes round and round until the correct password - AU - is entered.

Do note that in this particular example, pressing ESCAPE will terminate the program; if we wanted to prevent this, we could simply change line 3 to ON ERROR RUN, which would mean that if an error occurred (such as the user pressing ESCAPE) the program would be re-run. Try the change, but make sure you've saved all your desktop files first, just in case you make a typing error.

The second construct is REPEAT-UNTIL. Look at Listing 3.

Listing 3

REM >Listing3
:
ON ERROR REPORT:PRINT " at line ";ERL/10:END
MODE 0
:
count%=0
REPEAT
  count%=count%+1
  INPUT "What is your password? " pword$
UNTIL pword$="AU" OR count%=3
IF count%=3 PRINT "Access denied" ELSE PRINT "Password accepted"
END

This reads set count% to zero. Now repeat the following - increment count% by one, and ask for password - until the correct password is entered, or count% equals three. If count% is three, deny access, otherwise accept the password.

This is the common 'three goes or you're logged off' approach. The variable count% logs how many attempts the user has had: if it reaches three (as checked in line 10), access is denied. In either case the condition in line 10 is satisfied, so the REPEAT-UNTIL loop is terminated.

I'll see you next month for the formidable FOR-NEXT loop.


Source: Acorn User 137 - December 1993
Publication: Acorn User
Contributor: Mark Moxon