This is done in much the same way as single-dimensional arrays, using FOR loops. Here, one makes use of the fact that repetition structures such as FOR loops can be nested one inside the other in a Modula-2 program. Suppose one had the declaration:
TYPE Matrix = ARRAY [0 .. rowmax], [0 .. colmax] OF CARDINAL; VAR A : Matrix;
and wished to initialize all the elements to some value, initNum. Two FOR loops, one nested inside the other are written in the following manner:
FOR rowCount := 0 TO rowmax DO FOR columnCount := 0 TO colmax DO A [rowCount, columnCount] := initNum; END; (* for column *) END; (* for row *)
The outer of the two loops (FOR rowCount) steps through the rows, one at a time. For each of the rows, the inner (FOR columnCount) loop steps through the columns one at a time. In this fashion, each element is initialized in a systematic manner. This routine can be made generic as a procedure by using a two-dimensional open array as follows:
PROCEDURE InitMatrix (VAR theMatrix : ARRAY OF ARRAY OF CARDINAL; initNum : CARDINAL); BEGIN FOR rowCount := 0 TO HIGH (theMatrix) DO FOR columnCount := 0 TO HIGH (theMatrix ) DO theMatrix [rowCount, columnCount] := initNum; END; (* for column *) END; (* for row *) END InitMatrix;
Multidimensional arrays, though not open ones, are used in the following
Design a program that employs a data structure that will record the number of male and female freshmen, sophomores, juniors and seniors enrolled in each of the Sciences, Humanities, Social Sciences, Education, Physical Education, Business, and Aviation divisions at a typical small university. Write the declarations, the code to fill the data structure, and the code to print it out in tabular form. Print also the breakdown of the total number of students by sex, year, and division.
Given: data in the 56 distinct categories
Required to do: prepare summaries by major categories
Desired output: a complete listing of the data with summaries
At some stage during the refinement of the problem (close to the beginning), the programmer must make a decision on the kind of data structure to be used. Since this is a section on multi-dimensional arrays, it takes little imagination to arrive at a suitable way of doing it in this case.
Obtaining Data from user: For each class for each division ask the user for number of men and women enter this into the data structure Generating summaries: For each class sum the men and women in all divisions For each division sum the number of men and women in all classes For each sex sum the number from all classes and divisions Data output: For each class print an informative heading for each division print an informative heading print the number of men print the number of women
No attempt has been made to abstract separate tasks from the whole into procedures, as all the work is closely tied to a single array variable that holds all the program data.
MODULE EnrollData; FROM STextIO IMPORT WriteString, WriteLn, ReadString; FROM SWholeIO IMPORT ReadCard, WriteCard; FROM SIOResult IMPORT ReadResults, ReadResult; TYPE ClassName = (Freshman, Sophomore, Junior, Senior); DivName = (Science, Humanities, SocialScience, Education, PhysEd, Business, Aviation); SexName = (male, female); ClassTot = ARRAY ClassName OF CARDINAL; DivTot = ARRAY DivName OF CARDINAL; SexTot = ARRAY SexName OF CARDINAL; MainData = ARRAY ClassName, DivName, SexName OF CARDINAL; String = ARRAY [0 .. 18] OF CHAR; VAR (* arrays *) classTotals : ClassTot; divTotals : DivTot; sexTotals : SexTot; mainDataArray : MainData; (* counters *) classCount : ClassName; divCount : DivName; sexCount : SexName; (* strings for program use *) classNames : ARRAY ClassName OF String; divNames : ARRAY DivName OF String; sexNames : ARRAY SexName OF String; (* could have done types for last three too *) BEGIN (* main program *) (* First initialize all strings. *) classNames [Freshman] := "freshman "; classNames [Sophomore] := "sophomore "; classNames [Junior] := "junior "; classNames [Senior] := "senior "; divNames [Science] := "Science "; divNames [Humanities] := "Humanities "; divNames [SocialScience] := "Soc Science"; divNames [Education] := "Education "; divNames [PhysEd] := "PhysEd "; divNames [Business] := "Business "; divNames [Aviation] := "Aviation "; sexNames [male] := "males "; sexNames [female] := "females "; (* Now initialize the main array *) FOR classCount := Freshman TO Senior DO FOR divCount := Science TO Aviation DO FOR sexCount := male TO female DO mainDataArray [classCount, divCount, sexCount] := 0; END; (* for sexCount *) END; (* for divCount *) END; (* for classCount *) (* Now write the main loop to gather this data. *) FOR classCount := Freshman TO Senior DO FOR divCount := Science TO Aviation DO FOR sexCount := male TO female DO REPEAT WriteLn; WriteString ("Please give the number of "); WriteString (classNames [classCount]); WriteLn; WriteString (sexNames [sexCount]); WriteString (" in the "); WriteString (divNames [divCount]); WriteString (" division ==> "); ReadCard (mainDataArray [classCount, divCount, sexCount]); UNTIL ReadResult () = allRight; (* keep trying until correct entry *); WriteLn; END; (* for sexCount *) END; (* for divCount *) END; (* for classCount *) (* data is all here now, so do summaries *) FOR classCount := Freshman TO Senior (* by class *) DO classTotals [classCount] := 0; (* initialize to 0 *) FOR divCount := Science TO Aviation DO classTotals [classCount] := classTotals [classCount] + mainDataArray [classCount, divCount, male] + mainDataArray [classCount, divCount, female]; END; (* for divCount *) END; (* for classCount *) (* include code here to total by division and by sex in the same way *) WriteString ("Summary by class:"); WriteLn; WriteString ("class number"); WriteLn; FOR classCount := Freshman TO Senior DO WriteString (classNames [classCount]); (* write class name headings *) WriteCard (classTotals [classCount], 10); WriteLn; END; (* for classCount *) (* include code here to print the appropriate headings and final data by faculty and by sex in the same way *) END EnrollData.
NOTES: 1. The completion of this example is left for the exercises at the end of this chapter, as sufficient detail has been presented for illustrative purposes. What is present here is free from syntax errors, but since it has not been completed and run, it is not guaranteed to be free of logical errors, and the logic of the ReadCard statement needs work. Why?
2. A Modula-2 implementation is likely to have a fixed maximum permissible degree of loop nesting. This affects any combination of FOR, WHILE, REPEAT and any other similar programming structures. This limitation is rarely a problem for the student, whatever the figure may be.
3. Notice the painstaking initialization of all those strings. For the purpose to which they are put here, there is no alternative to this, as one cannot use strings (or any but ordinal types) in an enumeration. However, there are other ways of initializing arrays (including strings) and these are covered in section 11.6.1