UNIT DayIO;
(* This unit provides a facility to input and output day of the week
* names. The names are Sun, Mon, Tue, Wed, Thu, Fri, and Sat. Such
* names may be read in using ReadDay, written using WriteDay. ReadDay
* reads in the name, and returns it as a value of the enumerated type
* DayType. The input value is case-sensitive, and must be entered
* exactly as given in the list above. WriteDay takes a DayType value
* and prints it, using one of the string above. There is also a
* function MapToDay which accepts a string containing the name of a
* day and maps it to a DayType value.
*)
INTERFACE
TYPE
{ Type to represent a day of the week, or an error. }
DayType = (Sun, Mon, Tue, Wed, Thu, Fri, Sat, BadDay);
{ Convert a string to a day. If it is not a legal day, the result is
BadDay.
Precondition: None:
Postcondition: If S is one of the strings Sun Mon Tue Wed Thu Fri, or
Sat, MapToDay returns the corresponding day. Otherwise, it
returns BadDay. }
FUNCTION MapToDay(S: String): DayType;
{ Read a day from the file. The day must be the next item on the same
line. The procedure skips leading blanks, and reads the next
non-blank item on the line, and returns the day read. If there was
no item on the line, or the item was not a legal day, it returns
BadDay.
Precondition: InFile is open for reading.
Postcondition: The file has been read until the first non-blank
character is seen, then through the first blank character, but
not past the end of the current line. If the sequence of
non-blank characters read matches one of the day strings
Sun Mon Tue Wed Thu Fri or Sat, the corresponding day of the
week is returned in Day. If not, or if no non-blank characters
were read, the item BadDay is returned. }
PROCEDURE ReadDay
(VAR InFile: TEXT; (* Input file read from. *)
VAR Day: DayType); (* Returned day of the week value. *)
{ Write a day to the file.
Precondition: OutFile is open for writing.
Postcondition: The string of characters Sun Mon Tue Wed Thu Fri or Sat
corresponding the value is Day is written to OutFile. }
PROCEDURE WriteDay
(VAR OutFile: TEXT; (* Input file written to. *)
Day: DayType); (* Day to write. *)
IMPLEMENTATION
CONST
{ Size of day strings. }
DaySize = 3;
TYPE
{ Type of a day. }
DayStrType = STRING[DaySize];
VAR
{ Map from enumerated day type to characters. }
DayMap: ARRAY[DayType] of DayStrType;
{ Convert a string to a day. If it is not a legal day, the result is
BadDay. }
FUNCTION MapToDay(S: String): DayType;
VAR
Day: DayType; (* Scanner. *)
Found: boolean; (* Tell if a match was found. *)
BEGIN
Found := FALSE;
Day := Sun;
WHILE (Day < BadDay) AND NOT Found DO
BEGIN
IF DayMap[Day] = S THEN
Found := TRUE
ELSE
Day := succ(Day)
END;
MapToDay := Day
END;
{ Read one character, but do not read past the end of line. Just
return a space.
Pre: InFile is open for reading.
Post: If InFile was at eoln, Ch is set to ' ', and InFile is
unchanged. Otherwise, one character is read from InFile to Ch. }
PROCEDURE ReadOnLine(VAR InFile: TEXT; VAR Ch: Char);
BEGIN
IF eoln(InFile) THEN
Ch := ' '
ELSE
read(InFile, Ch)
END;
{ Read a day from the file. The day must be the next item on the same
line. The procedure skips leading blanks, and reads the next
non-blank item on the line, and returns the day read. If there was
no item on the line, or the item was not a legal day, it returns
BadDay. }
PROCEDURE ReadDay
(VAR InFile: TEXT; (* Input file read from. *)
VAR Day: DayType); (* Returned day of the week value. *)
VAR
Ch: char; (* Input character. *)
DayStr: DayStrType; (* Input string of chars. *)
BEGIN
(* Skip blanks. *)
Ch := ' ';
WHILE (Ch = ' ') AND NOT eoln(InFile) DO
BEGIN
read(InFile, Ch)
END;
(* See if we found a non-blank character. *)
IF Ch = ' ' THEN
(* The skip loop must have ended at eoln. *)
Day := BadDay
ELSE
BEGIN
(* Read the characters. *)
DayStr := '';
WHILE (Ch <> ' ') AND (Length(DayStr) < DaySize) DO
BEGIN
DayStr := DayStr + Ch;
ReadOnLine(InFile, Ch)
END;
(* Match must be exact. *)
IF Ch <> ' ' THEN
(* Something else out there. Not good. *)
Day := BadDay
ELSE
BEGIN
(* Discard any remaining characters. *)
WHILE (Ch <> ' ') AND NOT eoln(InFile) DO
read(InFile, Ch);
(* Map the string to the enum. *)
Day := MapToDay(DayStr)
END
END
END;
{ Write a day to the file. }
PROCEDURE WriteDay
(VAR OutFile: TEXT; (* Input file written to. *)
Day: DayType); (* Day to write. *)
BEGIN
write(OutFile, DayMap[Day])
END;
BEGIN
(* Initialize the DayMap. This is an easy way to convert
DayType values to strings. It is used internally by the
unit. *)
DayMap[Sun] := 'Sun';
DayMap[Mon] := 'Mon';
DayMap[Tue] := 'Tue';
DayMap[Wed] := 'Wed';
DayMap[Thu] := 'Thu';
DayMap[Fri] := 'Fri';
DayMap[Sat] := 'Sat';
DayMap[BadDay] := '***'
END.