If you have a Pascalite, or the software emulation, then there's a separate tutorial for you, covering much of the ground as presented here for the FPC/ TP crowd.
The Pascalite, while having a more limited version of the language, is blessed with some special hardware advantages. A few of the tutorials at the start of the series depend quite heavily on those features. When you read the rest of this tutorial, you may notice where things got a bit strained as I tried to cover the same ground in a FPC/ TP environment. Sorry! Still worth what you're paying?
Although this tutorial starts weakly, it actually ends more strongly than the tutorial it derives from. Swings and roundabouts. Life.
Enter the following, or create it from the program created during the previous tutorial. It is very nearly the same code. I've changed the program name, added the lines at //**1 and //**2, and slightly changed the line at //**3. And yes, this code could be improved, and yes, the changes are trivial in effect. They do show you something new, though, which also has non-trivial uses!
program Fourth; uses crt; var sItWas, sLatest:string; iCount:integer; boMatch:boolean; //** 1 begin ClrScr; iCount:=0; writeln('Type a short word, then press the "Enter" key.'); writeln('This will set the password to be matched later.'); readln(sItWas); ClrScr; repeat iCount:=iCount+1; writeln('You have gone through the loop ',iCount,' times.'); writeln('Type the password again to leave this loop, or'); writeln('type something else. In either case, then'); writeln('press the "Enter" key'); readln(sLatest); if sLatest=sItWas then boMatch:=true //no ; here else boMatch:=false; //** 2 if sLatest=sItWas then writeln('Bye') //no ; here else writeln('No, that was not the password.'); writeln;//this causes a blank line. until (boMatch) or (iCount>5);//** 3 writeln('Press the "Enter" key to end the program.'); readln; end.
First a simple matter: The variable names. You could call them Dick and Jane. But it is better to use names that mean something. The "bo" prefix doesn't MAKE the variables Boolean... the var statement does that... but if you use such variable name prefixes, it will help you remember what the variables are being used for. I normally prefix variables of type string with an s which is why, in the previous program, I used sItIs and sItWas as the names.
Let's look at the additions and the change....
//** 1: This creates, "declares", the boolean variable we're going to use. Always declare a variable before you use it.
//** 2: This new "if... then... else..." statement assigns a value to boMatch, depending on what is on sLatest and sItWas. If the contents of those variables match, then boMatch is true after this statement has executed. See how sensible variable names make your code easy to follow? Choose your variable names accordingly.
In a previous tutorial, we said that it is important to initialize variables. You may have wondered why there wasn't a "boMatch:=true;" (or maybe ":=false") before the repeat loop. Look at the code. boMatch will always have something put into it during line //**2's execution. And we never try to consult what is in boMatch until line //** has executed at least once. boMatch is initialized the first time we pass through //**2, and that is soon enough.
//** 3: In this line, we've replaced the condition "sLatest=sItWas" with "boMatch". It is, as you may realize, a very trivial replacement. But is all this clear to novices in my readership? When the program comes across "sLatest=sItWas", the computer goes off and "looks" at what's in sLatest, and what's in sItWas, and compares them, in the place of condition, one is left with the equivalent of a "true" or of a "false". A programming text might (quite properly) say that "sLatest=sItWas" returns a Boolean value, with something drawn from the list of possible values for a Boolean type datum, i.e. "true" or "false".
The idea of "boiling things down", of something "returning" something is important. It lets you look at a program at different levels. Sometimes you need to concentrate on detail; sometimes on the broader picture. In the program above, sometimes you need to look at the detail of what makes boMatch true or false. You do that by looking in the if... then... else... statement. At other times, you're more worried about what happens when there was a match, as in the line "until (boMatch) or..."
The relatively trivial move of the test of "if sLatest=sItWas", and the storing of the result in boMatch, is one of those things that arose from making this tutorial derive nicely from the older Pascalite tutorial. But the code is perfectly valid, perfectly correct... and not unlike something that you might encounter in other, less trivial, circumstances. We'll come back to this later.
That takes care of a lot of things. Now to address a few loose ends. In general, it is best to read these tutorials with your browser not filling your screen, and adjusted to make a comfortably narrow column of text. You may need to widen it a bit to see all of every line of the code which is coming up.
Surely you thought that....
if sLatest=sItWas then boMatch:=true //no ; here else boMatch:=false; if sLatest=sItWas then writeln('Bye') //no ; here else writeln('No, that was not the password.');
was dreadfully messy? You were right! And Pascal code doesn't need to be, and shouldn't be, messy. In an earlier tutorial, we talked a little about nested "begin... end" blocks.
An "if... then ... else... " statement, as used to date, needs "things" plugged in where I've put "...". The first "thing", as you know, must be a condition, something that returns, boils down to, "true" or "false".
After the "then" and after the "else" we have, to date, put simple statements, e.g. "boMatch:=true"
If you "wrap" several simple statements up in a "begin... end" block, they become, effectively, "one" statement. They "boil down to" "one" statement. (That "boil down to idea again!)
When you "wrap" statements together thus, you put a semicolon between each. I think of it as "glue". This is just a continuation of the general use of the semicolon at other levels of the program's editing. Note: "if... then... else" is ONE, SIMPLE statement. That's why there are no semicolons in it, say just before the else, which is a tempting place to put one.
The following is equivalent to what we had before, and a form you will come to see as neater. I would guess it looks neater to you even now when it is unfamiliar?
if sLatest=sItWas then begin boMatch:=true; writeln('Bye');//**1 end;//no ; here //**2 else begin boMatch:=false; writeln('No, that was not the password.');//**3 end;//else **4
(I've exaggerated the indenting, to make my point.)
We still have "if... then... else...". Look at the code carefully; be sure that you see that.
The "//no ; here" that I've put on line //**2 is something that I routinely put in my code. If in doubt, put semicolons in... they often do no harm, but a semicolon before an else is always bad news.
Strictly speaking, you don't need the semicolons at //**2 and //**3, but I would put them in.
You don't need them, because they would be to "glue" another simple statement into the compound statement between the "begin" and "end". The word "end" tells the compiler that the "begin... end" block ends here. A semicolon after the last statement before the "end" simply "glues" a "do nothing" statement onto the compound statement between the "begin" and "end".
I would put those semicolons in, because it is quite common to go back and add other things to the compound statement, and if you didn't put the semicolon in when you wrote what was there before, you may well fail to do so when you add the new line.
Moving on with "begin... end": Be very careful that every "begin" is matched by an "end".
Once you start using the "begin... end" "trick" to make a number of simple statements behave as one statement (it's called a compound statement), be careful to remember the "begin" and "end" around the simple statements. It is quite easy to write the following when you meant the code most recently presented....
if sLatest=sItWas then begin boMatch:=true; writeln('Bye'); end;//no ; here else boMatch:=false; writeln('No, that was not the password.');
The "then" part is unchanged, but look at what is supposed to happen in the "else" situation.
Set out like that, the error is fairly easy to see... another reason for setting things out like that... but I assure you: You will sometime spend a few hours tracking down a mistake like that. Like what? I'm going to explain...
With the faulty code, instead of the "writeln('No, that was not the password.');" happening only when sLatest does not equal sItWas, it will happen every time. It has become the first statement after the "if... then... else..." The "..." part for the "else" is now simply "boMatch:=false;"
Trust me: Be careful with your "begin... end" pairs.
Moving on again: One way to help yourself avoid errors is, when entering code, to type both the "begin" and the "end", and then go back and fill in what they are "gluing" into a single compound statement.
I.e., I would have entered the code you see above in the following steps....
if sLatest=sItWas then begin end;//no ; here else begin end;//else
... followed by....
if sLatest=sItWas then begin boMatch:=true; writeln('Bye'); end;//no ; here else begin end;//else
... and then I would have entered the stuff between the "else"s "begin... end".
Take a deep breath. Make sure you're clear on the above. I'm about to go on to a related topic.
You've already seen something rather like the "begin... end" block. I'll leave a big vertical blank space so you can think "What could that be?" before seeing the answer.
... answer further down page...
... answer further down page...
Answer: The "repeat... until" block is like the "begin.. end" block, in that it can "glues" a bunch of stuff together into a "single" "thing".
The "repeat... until" block is slightly "fancier" that the "begin... end" block. (You may go through the block more than once, which you won't do with a "begin... end" unless there is something outside of it causing the repetition.) However, just like "begin... end", the words "repeat... until" will have one or more statements between them. (A "begin... end" block with only one simple statement in it would be pointless.... but it would work.) If there is more than one simple statement in the block, there should be a semicolon between each of them. Thus, strictly speaking, one could say that either type of block has "one statement" in it... either a simple statement, or a compound statement (simple statements "glued" together with semicolons). That bit of cleverness is not mere academic pedantry. You should try to see your program's structure in these terms.
And now for something completely different!
In the program we've been discussing, the boMatch variable is pretty superfluous. It could be written out with no loss of clarity.
However, what we did does sometimes have its uses, particularly in more complex programs.
Imagine a program not unlike our example program. A sketch of the important bits is as follows. N.B. What follows is not complete code, it would never run....
repeat boMatch:=false; if (first complicated possibility) then boMatch:true; if (second complicated possibility) then boMatch:true; if (third complicated possibility) then boMatch:true; if (fourth complicated possibility) then boMatch:true; until boMatch;
... and that's the simplified code! You will get loops (and other structures) with all sorts of things going on within them, with all sorts of ways for the time to leave the loop to arise. What we've done above is useful: Set "boMatch" false, to begin with, knowing that it can always be made true anywhere below the initialization, and thus trigger an exit from the loop, if the time has come, however arcane the indication thereof, to do so.
Moving on again...
This is a "scrap" that doesn't fit the FPC/ TP tutorial very well, but it was covering in the Pascalite tutorials at this point, so I'm shoehorning it in here, so you'll be ready for subsequent things.
Forget the program we've been discussing. Consider a program about the weather with three boolean variables: boCold, boRaining, and boSnowing.
Starting with the very, very easy:
if boCold then writeln('Put a coat on.');
Easy? Yes. But note two things: You don't have to say "if boCold=true...". If boCold is holding "true", then "boCold=true" boils down to "true", so it would work. But "boCold" on it's own, when the variable boCold holds "true" also boils down to true, and more quickly, so there's no need for the longwinded version.
In different circumstances, you might want to say "if boCold=false..." which is perfectly acceptable. Alternatively, you can say "if not boCold".
"Not" is a reserved word... it is part of the Pascal language, like "begin", "end", etc. It is a boolean operator. Consider, for comparison, mathematical operators. There's "squared" for instance. 3 squared is 9. "x squared" boils down to the number multiplied by itself. A boolean thing "not"ed boils down to true if the boolean thing was false, and to false if the boolean thing was true.
This is usually depicted with a truth table:
"Boolean thing" NOT "Boolean thing" false true true falseThe equivalent for "squared" would be....
"Number" "Number" squared" 1 1 2 4 3 9 4 16 ... etc
Pascal would also be quite happy with the following...
if boRaining or boSnowing then writeln('Bring umbrella.');
"Or" is another Pascal reserved word, as is "and". They are two more boolean operators. Where "not" operated on a single boolean value, "or" and "and" operate on two values, returning ("boiling down") to a single value. Because there are two "inputs", these operators are called binary operators. (The name has nothing to do with the fact that they are sometimes applied to numbers you may be thinking of in binary form.) Can you think of some binary operators used in everyday mathematics?
... answer further down page...
Answer to "Name some binary operators used in everyday mathematics": Easy! Adding, subtracting, multiplying, etc!
Here are the truth tables:
(BT= "Boolean Thing") "BT1" "BT2" BT1 AND BT2 false false false false true false true false false true true true "BT1" "BT2" BT1 OR BT2 false false false false true true true false true true true true
The equivalent for "added" would be....
"Num" for "number" "1stNum" "2ndNum" 1stNum PLUS 2ndNum 0 0 0 0 1 1 0 2 2 ... snip... 9 7 16 9 8 17 9 9 18 ... etc
So far, we've looked at simple conditions. You can get "clever"....
if (boRaining or boSnowing) and boCold then writeln('Bring umbrella and wear coat.');
Note the use of the brackets, (), to indicate the order of operations. Because of the brackets, you first boil down the "boRaining or boSnowing" to a "true" or a "false". You then "and" that with what's held in boCold to get the final "answer" to whether you do the "then" part or not.
N.B. You will often write conditions like "iCount>5". (We had that as part of our program. Revisit the text farther up the page, if you are unclear about this.) If you have one of those in a compound condition, put it in brackets. Also put anything with an equals sign in it in brackets, e.g.
if (iCount=5) and (boRaining=false) then...
Without the brackets, Pascal sometimes does unexpected things, like trying to treat the foregoing as....
if iCount=(5 and boRaining)...
Just before we end, I'm going to give you one more Boolean operator, just to round out the story....
The Boolean operator "xor" was named from the words "exclusive or". It is a special case of the "or" operator. Truth table....
(BT= "Boolean Thing") "BT1" "BT2" BT1 XOR BT2 false false false false true true true false true true true FALSE
When you use the ordinary "or" to combine two boolean things, the result, the boiled down single Boolean answer is "true" if the first OR the second of the things you were ORing together were true. This includes the case where both of the inputs are true. The EXCLUSIVE "OR" excludes this case. boCold xor boRaining only boils down to "true" if boCold is true, OR if boRaining is true, but the result is FALSE (not true) if BOTH of them are true.
So! Now you know a lot more than you did! There are more tutorials for you as soon as you recover from this session.
(Sorry... I'll try to write one someday!)
Page has been tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org. Mostly passes.
....... P a g e . . . E n d s .....