## 5.8 Manipulating Multi-Dimensional Arrays

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 [0])
DO
theMatrix [rowCount, columnCount] := initNum;
END;      (* for column *)
END;    (* for row *)
END InitMatrix;```

Multidimensional arrays, though not open ones, are used in the following

### Problem:

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.

### Restatement:

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

### Discussion of Data Structure:

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.

### Pseudocode:

```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
for each division
print the number of men
print the number of women```

### Data Table:

Enumerated types:

• names of classes, divisions and sexes

Array Types:

• an array of cardinals indexed by class, division, and sex names to hold the raw data
• an array of cardinals indexed by class names to hold class totals
• an array of cardinals indexed by division names to hold division totals
• an array of cardinals indexed by sex names to hold sex totals
• a string type to hold names of all the categories

Main variables:

• a main data array
• an array for each of the sets of totals
• a counter variable for loops on each of the three index types
• an array indexed by class names to hold corresponding strings
• an array indexed by division names to hold corresponding strings
• an array indexed by sex names to hold corresponding strings

Imports required:

From STextIO:

From SWholeIO:

From SIOResult:

### Organization:

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.

### Code:

```MODULE EnrollData;

FROM STextIO IMPORT
FROM SWholeIO IMPORT
FROM SIOResult IMPORT

TYPE
ClassName = (Freshman, Sophomore, Junior, Senior);
DivName  = (Science, Humanities, SocialScience, Education,
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 [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 ==> ");
(* 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

Contents