Pascal Programming/Input and Output

From Wikibooks, open books for an open world
Jump to navigation Jump to search

We already have been using I/O since the first chapter, but only to get going. It is time to dig a little bit deeper, so we can write nicer programs.

Interface[edit | edit source]

In its heydays Pascal was so smart and defined a minimal common, yet convenient interface to interact with I/O. Despite various standardization efforts I/O operations differ among every single OS, yet – as part of the language – Pascal defines a set of operations to be present, regardless of the utilized compiler or OS.

Special files[edit | edit source]

In the first chapter it was already mentioned that input and output are special program parameters. If you list them in the program parameter list, you can use these identifiers to write and read from the terminal, the CLI you are using.

Text files[edit | edit source]

In fact, input and output are variables. Their data type is text. We call a variable that has the data type text a text file.

The data of a text file are composed of lines. A line is a (possibly empty) sequence of characters (e. g. letters, digits, spaces or punctuation) until and including a terminating “newline character”.

Files[edit | edit source]

A file – in general – has the following properties:

  • It can be associated with an external entity. External means “outside” of your program. A suitable entity can be, for instance, your console window, a device such as your keyboard, or a file that resides in your file system.
  • If a file is associated with an external entity, it is considered bound.
  • A file has a mode. Every file can be in generation or inspection mode, none or both. If a file is in generation and inspection mode at the same time, this can also be called update mode.[fn 1]
  • Every file has a buffer. This buffer is a temporary storage for writing or reading data, so virtually another variable. This buffer variable exists due to reasons how I/O on computers works.

All this information is implicitly available to you, you do not need to take care of it. You can query and alter some information in predefined ways.

All you have to keep in mind in order to successfully use files is that a file has a mode. The text files input and output are, once they are listed in the program parameter list, in inspection and generation mode respectively. You can only read data from files that are inspection mode. And it is only possible to write data to files that are generation mode.

Note, due to their special nature the mode of input and output cannot be changed.

Routines[edit | edit source]

Pascal defines the following routines to read and write to files:

  • get,
  • put,
  • read/readLn, and
  • write/writeLn.

The routines readLn and writeLn can only be used in conjunction with text files, whereas all other routines work with any kind of file. In the following sections we will focus on read and write. These routines build upon the “low-level” get and put. In the chapter “Files” we will take a look at them, though.

Writing data[edit | edit source]

Let’s look at a simple program:

program writeDemo(output);
var
	x: integer;
begin
	x := 10;
	writeLn(output, x:20);
end.

Copy the program and see what it does.

Assignment[edit | edit source]

First, we will learn a new statement, the assignment. Colon equals (:=) is read as “becomes”. In the line x := 10 the variable’s value becomes ten. On the left hand side you write a variable name. On the right hand side you put a value. The value has to be valid for the variable’s data type. For instance, you could not assign 'Hello world!' to the variable x, because it is not a valid integer, i. e. the data type x has.

Converting output[edit | edit source]

The power of write/writeLn is that – for text files – it converts the parameters into a human-readable form. On modern computers the integer value ten is stored in a particular binary form. 00001010 is a visual representation of the bits set (1) and unset (0) for storing “ten”. Yet, despite the binary storage the characters you see on the screen are 10. This conversion, from zeroes and ones into a human-readable representation, the character sequence “10”, is done automatically.

Note If the destination of write/writeLn is a text file, all parameters are converted into a human-readable form provided such conversion is necessary and makes sense.

Formatting output[edit | edit source]

Furthermore, after the parameter x comes :20. As you might have noticed, when you run the program the value ten is printed right-aligned making the 0 in 10 appear at the 20th column (position from the left margin).

The :20 is a format specifier. It ensures that the given parameter has a minimum width of that many characters and it may fill missing “width” with spaces to left.

Note Format specifiers in a write/writeLn call can only be specified where a human-readable representation is necessary, in other words if the destination is a text file.

Reading data[edit | edit source]

Look at this program:

program iceCream(input, output);
var
	response: char;
begin
	writeLn('Do you like ice cream?');
	writeLn('Type “y” for “yes” (“Yummy!”) and “n” for “no”.');
	writeLn('Confirm your selection by hitting Enter.');
	
	readLn(input, response);
	
	if response = 'y' then
	begin
		writeLn('Awesome!');
	end;
end.

Requirements[edit | edit source]

All parameters given to read/readLn have to be variables. The first parameter, the source, has to be a file variable which is currently in inspection mode. We ensure that by putting input into the program parameter list. If the source parameter is input, you are allowed to omit it, thus readLn(response) is equivalent to readLn(input, response).

Note If the source is a text file, you can only read values for variables having the data type char, integer, real, or “string types”. Other variables not compatible to these types cannot be read from a text file. (The term “compatible” will be explained later.)

Branching[edit | edit source]

A new language construct which we will cover in detail in the next chapter is the if-then-branch. The code after then that is surrounded by begin and end; is only executed if response equals to the character value 'y'. Otherwise, we are polite and do not express our strong disagreement.

Tasks[edit | edit source]

Can you write to input? Why does / should it work, or not?
You cannot write to input. The text file input is, provided it is listed in the program parameter list, in inspection mode. That means you can only read data from this text file, never write.
You cannot write to input. The text file input is, provided it is listed in the program parameter list, in inspection mode. That means you can only read data from this text file, never write.


Can you read to a constant?
No, all parameters to read/readLn have to be variables. A constant, per definition, does not change its value during run-time. That means, also the user cannot assign values to a constant.
No, all parameters to read/readLn have to be variables. A constant, per definition, does not change its value during run-time. That means, also the user cannot assign values to a constant.


Take your program valentine from the first chapter and improve it with knowledge you have learned in this chapter: Make the heart ideogram appear (sort of) centered. Assume a console window width of 80 characters, or any reasonable width.
An improved version may look like this:
program valentine(output);
const
	width = 49;
begin
	writeLn('   ####     ####   ':width);
	writeLn(' ######## ######## ':width);
	writeLn('##     ####      ##':width);
	writeLn('##       #       ##':width);
	writeLn('##      ILY      ##':width);
	writeLn(' ##   sweetie   ## ':width);
	writeLn('  ###         ###  ':width);
	writeLn('    ###     ###    ':width);
	writeLn('      ### ###      ':width);
	writeLn('        ###        ':width);
	writeLn('         #         ':width);
end.
Note the usage of a constant for the formatting width. Use constants whenever you are otherwise repeating values. Do not worry if you did not do that. You will get a sense for that. Also, the string literals can be shorter on the left side:
program valentine(output);
const
	width = 49;
begin
	writeLn(   '####     ####   ':width);
	writeLn( '######## ######## ':width);
	writeLn('##     ####      ##':width);
	writeLn('##       #       ##':width);
	writeLn('##      ILY      ##':width);
	writeLn( '##   sweetie   ## ':width);
	writeLn(  '###         ###  ':width);
	writeLn(    '###     ###    ':width);
	writeLn(      '### ###      ':width);
	writeLn(        '###        ':width);
	writeLn(         '#         ':width);
end.
Note that the “opening” typewriter apostrophe starts right before first hash mark. Indentation, though, has been preserved, so you can still recognize the heart shape in your source code and do not need to run the program to see it.
An improved version may look like this:
program valentine(output);
const
	width = 49;
begin
	writeLn('   ####     ####   ':width);
	writeLn(' ######## ######## ':width);
	writeLn('##     ####      ##':width);
	writeLn('##       #       ##':width);
	writeLn('##      ILY      ##':width);
	writeLn(' ##   sweetie   ## ':width);
	writeLn('  ###         ###  ':width);
	writeLn('    ###     ###    ':width);
	writeLn('      ### ###      ':width);
	writeLn('        ###        ':width);
	writeLn('         #         ':width);
end.
Note the usage of a constant for the formatting width. Use constants whenever you are otherwise repeating values. Do not worry if you did not do that. You will get a sense for that. Also, the string literals can be shorter on the left side:
program valentine(output);
const
	width = 49;
begin
	writeLn(   '####     ####   ':width);
	writeLn( '######## ######## ':width);
	writeLn('##     ####      ##':width);
	writeLn('##       #       ##':width);
	writeLn('##      ILY      ##':width);
	writeLn( '##   sweetie   ## ':width);
	writeLn(  '###         ###  ':width);
	writeLn(    '###     ###    ':width);
	writeLn(      '### ###      ':width);
	writeLn(        '###        ':width);
	writeLn(         '#         ':width);
end.
Note that the “opening” typewriter apostrophe starts right before first hash mark. Indentation, though, has been preserved, so you can still recognize the heart shape in your source code and do not need to run the program to see it.


Create a program that draws a 40 by 6 box like the one shown below, but (for educational purposes) we do not want to enter four times 38 spaces in our source code.
o--------------------------------------o
|                                      |
|                                      |
|                                      |
|                                      |
o--------------------------------------o
If you are stuck, here is a hint.
This is an empty string literal: ''. It is two straight typewriter’s apostrophes back-to-back. You can use it in your solution.
This is an empty string literal: ''. It is two straight typewriter’s apostrophes back-to-back. You can use it in your solution.
An acceptable implementation could look like this:
program box(output);
const
	space = 38;
begin
	writeLn('o--------------------------------------o');
	writeLn('|', '':space, '|');
	writeLn('|', '':space, '|');
	writeLn('|', '':space, '|');
	writeLn('|', '':space, '|');
	writeLn('o--------------------------------------o');
end.
The '':space will generate 38 (that is the value of the constant space) spaces. If you are really smart, you have noticed that the top and bottom edges of the box are the same literal twice. We can shorten our program even further:
program box(output);
const
	space = 38;
	topAndBottomEdge = 'o--------------------------------------o';
begin
	writeLn(topAndBottomEdge);
	writeLn('|', '':space, '|');
	writeLn('|', '':space, '|');
	writeLn('|', '':space, '|');
	writeLn('|', '':space, '|');
	writeLn(topAndBottomEdge);
end.
An acceptable implementation could look like this:
program box(output);
const
	space = 38;
begin
	writeLn('o--------------------------------------o');
	writeLn('|', '':space, '|');
	writeLn('|', '':space, '|');
	writeLn('|', '':space, '|');
	writeLn('|', '':space, '|');
	writeLn('o--------------------------------------o');
end.
The '':space will generate 38 (that is the value of the constant space) spaces. If you are really smart, you have noticed that the top and bottom edges of the box are the same literal twice. We can shorten our program even further:
program box(output);
const
	space = 38;
	topAndBottomEdge = 'o--------------------------------------o';
begin
	writeLn(topAndBottomEdge);
	writeLn('|', '':space, '|');
	writeLn('|', '':space, '|');
	writeLn('|', '':space, '|');
	writeLn('|', '':space, '|');
	writeLn(topAndBottomEdge);
end.

Notes:

  1. “Update” mode is only available in Extended Pascal (ISO standard 10206). In Standard (unextended) Pascal (laid out in ISO standard 7185) a file can be either in inspection or generation mode, or none.