Read: Difference between revisions

From Free Pascal wiki
Jump to navigationJump to search
(partially undo revision 133032 by Trev (talk); (ensure h1 is page title, and h2 headings are subsections of the page) cf. discussion)
(typos; review links; mention readStr)
Line 18: Line 18:


As an optional first parameter a <syntaxhighlight lang="pascal" inline>text</syntaxhighlight> variable can be specified where data are read from.
As an optional first parameter a <syntaxhighlight lang="pascal" inline>text</syntaxhighlight> variable can be specified where data are read from.
<syntaxhighlight lang="pascal" inline>Read</syntaxhighlight> is additionally capable of reading from a [[File|typed <syntaxhighlight lang="pascal" inline>file</syntaxhighlight>]] variable (<syntaxhighlight lang="pascal" inline>file of recordType</syntaxhighlight>).
<syntaxhighlight lang="pascal" inline>Read</syntaxhighlight> is additionally capable of reading from a [[typed files|typed <syntaxhighlight lang="pascal" inline>file</syntaxhighlight>]] variable (<syntaxhighlight lang="pascal" inline>file of recordType</syntaxhighlight>).


If no source is specified, [[Input|<syntaxhighlight lang="pascal" inline>input</syntaxhighlight>]] is assumed.
If no source is specified, [[Input|<syntaxhighlight lang="pascal" inline>input</syntaxhighlight>]] is assumed.
Line 25: Line 25:


Earlier versions of [[FPC]] also allowed reading variables of the type [[PChar|<syntaxhighlight lang="pascal" inline>PChar</syntaxhighlight>]]. This has been removed, since no buffer checking is possible with those.
Earlier versions of [[FPC]] also allowed reading variables of the type [[PChar|<syntaxhighlight lang="pascal" inline>PChar</syntaxhighlight>]]. 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's record type can be specified.
In the case of typed files as source, only variables of the [[File|file’s]] record type can be specified.


=== Execution ===
=== Execution ===
Line 57: Line 57:
</syntaxhighlight>
</syntaxhighlight>


will yield a [[Run-time error|run-time error]] (in this case RTE 106).
will yield a [[runtime error|run-time error]] (in this case RTE 106).


Once data are read and stored, they are “consumed”, thus cannot be retrieved otherwise, but via the variables only.
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.
However, data are read up to the variable’s size limits.
E.g. a fixed length <syntaxhighlight lang="pascal" inline>string[24]</syntaxhighlight> will stop reading beyond the 24th character.
E.&#8239;g. a fixed length <syntaxhighlight lang="pascal" inline>string[24]</syntaxhighlight> will stop reading beyond the 24th character.


Leading blanks in front of numeric types are skipped.
Leading blanks in front of numeric types are skipped.
Line 70: Line 70:


<syntaxhighlight lang="pascal" inline>Read</syntaxhighlight> and <syntaxhighlight lang="pascal" inline>readLn</syntaxhighlight> are so powerful, because they interpret given data.
<syntaxhighlight lang="pascal" inline>Read</syntaxhighlight> and <syntaxhighlight lang="pascal" inline>readLn</syntaxhighlight> are so powerful, because they interpret given data.
For instance, a <syntaxhighlight lang="pascal" inline>readLn</syntaxhighlight> storing an integer does not expect the binary value to be entered, but their decimal representation with ASCII numerals suffices (e.g. <syntaxhighlight lang="text" inline>42</syntaxhighlight> instead of <syntaxhighlight lang="text" inline>*</syntaxhighlight> [<nowiki></nowiki>[[*#other appearances|asterisk]] has the numeric value 42]).
For instance, a <syntaxhighlight lang="pascal" inline>readLn</syntaxhighlight> storing an integer does not expect the binary value to be entered, but their decimal representation with ASCII numerals suffices (e.&#8239;g. <syntaxhighlight lang="text" inline>42</syntaxhighlight> instead of <syntaxhighlight lang="text" inline>*</syntaxhighlight> [<nowiki></nowiki>[[*#other appearances|asterisk]] has the numeric value 42]).


While <syntaxhighlight lang="pascal" inline>char</syntaxhighlight> and <syntaxhighlight lang="pascal" inline>string</syntaxhighlight> can be stored (sort of) directly, the numeric types <syntaxhighlight lang="pascal" inline>integer</syntaxhighlight> and <syntaxhighlight lang="pascal" inline>real</syntaxhighlight> are converted following certain rules.
While <syntaxhighlight lang="pascal" inline>char</syntaxhighlight> and <syntaxhighlight lang="pascal" inline>string</syntaxhighlight> can be stored (sort of) directly, the numeric types <syntaxhighlight lang="pascal" inline>integer</syntaxhighlight> and <syntaxhighlight lang="pascal" inline>real</syntaxhighlight> are converted following certain rules.
The rules are those, you normally write literals of such types within your [[Standard Pascal|(Standard) Pascal]] source code.
The rules are those, you normally write literals of such types within your (Standard) Pascal source code.
However, some compiler's <syntaxhighlight lang="pascal" inline>read</syntaxhighlight> implementation (here FPC) allow additional formats:
However, some compiler’s <syntaxhighlight lang="pascal" inline>read</syntaxhighlight> implementation (here FPC) allow additional formats:


An integer's hexadecimal base can be indicated by prepending <syntaxhighlight lang="text" inline>0x</syntaxhighlight>, or just <syntaxhighlight lang="text" inline>x</syntaxhighlight> (case insensitive) instead of the usual [[Dollar sign|<syntaxhighlight lang="text" inline>$</syntaxhighlight> (dollar sign)]].
An integer’s hexadecimal base can be indicated by prepending <syntaxhighlight lang="text" inline>0x</syntaxhighlight>, or just <syntaxhighlight lang="text" inline>x</syntaxhighlight> (case insensitive) instead of the usual [[Dollar sign|<syntaxhighlight lang="text" inline>$</syntaxhighlight> (dollar sign)]].


=== Difference between <syntaxhighlight lang="pascal" inline>read</syntaxhighlight> and <syntaxhighlight lang="pascal" inline>readLn</syntaxhighlight> ===
=== Difference between <syntaxhighlight lang="pascal" inline>read</syntaxhighlight> and <syntaxhighlight lang="pascal" inline>readLn</syntaxhighlight> ===
Line 94: Line 94:
If users do not comply a run-time error will terminate the program.
If users do not comply a run-time error will terminate the program.


This is quite unsatisfactory, since a run-time error number won't enlighten the end user.
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.
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|<syntaxhighlight lang="pascal" inline>val</syntaxhighlight> procedure]].
When reading ordinal types one can make use of the [[Val|<syntaxhighlight lang="pascal" inline>val</syntaxhighlight> procedure]].
Line 156: Line 156:


{{Note|Therefore the main application of <syntaxhighlight lang="pascal" inline>read</syntaxhighlight> or <syntaxhighlight lang="pascal" inline>readLn</syntaxhighlight> is non-interactive programs reading (generated) data files.}}
{{Note|Therefore the main application of <syntaxhighlight lang="pascal" inline>read</syntaxhighlight> or <syntaxhighlight lang="pascal" inline>readLn</syntaxhighlight> is non-interactive programs reading (generated) data files.}}
Nevertheless, if the convenient interpretation functionality is desired, without having a file open, the procedure {{Doc|package=RTL|unit=system|identifier=readstr|text=<syntaxhighlight lang="pascal" inline>system.readStr</syntaxhighlight>}} can be used to do so.


== See also ==
== See also ==

Revision as of 18:40, 24 May 2020

Deutsch (de) English (en)

The procedures read and readLn retrieve a date from a text file. They are defined as part of the Pascal programming language. Everyone can expect them to work no matter which compiler has been used.

In property definitions the reserved word read is used to direct read access. This article deals with the procedures read and readLn. See object and related articles for the occurrence of read in the context of properties.

Behavior

Signature

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:

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 file variable (file of recordType).

If no source is specified, 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, integer, real, or string.

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’s record type can be specified.

Execution

Calling read/readLn will place the read (and possibly accordingly interpreted) values to the given variables.

The order of variables matters. For instance, when the following program:

program readDemo(input, output, stderr);
var
	i: integer;
	c: char;
begin
	readLn(i, c);
end.

is supplied with:

42 x

everything is fine.

i will become 42 and c will become 'x'. But the reverse input order

x 42

will yield a run-time error (in this case RTE 106).

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.

Leading blanks in front of numeric types are skipped.

If no data is available, possibly because the end of file has already been reached, default values for the remaining variables are loaded.

Interpretation

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]).

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 compiler’s read implementation (here FPC) allow additional formats:

An integer’s hexadecimal base can be indicated by prepending 0x, or just x (case insensitive) instead of the usual $ (dollar sign).

Difference between read and readLn

ReadLn will in contrast to read consume a trailing 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.

Note, the notion of “line” applies only for text files. Functions like eoLn and readLn only work on such files. In consequence readLn can not be used on typed files (file of recordType variables).

Production usage

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.

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 procedure.

program readNumbers(input, output, stderr);

{$modeSwitch out+}

{**
	reads an integer from input
	
	\param destination the variable to store the read value in
	\returns true if reading was successful
*}
function readLnInteger(out destination: integer): longbool;
var
	/// temporarily stores input string
	userInput: ansistring;
	/// stores return code of val
	errorPosition: valSInt;
begin
	readLn(userInput);
	val(userInput, destination, errorPosition);
	
	// val is successful, if no character caused problems
	readLnInteger := errorPosition = 0;
	
	if not readLnInteger then
	begin
		// set an arrow right below
		// the character causing troubles
		writeLn(space(errorPosition-1), '⇡');
	end;
end;

{ === M A I N ================================================ }
var
	i: integer;
begin
	repeat
	begin
		writeLn('Enter an integer:');
	end
	{$push}
	{$boolEval off} // lazy evaluation
	until eof() or readLnInteger(i);
	{$pop}
	
	if eof() then
	begin
		halt(1);
	end
end.

Beware, it is necessary to check for end of file. Unlike readLn no default value is loaded.

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.

Light bulb  Note: Therefore the main application of read or readLn is non-interactive programs reading (generated) data files.

Nevertheless, if the convenient interpretation functionality is desired, without having a file open, the procedure system.readStr can be used to do so.

See also