1. Backtracking is the recursive use of trial-and-error steps through some kind of pattern, retracing the logical path back to the last success and then following a different branch.
2. The IF and CASE statements are the Modula-2 selection constructs.
3. One should opt for the CASE statement when: (i) the decision involves only the value of a single variable, (ii) there are several (but not very many) adjacent alternative values, (iii) the majority of the alternatives do NOT fall into the ELSE category.
4. CARDINAL has too many values, unless there is an optimizing compiler to reduce the size of the code.
5. The range in one case of a CASE statement cannot be interlaced with ranges in other cases.
6. Range checking can be turned off when error trapping code has been thoroughly tested.
7. Answers may vary.
8. In Modula-2, a pragma is a directive to the compiler that is included in the source file it is compiling. It gives the programmer a chance to give directions to the compiler while the code is being compiled. It is written in pragma brackets: "<*" and "*>"
9. Answers may vary.
10. Some strategies for reducing running time include: (i) Control Run-Time Checking (ii) Compile programs for specified environments (iii) Fine-tune loops (iv) link code segments or (v) use an optimized linker (the latter two are system dependent).
11. Answers may vary.
12. A program library is a collection of the code of one or more modules into a single file.
13. A structure constructor has the form typeName{values}. It is able to construct specific sets, arrays, and records using literals.
14.
TYPE realArray = ARRAY [1..10] OF REAL; VAR reels : realArray; BEGIN reels := realArray{0.0 BY 10};15. The case separator is denoted by the "|" (vertical bar) character and is used to separate cases in a CASE statement. The statement separator is the ";" character and is used to denote the end of a statement in a block of code. Example for case and statement separators:
CASE num OF 1: <statement1>; (* notice the semicolon used to separate statements *) <statement2>; <statement3>; | (* notice the vertical bar used to denote the end of a case *) 2: <statement1>; END;
16. If none of cases match the value of case variable then an error will be generated at execution time. To avoid this problem, an ELSE clause can be attached to the CASE statement to handle any other values that are not handled by a case.
17. A variant record field is a record field that gives the option to select different fields from a CASE clause embedded in the record depending on the value of a tag variable. One would declare a variant field by using a case statement in a record with the expression as a record field and the cases as an optional record fields.
18. TYPE
Classification = (single, married, divorce); Date = RECORD year, month, day : CARDINAL; END; Employee = RECORD lastname : nameString; firstname : nameString; sex : SexType; (* enumerated data type of M or F *) dob : Date; CASE marital : Classification OF single : nextofKin : nameString; | married : marriageDate : Date; spouse : nameString; kids : CARDINAL; | divorce: divorceDate : Date; nextofKin : nameString; END; (* end CASE *) CASE executive : BOOLEAN OF TRUE: salary : REAL; car : REAL; rank : RankString; | FALSE: hourly : REAL; rank : RankString; END; (* end CASE *) END (* end RECORD *)
19. CONST
defSingle = Employee{"", BY 2, M, Date{0 BY 3}, single, "", TRUE, 0 BY 2, ""};
and there are 5 more to make a complete set.
20. Using a variant record can improve the simplify the structure of the RECORD. However, it can also make many nested CASEes that could make the programmer confused when debugging. If most of the fields in the records are identical, a variant form may be best.
21. Unrolling a loop is writing two or more repetitions of the steps in each iteration of the loop. This is done because some control structures are more efficient than repetition.
22. More efficient programs run faster, saving time and money. However, most efficiency improvements can be made with minimal changes to code, and determining the most efficient code technique may not be practical in any reasonable amount of time.
Note: Not all problems are shown. Most problems are left up to students as labs.
(* Created June.22.1999 Chapter 11, Question#26 No error checking has been used for this program...be careful when inputting data!! *) MODULE DataBase; FROM STextIO IMPORT WriteString, ReadString, WriteLn, ReadChar, SkipLine; FROM SWholeIO IMPORT ReadCard, WriteCard; FROM SRealIO IMPORT ReadReal, WriteFixed; FROM SeqFile IMPORT (* use regular text so we can see what the file contains *) OpenWrite, OpenRead, ChanId, Close, OpenResults, read, write, old; FROM Strings IMPORT Compare, CompareResults, Delete; IMPORT TextIO; IMPORT RealIO; IMPORT WholeIO; CONST min = 1; max = 10; TYPE Name = ARRAY [0 .. 20] OF CHAR; MonthType = ARRAY [0..9] OF CHAR; Classification = (student, faculty, staff); Year = (freshman, sophomore, junior, senior); Rank = (instructor, assistant, associate, professor); Job = (secretary, maintenance, janitor); Date = RECORD year : CARDINAL; month : MonthType; day : [1 .. 31]; END; (* of the record Date *) Person = RECORD lastname, firstname : Name; birthdate : Date; (* use previous declarations for these. *) male : BOOLEAN; CASE status : Classification OF (* variant part here *) student: idnumber : CARDINAL; year : Year | faculty: position : Rank; pay : REAL | staff: occupation : Job; END; (* case *) married : BOOLEAN; END; (* of the record Person *) RecType = ARRAY [min..max] OF Person; VAR RecArray : RecType; option, current : CARDINAL; PROCEDURE Menu (VAR option : CARDINAL); (* pre: none post: changes the value of option *) BEGIN WriteString ("********************************"); WriteLn; WriteString ("1. Insert Record "); WriteLn; WriteString ("2. Edit Record "); WriteLn; WriteString ("3. Display Info "); WriteLn; WriteString ("4. Save Record"); WriteLn; WriteString ("5. Get Record File "); WriteLn; WriteString ("6. Exit "); WriteLn; WriteString ("********************************"); WriteLn; WriteLn; WriteString ("Enter an option: "); ReadCard (option); SkipLine; WriteLn; WriteLn; WriteLn; END Menu; PROCEDURE Insert (VAR RecArray : RecType; currentRecNum : CARDINAL); (* pre: none post: Adds a record into the array *) VAR tempcard : CARDINAL; tempreal : REAL; tempchar : CHAR; str : Name; str1 : MonthType; BEGIN WITH RecArray[currentRecNum] DO WriteString ("Name:"); WriteLn; WriteLn; WriteString ("Last Name: "); ReadString (lastname); SkipLine; WriteLn; WriteString ("First Name : "); ReadString (str); SkipLine; firstname := str; WriteLn;WriteLn; WITH birthdate DO WriteString ("Date of Birth: "); WriteLn; WriteLn; WriteString ("Month: "); ReadString (month); SkipLine; WriteLn; WriteString ("Day: "); ReadCard (tempcard); SkipLine; day := tempcard; WriteLn; WriteString ("Year: "); ReadCard (year); SkipLine; END; WriteLn; WriteLn; WriteString ("Male or Female (m/f): "); ReadChar (tempchar); SkipLine; IF CAP(tempchar) = 'M' THEN male := TRUE; ELSE male := FALSE; END; (* IF *) WriteLn; WriteLn; WriteString ("Classifcation: "); WriteLn; WriteString ("1. student"); WriteLn; WriteString ("2. faculty"); WriteLn; WriteString ("3. staff"); WriteLn; WriteString ("Choice: "); ReadCard (tempcard); SkipLine; status := VAL (Classification, tempcard - 1); CASE status OF student: WriteString ("Give i.d. number, please. "); ReadCard (idnumber); SkipLine; WriteLn; WriteString ("and enter the year 1 .. 4 "); WriteString ("of studies. "); ReadCard (tempcard); SkipLine; year := VAL(Year, tempcard - 1) | faculty: WriteString ("Enter the rank of the faculty member "); WriteLn; WriteString ("by number. A '1' for instructor, "); WriteLn; WriteString ("a '2' for assistant, a '3' for associate, "); WriteLn; WriteString ("or a '4' for a full professor. "); ReadCard (tempcard); SkipLine; position := VAL (Rank, tempcard - 1); WriteLn; WriteString ("How much is this faculty member paid? "); WriteLn; WriteString ("Answer using decimal point, please. "); ReadReal (pay); SkipLine; | staff: WriteString ("Please enter a '1' for a secretary, "); WriteLn; WriteString ("a '2' for a maintenance employee, "); WriteLn; WriteString ("or a '3' for a janitor. "); ReadCard (tempcard); SkipLine; WriteLn; occupation := VAL (Job, tempcard - 1); (* no bar here *) END; (* CASE *) WriteLn; WriteLn; WriteString ("Married (y/n)? "); ReadChar (tempchar); SkipLine; IF CAP(tempchar) = 'Y' THEN married := TRUE; ELSE married := FALSE; END; (* IF *) END; (* WITH *) END Insert; PROCEDURE Display (record : RecType; currentRecNum : CARDINAL); (* pre: none post: changes a displayed record *) VAR count : CARDINAL; BEGIN IF currentRecNum = 0 THEN WriteString ("No records available"); WriteLn; WriteLn; ELSE FOR count := 1 TO currentRecNum DO WriteCard (count, 1); WriteString (". "); WITH record[count] DO WriteString (lastname); WriteString (", "); WriteString (firstname); END; WriteLn; END; (* end FOR *) END; (* end IF *) WriteLn; WriteLn; END Display; PROCEDURE DisplayFull (RecArray : RecType; recnum : CARDINAL); (* pre: none post: displays full record information *) VAR class : Classification; BEGIN WITH RecArray[recnum] DO WriteString ("Name: "); WriteString (firstname); WriteString (" "); WriteString (lastname); WriteLn; WITH birthdate DO WriteString ("Date of Birth:"); WriteString (" Month: "); WriteString (month); WriteString (" Day:"); WriteCard (ORD(day), 0); WriteString (" Year:"); WriteCard (year, 0); WriteLn; END; (* end WITH *) WriteString ("Gender: "); IF male THEN WriteString ("Male"); ELSE WriteString ("Female"); END; WriteLn; WriteString ("Classification: "); CASE status OF student: WriteString ("Student"); WriteLn; WriteString ("Id Number: "); WriteCard (idnumber, 1); WriteLn; WriteString ("Year: "); IF year = freshman THEN WriteString ("Freshman"); ELSIF year = sophomore THEN WriteString ("Sophomore"); ELSIF year = junior THEN WriteString ("Junior"); ELSE WriteString ("Senior"); END; | faculty: WriteString ("Faculty"); WriteLn; WriteString ("Rank: "); IF position = instructor THEN WriteString ("Instructor"); ELSIF position = assistant THEN WriteString ("Assistant"); ELSIF position = associate THEN WriteString ("Associate"); ELSE WriteString ("Professor"); END; WriteLn; WriteString ("Salary: $"); WriteFixed (pay, 2, 1); | staff: WriteString ("Staff"); WriteLn; WriteString ("Job: "); IF occupation = secretary THEN WriteString ("Secretary"); ELSIF occupation = maintenance THEN WriteString ("Maintenance"); ELSE WriteString ("Janitor"); END; END; (* end CASE *) WriteLn; WriteString ("Married: "); IF married THEN WriteString ("Yes"); ELSE WriteString ("No"); END; WriteLn; WriteLn; END; (* end WITH *) END DisplayFull; PROCEDURE SaveRec (record : RecType; numtosave : CARDINAL) : BOOLEAN; (* pre: none post: saves the array of records to a file specified by user *) VAR file : ChanId; filename : ARRAY [0..12] OF CHAR; res : OpenResults; count : CARDINAL; BEGIN WriteString ("Enter filename: "); ReadString (filename); SkipLine; WriteLn; OpenWrite (file, filename, read+write+old, res); IF res = opened THEN FOR count := 1 TO numtosave DO WITH record[count] DO (* save name *) TextIO.WriteString (file, lastname); TextIO.WriteString (file, " "); TextIO.WriteString (file, firstname); TextIO.WriteLn (file); (* save birthdate *) WITH birthdate DO TextIO.WriteString (file, month); TextIO.WriteString (file, " "); WholeIO.WriteCard (file, ORD(day), 1); TextIO.WriteString (file, " "); WholeIO.WriteCard (file, year, 1); TextIO.WriteLn (file); END; (* end WITH *) (* save gender *) WholeIO.WriteCard (file, ORD(male), 1); TextIO.WriteLn (file); (* save classification *) WholeIO.WriteCard (file, ORD(status), 1); TextIO.WriteString (file, " "); CASE status OF student: WholeIO.WriteCard (file, idnumber, 1); TextIO.WriteString (file, " "); WholeIO.WriteCard (file, ORD(year), 1); | faculty: WholeIO.WriteCard (file, ORD(position), 1); TextIO.WriteString (file, " "); RealIO.WriteFixed (file, pay, 2, 1); | staff: WholeIO.WriteCard (file, ORD(occupation), 1); END; (* end CASE *) TextIO.WriteLn (file); (* save marital status *) WholeIO.WriteCard (file, ORD(married), 1); TextIO.WriteLn (file); TextIO.WriteLn (file); END; (* end WITH *) END; (* end FOR *) TextIO.WriteString (file, "<>"); Close (file); RETURN TRUE; ELSE Close (file); RETURN FALSE; END; (* end IF *) END SaveRec; PROCEDURE GetRec (VAR record : RecType; VAR numofRecs : CARDINAL) : BOOLEAN; (* pre: none post: retrieves a record from a file and puts it in an array *) VAR done : BOOLEAN; count, tempcard : CARDINAL; file : ChanId; res : OpenResults; filename : ARRAY [0..13] OF CHAR; BEGIN WriteString ("Enter name of record file to retrieve: "); ReadString (filename); SkipLine; (* initialize variables *) numofRecs := 0; done := FALSE; count := 1; (* open file *) OpenRead (file, filename, read+write+old, res); IF res = opened THEN WHILE NOT done DO WITH record[count] DO (* get name *) TextIO.ReadToken (file, lastname); (* check for end of file *) IF Compare (lastname, "< >") # equal THEN TextIO.ReadString (file, firstname); TextIO.SkipLine (file); Delete (firstname, 0, 1); (* to counter the extra space effect *) (* get birthdate *) WITH birthdate DO TextIO.ReadToken (file, month); WholeIO.ReadCard (file, tempcard); day := tempcard; WholeIO.ReadCard (file, year); TextIO.SkipLine (file); END; (* end WITH *) (* get gender *) WholeIO.ReadCard (file, tempcard); male := VAL(BOOLEAN, tempcard); TextIO.SkipLine (file); (* get classification *) WholeIO.ReadCard (file, tempcard); status := VAL(Classification, tempcard); CASE status OF student: WholeIO.ReadCard (file, idnumber); WholeIO.ReadCard (file, tempcard); year := VAL(Year, tempcard); | faculty: WholeIO.ReadCard (file, tempcard); position := VAL(Rank, tempcard); RealIO.ReadReal (file, pay); | staff: WholeIO.ReadCard (file, tempcard); occupation := VAL(Job, tempcard); END; (* end CASE *) TextIO.SkipLine (file); (* get marital status *) WholeIO.ReadCard (file, tempcard); married := VAL(BOOLEAN, tempcard); TextIO.SkipLine (file); TextIO.SkipLine (file); INC (count); INC (numofRecs); ELSE done := TRUE; END; END; (* end WITH *) END; (* end WHILE *) Close (file); RETURN TRUE; ELSE Close (file); RETURN FALSE; END; (* end IF *) END GetRec; (* begin main block *) BEGIN current := 0; REPEAT Menu (option); IF option = 1 THEN INC (current); Insert(RecArray, current); ELSIF option = 2 THEN Display (RecArray, current); IF current # 0 THEN WriteString ("Choose a record to edit: "); ReadCard (option); SkipLine; Insert (RecArray, option); option := 2; END; ELSIF option = 3 THEN Display (RecArray, current); IF current # 0 THEN WriteString ("Choose a record to display full info: "); ReadCard (option); SkipLine; DisplayFull(RecArray, option); option := 3; END; ELSIF option = 4 THEN IF SaveRec(RecArray, current) THEN WriteString ("Save successful"); ELSE WriteString ("An error has occured couldn't save"); END; ELSIF option = 5 THEN IF GetRec(RecArray, current) THEN WriteCard (current, 1); WriteString ("record(s) retrieved"); ELSE WriteString ("Error occured when retrieved"); END; END (* End IF *); WriteLn; UNTIL option = 6; END DataBase.
(* Created June.21.1999 Chapter 11 Question 27 *) MODULE NumberCheck; FROM STextIO IMPORT WriteString, WriteLn, ReadChar, SkipLine; FROM SWholeIO IMPORT ReadInt, WriteInt; FROM SIOResult IMPORT ReadResult, ReadResults; VAR number, count, sum : INTEGER; exit : CHAR; BEGIN REPEAT (* get input *) WriteString ("Enter a whole number to be evaluated: "); ReadInt (number); IF ReadResult () # allRight THEN WriteString ("Not the right a valid number"); END; SkipLine; WriteLn; (* initialize *) count := 1; sum := 0; (* evaluate if it's a perfect, deficitent, or abundant *) WHILE count < number DO IF number MOD count = 0 THEN sum := sum + count; END; INC (count); END; (* print *) WriteString ("The number"); WriteInt (number, 0); WriteString (" is "); count := sum - number; CASE count OF 0: WriteString ("PERFECT");| 1..MAX(INTEGER): WriteString ("ABUNDANT"); ELSE WriteString ("DEFICIENT"); END; (* redo *) WriteLn; WriteString ("Do you want to do another (y/n)? "); ReadChar (exit); SkipLine; UNTIL CAP(exit) = 'N'; END NumberCheck.