Once the programmer has the means to deal with numbers within programs, it also becomes necessary to print the answers to the screen where they can be seen by the program operator. The sample program module powers in section 2.3 contained the statement
WriteCard (exponent, 0);
for writing out the value of CARDINAL to the screen. There is also a WriteInt statement and both are, like ReadCard and ReadInt, imported from SWholeIO (Or, in non ISO Modula-2, from InOut). The second number in the WriteInt and WriteCard statements gives the size of the space to write in. Any extra spaces not needed for the number itself are placed to the left of the number. If not enough spaces are provided for, exactly the correct number will be taken. We say that the numbers are right justified in the specified field. That is,
WriteString ("the number is"); WriteCard (6, 0);
produces the output
the number is 6
with one space before the 6. (Zero room provided is handled as a special case in ISO standard Modula-2 and a single space is prefixed. In non ISO standard versions, there may be no space at all written in this situation.) The statements
WriteString ("the number is"); WriteCard (6, 3);
produce the output
the number is 6
with two spaces before the six, and the statements
int := -13; WriteString ("the number is"); WriteInt (int, 4);
produce the output
the number is -13
with a single space, because one of the four spaces allowed for is needed for the negative sign. Thus, the second number in WriteCard and WriteInt allow for some formatting of the output number. On the other hand, if one does not care how many spaces are used, the second number in WriteInt or WriteCard should be zero. This was done in the powers example, where the space between the strings and the numerals was created by putting spaces into the strings, rather than having them written by WriteCard. This method is preferred when the number of digits in the answer may vary and works in both ISO and non-ISO libraries.
(* display the result *) WriteCard (base, 0); WriteString ( " raised to the power "); WriteCard (exponent, 0); WriteString (" equals "); WriteCard (result, 0); WriteLn;
To illustrate, consider a program designed to print out a small table of cardinals (1 through 10) with their squares and cubes. The planning will not be given in detail, but the algorithm used can be expressed in pseudocode as:
print table headings set base to 1 while base <= 10 print base print square of base print cube of base increase base by one end while
If this algorithm is implemented as:
MODULE SquareCube; (* by R. Sutcliffe *) FROM STextIO IMPORT WriteString, WriteLn; FROM SWholeIO IMPORT WriteCard; VAR base: CARDINAL; BEGIN (* Write column headings *) WriteString ("Number "); WriteString ("Square "); WriteString ("Cube"); WriteLn; base := 1; (*on each line print first, second, and third powers of the base*) WHILE base <= 10 DO WriteCard (base, 0); WriteCard (base * base, 0); WriteCard (base * base * base, 0); base := base + 1; WriteLn; END; END SquareCube.
the output will look like this:
Number Square Cube 1 1 1 2 4 8 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000
because no spacing has been included. (In many non ISO versions, the numbers will be jammed together with no spaces at all, but the ISO standard requires one space to be output before the number in the special case that the room allowed is zero.) Putting one extra space into the WriteCard statements is not sufficient, for only the one digit numbers will then be properly separated. Instead, the program should lay out a well-spaced table. Moreover, this is a good place to use a constant, for the upper limit of the table may well be subject to change. If it is re-written as:
MODULE SquareCubeFormatted; (* by R. Sutcliffe *) FROM STextIO IMPORT WriteString, WriteLn; FROM SWholeIO IMPORT WriteCard; CONST maxToDo = 10; VAR base: CARDINAL; BEGIN (* write column headings *) WriteString (" Number"); (* allow 15 spaces for each *) WriteString (" Square"); WriteString (" Cube"); WriteLn; base := 1; (* on each line print first, second, and third power of base *) WHILE base <= maxToDo DO WriteCard (base, 15); WriteCard (base * base, 15); WriteCard (base * base * base, 15); base := base + 1; WriteLn; END; END SquareCubeFormatted.
the output is
Number Square Cube 1 1 1 2 4 8 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000
There is also a procedure in STextIO (or in InOut) to output CHAR variables. This is the WriteChar statement (called Write when found in InOut,) and it too can output either literal characters, or those designated by constant or variable names. Here is a brief example:
VAR ch : CHAR; BEGIN ch := 'R'; WriteChar (ch); WriteChar ('.'); WriteChar ('S'); WriteChar ('.'); (* outputs my initials *)
and, another:
MODULE GetIt; (* by R. Sutcliffe *) (* prints out a little joke *) FROM STextIO IMPORT WriteString, WriteLn, WriteChar; FROM SWholeIO IMPORT WriteCard; CONST wye = "Y"; (* Character constants are allowed. *) four = 4; BEGIN WriteChar (wye); WriteChar (wye); WriteString ("UR "); WriteChar (wye); WriteChar (wye); WriteString ("UB "); WriteChar ("I"); WriteChar ("C"); WriteString (" UR "); WriteChar (wye); WriteChar (wye); WriteCard (four, 2); WriteString (" ME!"); WriteLn; END GetIt.
the output of which is
YYUR YYUB IC UR YY 4 ME!