Pascal provides two main methods to control the flow of a program - the if...then...else construct and the case...of construct
If
The if statement takes the format
If (condition) then Begin
commands;
End;
Else Begin
commands;
End;
The else section is optional and any of the set of commands may be the null statement (;). The condition must evaluate to a boolean true or false.
Example
As an illustration of using the if command, here we read through the paddress.txt file generated using writeadd.pas or writadd2.pas, searching for a name specified by the user. As well as using the if to perform the comparison of the search string with the value of the name in the current record, the program also uses the while construct to read through the records until end-of-file. Note that the search string used must match exactly, including punctuation and case, the value in the field to be tested to yield a correct match.
program findaddress;
{ searches address file for a given name }
{ sizes for the fields to be stored in the file }
const namesize = 30;
const addresssize = 30;
const telnosize = 20;
{ record structure for the file }
type
address_record = record
name : string[namesize];
address : string[addresssize];
email_address : string[addresssize];
telno : string[telnosize];
end;
var address_rec : address_record;
var infile : text;
var recstring : string[113];
var comma : integer;
var findname : string[namesize];
var found : integer;
begin
{ open the input file and read through all existing records }
assign (infile, 'c:\paddress.txt');
reset (infile);
found := 0; {number of matching records found }
writeln ('Enter name to be retrieved from contacts file :');
readln (findname);
while not (eof(infile)) do
begin
readln (infile, recstring);
{variable recstring now contains the complete record, so we }
{must parse it to extract the individual fields }
{ 1st field is name }
comma := pos(',',recstring); { find where the first field terminates }
address_rec.name := copy (recstring, 1, comma-1); { copy into address_rec.name }
delete (recstring, 1, comma); { delete the name section from recstring}
{ 2nd field is address }
comma := pos(',',recstring);
address_rec.address := copy (recstring, 1, comma-1);
delete (recstring, 1, comma);
{ 3rd field is email_address }
comma := pos(',',recstring);
address_rec.email_address := copy (recstring, 1, comma-1);
delete (recstring, 1, comma);
{ the remaining character in the string is the field telno }
address_rec.telno := recstring;
if (findname = address_rec.name) then
begin
{ Print out the details }
with address_rec do
begin
writeln ('Name : ', name);
writeln ('Address : ', address);
writeln ('Email : ', email_address);
writeln ('Phone : ', telno);
writeln ('');
end; { end of with address_rec }
found := found + 1;
end; { end of 'if' }
end; { end of while not(eof) }
writeln (' * * End-of-file reached * *');
if (found = 0) then
writeln ('There were no records found for ',findname)
else writeln('Number of records found for ',findname,' : ',found);
close (infile);
end.
The program is an amended version of readaddr.pas, with the added functionality that it searches for the name provided by the user.
The first if statement prints the record if the names match. It does not have an else statement, since regardless of whether the record matches or not, we need to read the next contacts record to check again for a match.
The second if statement is a simple check to see how many, if any, matching records have been found and print an appropriate message.
Case...of
The second flow of control construct used in Pascal is the case...of construct. The construct takes the following format :
Case variable of
Expr1 : commands;
Expr2 : commands;
Exprn... : commands;
Else : commands;
End;
Variable is compared, in turn, with expr1, expr2 and so forth until a match is found. Exprn can take be a single value or a set of values. There is no practical limit on the number of value checks that may be used. When a match is found, the commands associated with that exprn are executed. If no match is found, and if an else clause exists, the commands associated with the else clause are executed. If no match is found and no else clause exists, the compiler will leave the case command without executing any commands. The else clause is frequently used to trap as an error a condition that is not catered for.
Example
To illustrate the case...of construct, we amend the findaddr.pas program above, which searches for a name, to search the contacts file by name, address or email address, depending on what the user specifies.
program searchaddress;
{ searches address file by name, address or email address }
{ sizes for the fields to be stored in the file }
const namesize = 30;
const addresssize = 30;
const telnosize = 20;
{ record structure for the file }
type
address_record = record
name : string[namesize];
address : string[addresssize];
email_address : string[addresssize];
telno : string[telnosize];
end;
var address_rec : address_record;
var infile : text;
var recstring : string[113];
var comma : integer;
var findfield : string[namesize];
var option : char;
var matched : boolean;
var found : integer;
begin
{ open the input file and read through all existing records }
assign (infile, 'c:\paddress.txt');
reset (infile);
found := 0;
writeln ('Enter one of the following options ');
writeln (' N - Search by Name');
writeln (' A - Search by Address');
writeln (' E - Search by Email Address');
writeln (' Enter any other letter to quit program ');
readln (option);
if ((option = 'N') or (option = 'A') or (option = 'E') or
(option = 'n') or (option = 'a') or (option = 'e'))
then begin
writeln ('Enter search value : ');
readln (findfield);
while not (eof(infile)) do
begin
readln (infile, recstring);
{variable recstring now contains the complete record, so we }
{must parse it to extract the individual fields }
{ 1st field is name }
comma := pos(',',recstring); { find where the first field terminates }
address_rec.name := copy (recstring, 1, comma-1); { copy into address_rec.name }
delete (recstring, 1, comma); { delete the name section from recstring}
{ 2nd field is address }
comma := pos(',',recstring);
address_rec.address := copy (recstring, 1, comma-1);
delete (recstring, 1, comma);
{ 3rd field is email_address }
comma := pos(',',recstring);
address_rec.email_address := copy (recstring, 1, comma-1);
delete (recstring, 1, comma);
{ the remaining character in the string is the field telno }
address_rec.telno := recstring;
case option of
'N', 'n' : matched := findfield = address_rec.name;
'A', 'a' : matched := findfield = address_rec.address;
'E', 'e' : matched := findfield = address_rec.email_address;
end; {end case}
if (matched) then
begin
{ Print out the details }
with address_rec do
begin
writeln ('Name : ', name);
writeln ('Address : ', address);
writeln ('Email : ', email_address);
writeln ('Phone : ', telno);
writeln ('');
end; { end of with address_rec }
found := found + 1;
end; { end of if matched }
end; { end of while not(eof) }
writeln (' * * End-of-file reached * *');
if (found = 0) then
writeln ('There were no records found for ',findfield)
else writeln('Number of records found for ',findfield,' : ',found);
end; { end of check option is valid }
close (infile);
end.
The case...of construct is often used in the place of a series of nested if statements, to the benefit of the legibility of the code.