
People type untidily. They put two spaces where one would do, start with a space, end with a full stop, add a comma, and use capitals when they feel like it. A program that has to recognise TAKE should not also have to recognise take, Take, and TAKE.. So before anything else, the line is tidied: once, in one place.
After tidying, a line:
Take the lamp! becomes TAKE THE LAMP. look,then go north becomes LOOK THEN GO NORTH. A line of nothing but punctuation becomes the empty string.
A set of characters says which characters belong to a group, and in asks whether one does:
if not (Ch in ['A'..'Z']) then
Ch := ' ';
Every character that is not a capital letter becomes a space. Run UpCase first, and small letters are capitals by the time they are tested, while everything else passes through UpCase unchanged.
A set can be named, too, as a typed constant, and used wherever the brackets would go:
const
Letters: set of Char = ['A'..'Z'];
Tidy builds a new string, T, one character at a time. A letter always goes in. A space goes in only if T is not empty and does not already end in a space; that one rule removes spaces at the start and doubled spaces everywhere. At the end, a single space left on the end is cut off with T[0] := Pred(T[0]).
Notice the test (T <> '') and (T[Length(T)] <> ' '). Turbo works out both sides of an and, always, even when the first is false. So when T is empty, T[Length(T)] is still looked at: it is T[0], the length byte, which does no harm here, but it is worth knowing that Turbo does not stop early.
program Tidier;
type
Str40 = string[40];
var
Line: Str40;
procedure Tidy(var S: Str40);
var
T: Str40;
I: Integer;
Ch: Char;
begin
T := '';
for I := 1 to Length(S) do
begin
Ch := UpCase(S[I]);
if not (Ch in ['A'..'Z']) then
Ch := ' ';
if (Ch <> ' ') or ((T <> '')
and (T[Length(T)] <> ' ')) then
T := T + Ch;
end;
if (T <> '') and
(T[Length(T)] = ' ') then
T[0] := Pred(T[0]);
S := T;
end;
begin
repeat
Write('> ');
Readln(Line);
Tidy(Line);
Writeln('[', Line, ']');
until Line = '';
end.
Starting from
A new work file TIDIER. Press CAPS LOCK once for small letters.
What you should see
Type the lines on the left. The program stops when a line tidies to nothing.
> Take the lamp!
[TAKE THE LAMP]
> n.
[N]
> look,then go north
[LOOK THEN GO NORTH]
> turn dial to 7
[TURN DIAL TO]
> ...
[]
if statement, the one that cuts a trailing space. Which of the lines above change?['A'..'Z'] to ['A'..'Z', '0'..'9']. Which line changes?if with just T := T + Ch;. What happens to Take the lamp!, and what happens when you type ...?5.1 Add a function Words(S: Str40): Integer that counts the words in a tidied line, and print the count beside each line.
5.2 Write Tidy without UpCase: test for ['a'..'z'] and make the capital with Chr(Ord(Ch) - 32).
5.3 Players are polite. If a tidied line starts with PLEASE, take it off, so that please open the door becomes OPEN THE DOOR. Make sure pleased to meet you is left alone.
Worked solutions are in Appendix II.
| Symptom | Cause |
|---|---|
| The program never ends | A line of punctuation tidied to spaces rather than to nothing: the rule that keeps spaces out of an empty T is missing. |
| A space on the end of every line | The final if that cuts it is missing. |
| Numbers vanish | Only letters are in the set. Add '0'..'9' if your game needs them. |
Tidying makes every line the same shape before the parser sees it: capitals, letters, single spaces. UpCase makes capitals; a set of characters says what to keep; a space is added only after a letter; the last space, if any, is cut with S[0].
S6, Splitting Into Words, Two Ways: a tidy line, taken apart.
This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.