Sign in Join
Wiki copytemporary

Read: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Read

OldNewLine
1+The procedures `read` and `readLn` retrieve data from a [[Text|text file]] (such as `input`, the command line interface, or any file on disk). They are defined as part of the [[Standard Pascal|Pascal]] programming language. Everyone can expect them to work no matter which compiler has been used.
2+
3+In [[Property|property]] definitions the [[Reserved word|reserved word]] `read` is used to direct read access. This article deals with the procedures `read` and `readLn`. See [[Object|object]] and related articles for the occurrence of `read` in the context of properties.
4+
5+## Behavior
6+
7+### Signature
8+
9+`Read` as well as `readLn` share almost the same identical formal signature. However a formal signature is omitted here, since you can not write their signatures in Pascal. Therefore a description follows:
10+
11+As an optional first parameter a `text` variable can be specified where data are read from. `Read` is additionally capable of reading from a [[typed files|typed file]] variable (`file of recordType`).
12+
13+If no source is specified, [[Input|input]] is assumed. Thereafter any number of variables can be specified, but at least one has to be present. They have to be either [[Char|char]], [[Integer|integer]], [[Real|real]], or [[String|string]]. If you have specified a typed file as the source, all variables have to be of the file’s underlying base type.
14+
15+Earlier versions of [[FPC]] also allowed reading variables of the type [[PChar]]. This has been removed, since no buffer checking is possible with those. In the case of typed files as source, only variables of the [[File|file’s]] record type can be specified.
16+
17+### Execution
18+
19+Calling `read`/`readLn` will place the read (and possibly accordingly interpreted) values to the given variables.
20+
21+The order of variables matters. For instance, when the following program:
22+
23+``` pascal
24+program readDemo(input, output, stderr);
25+var
26+ i: integer;
27+ c: char;
28+begin
29+ readLn(i, c);
30+end.
31+```
32+
33+is supplied with:
34+
35+```text
36+42 x
37+```
38+
39+everything is fine.
40+
41+`i` will become `42` and `c` will become `'x'`. But the reverse input order
42+
43+```text
44+x 42
45+```
46+
47+will yield a [[runtime error|run-time error]] (in this case RTE 106).
48+
49+Once data are read and stored, they are “consumed”, thus cannot be retrieved otherwise, but via the variables only. However, data are read up to the variable’s size limits. E. g. a fixed length `string[24]` will stop reading beyond the 24th character.
50+
51+Leading blanks in front of numeric types are skipped.
52+
53+If the source file is not open, the RTE 103 “file not open”, RTE 6 “invalid file handle” (for `input` in a non-[[Mode iso|ISO compiler mode]]) will stop the program. These RTE may be converted to an [`eInOutError`](https://www.freepascal.org/docs-html/rtl/sysutils/einouterror.html) exception if the [[sysutils|sysUtils unit]] is included (e. g. via a [[Uses|uses-clause]]).
54+
55+If the source file is open, but no data is available, possibly because the end of file has already been reached, default values for the remaining variables are loaded.
56+
57+### Interpretation
58+
59+`Read` and `readLn` are so powerful, because they interpret given data. For instance, a `readLn` storing an integer does not expect the binary value to be entered, but their decimal representation with ASCII numerals suffices (e. g. `42` instead of `*` \[[[*|asterisk]] has the numeric value 42\]).
60+
61+While `char` and `string` can be stored (sort of) directly, the numeric types `integer` and `real` are converted following certain rules. The rules are those, you normally write literals of such types within your (Standard) Pascal source code. However, some compilers’ `read` implementation (here FPC) allow additional formats:
62+
63+An integer’s hexadecimal base can be indicated by prepending `0x`, or just `x` (case insensitive) instead of the usual [[Dollar sign|$ (dollar sign)]].
64+
65+### Difference between `read` and `readLn`
66+
67+`ReadLn` will in contrast to `read` consume a trailing [[End of Line|line feed]]. It is discarded and does not have any influence on how to save supplied data. The read line ending is platform-independent. A line ending typical for Windows-platforms will be read and does not pose a problem, even if the program is run on [[Linux]] or any other platform.
68+
69+Note, the notion of “line” applies only for `text` files. Functions like [`eoLn`](https://www.freepascal.org/docs-html/rtl/system/eoln.html) and `readLn` only work on such files. In consequence `readLn` can not be used on typed files (`file of recordType` variables).
70+
71+## Production usage
72+
73+`Read` and `readLn` have a major drawback in that they expect the user to supply data in a given order. If users do not comply a run-time error will terminate the program.
74+
75+This is quite unsatisfactory, since a run-time error number won’t enlighten the end user. You usually want to design your error messages in a way the user is capable in correcting her behavior. When reading ordinal types one can make use of the [[Val|val procedure]].
76+
77+``` pascal
78+program readNumbers(input, output, stderr);
79+
80+{$modeSwitch out+}
81+
82+{**
83+ reads an integer from input
84+
85+ \param destination the variable to store the read value in
86+ \returns true if reading was successful
87+
88+ This function will inform the user about any mistakes.
89+*}
90+function readLnInteger(out destination: integer): longbool;
91+var
92+ /// temporarily stores input string
93+ userInput: ansistring;
94+ /// stores return code of val
95+ errorPosition: valSInt;
96+begin
97+ readLn(userInput);
98+
99+ val(userInput, destination, errorPosition);
100+
101+ // val is successful, if no character caused problems
102+ readLnInteger := errorPosition = 0;
103+
104+ // tell the user, what went wrong
105+ if not readLnInteger then
106+ begin
107+ if length(userInput) < 1 then
108+ begin
109+ writeLn('Error: There was no input.');
110+ end
111+ else
112+ begin
113+ writeLn('Error: Could not parse your input as an integer. Your input was:');
114+ writeLn(userInput);
115+
116+ // set an arrow right below
117+ // the character causing troubles
118+ writeLn(space(errorPosition-1), '⇡');
119+ writeLn('The character with an arrow underneath caused the troubles.');
120+
121+ if length(userInput) > bitSizeOf(nativeInt) then
122+ begin
123+ writeLn('Maybe your value is too large.');
124+ end;
125+ end;
126+ end;
127+end;
128+
129+{ === M A I N ================================================ }
130+var
131+ EOI: Boolean;
132+
133+function endOfInput(): Boolean;
134+begin
135+ EOI := system.eof();
136+ endOfInput := EOI;
137+end;
138+
139+var
140+ i: integer;
141+
142+begin
143+ repeat
144+ begin
145+ writeLn('Enter an integer:');
146+ end
147+ {$push}
148+ {$boolEval off} // lazy evaluation [until or_else is supported]
149+ until endOfInput() or readLnInteger(i) or endOfInput();
150+ {$pop}
151+
152+ if EOI then
153+ begin
154+ halt(1);
155+ end;
156+
157+ writeLn('Excellent choice!');
158+end.
159+```
160+
161+Beware, it is necessary to check, whether the end of file has been reached *before* attempting to read data. The `text` file `input` may not be open. Unlike `readLn` *no* default value is loaded. Hence it is imperative to check `val`’s `code` value in order to determine whether the destination variable `v` now has a legit value.
162+
163+Of course, it would be even better to catch wrong key strokes right when they are made, but this is not possible when utilizing `read` or `readLn`.
164+
165+> **Note:** Therefore the main application of `read` or `readLn` is non-interactive programs reading (generated) data files.
166+
167+Nevertheless, if the convenient interpretation functionality is desired, without having a file open, the procedure [`system.readStr`](https://www.freepascal.org/docs-html/rtl/system/readstr.html) can be used to do so.
168+
169+## See also
170+
171+- [`system.read`](https://www.freepascal.org/docs-html/rtl/system/read.html) and [`system.readLn`](https://www.freepascal.org/docs-html/rtl/system/readln.html)
172+- [[Why use Pascal|Why use Pascal, § “the readLn and writeLn effect”]]
173+- [[Secure programming]] regarding how to properly treat input
174+- [[Write|write]] performing the opposite action
175+
176+---
177+*From the Free Pascal wiki, page "Read", as it stood on 2020-08-23 after a change by Kai Burghardt, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
178+Category: Code

Back to history