Read: Difference between revisions

From Free Pascal wiki
Jump to navigationJump to search
mNo edit summary
(review, expand)
Line 1: Line 1:
{{read}}
{{read}}
<br>
'''Read''' is one of the [[standard]] procedures in the [[Pascal]] programming language.  It is used to accept input from a [[File|file]].  The format is


Read (&#91;filename],variable1 &#91;, variable2 ...]);
The procedures <syntaxhighlight lang="pascal" enclose="none">read</syntaxhighlight> and <syntaxhighlight lang="pascal" enclose="none">readLn</syntaxhighlight> retrieve a date from a [[Text|<syntaxhighlight lang="pascal" enclose="none">text</syntaxhighlight> file]].
They are defined as part of the [[Pascal]] programming language.
Everyone can expect them to work no matter which compiler has been used.


Where
== behavior ==
*&#91;filename] is an optional parameter, indicating the [[file variable]] to read  data from
=== signature ===
*variable1 is the first [[Variable|variable]] to read data into
<syntaxhighlight lang="pascal" enclose="none">Read</syntaxhighlight> as well as <syntaxhighlight lang="pascal" enclose="none">readLn</syntaxhighlight> share the same formal signature.
*&#91;, variable2] is an optional second variable to read more data into
As an optional first parameter a <syntaxhighlight lang="pascal" enclose="none">text</syntaxhighlight> variable can be specified where data are read from.
*... indicates more variables may be added
If none is specified, [[Input|<syntaxhighlight lang="pascal" enclose="none">input</syntaxhighlight>]] is assumed.
Thereafter any number of variables can be specified, but at least one has to be present.
They have to be either [[Char|<syntaxhighlight lang="pascal" enclose="none">char</syntaxhighlight>]], [[Integer|<syntaxhighlight lang="pascal" enclose="none">integer</syntaxhighlight>]], [[Real|<syntaxhighlight lang="pascal" enclose="none">real</syntaxhighlight>]], or [[String|<syntaxhighlight lang="pascal" enclose="none">string</syntaxhighlight>]].
Earlier versions of [[FPC]] also allowed reading variables of the type [[PChar|<syntaxhighlight lang="pascal" enclose="none">PChar</syntaxhighlight>]].
This has been removed, since no buffer checking is possible with those.


The read procedure checks the type of variables which have been passed to it and accepts input from the specified file variable and places it into that variable.
=== execution ===
Calling <syntaxhighlight lang="pascal" enclose="none">read</syntaxhighlight>/<syntaxhighlight lang="pascal" enclose="none">readLn</syntaxhighlight> will place the read (and possibly accordingly interpreted) values to the given variables.


If no file variable is specified, the file variable [[input]] is used.
The order of variables matters. For instance, when the following program
<syntaxhighlight lang="pascal">
program readDemo(input, output, stderr);
var
i: integer;
c: char;
begin
readLn(i, c);
end.</syntaxhighlight>
is supplied with
<syntaxhighlight lang="text">
42 x
</syntaxhighlight>
everything is fine.
<syntaxhighlight lang="pascal" enclose="none">i</syntaxhighlight> will become <syntaxhighlight lang="pascal" enclose="none">42</syntaxhighlight> and <syntaxhighlight lang="pascal" enclose="none">c</syntaxhighlight> will become <syntaxhighlight lang="pascal" enclose="none">'x'</syntaxhighlight>.
But the reverse input order
<syntaxhighlight lang="text">
x 42
</syntaxhighlight>
will yield a [[Run-time error|run-time error]] (in this case RTE 106).


If the variable is a [[Char|char]]acter, an array of characters, or a string, the characters will be read up to the size limit of the variable.
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 <syntaxhighlight lang="pascal" enclose="none">string[24]</syntaxhighlight> will stop reading beyond the 24th character.


If the variable is a numeric variable such as an [[Integer|integer]], or [[Real|real]], the read procedure will ignore any leading blanks, and will read in characters until an invalid character for the type of variable is found, and it will then stop reading for that variable.  For example, for an integer, it will stop reading if a decimal point or any other non-number is found in the input stream.
Leading blanks in front of numeric types are skipped.


For a real variable, a decimal point and the letter "E" followed by an optional + or -, and an exponent, may be used.
If no data is available, possibly because the end of file has already been reached, default values for the remaining variables are loaded.


If the first non-blank which is to be read by a numeric variable is not a +, - or a digit, a run-time error occurs.
=== interpretation ===
<syntaxhighlight lang="pascal" enclose="none">Read</syntaxhighlight> and <syntaxhighlight lang="pascal" enclose="none">readLn</syntaxhighlight> are so powerful, because they interpret given data.
For instance, a <syntaxhighlight lang="pascal" enclose="none">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" enclose="none">42</syntaxhighlight> instead ).


If [[eof]] occurs on the file variable passed to the read procedure, a run-time error occurs.
While <syntaxhighlight lang="pascal" enclose="none">char</syntaxhighlight>, <syntaxhighlight lang="pascal" enclose="none">string</syntaxhighlight> and <syntaxhighlight lang="pascal" enclose="none">PChar</syntaxhighlight> can be stored more or less directly, the numeric types <syntaxhighlight lang="pascal" enclose="none">integer</syntaxhighlight> and <syntaxhighlight lang="pascal" enclose="none">real</syntaxhighlight> are converted following certain rules.
The rules are those, you normally write literals of such types within your Pascal source code.
However, some compiler's (here FPC) allow additional formats:


The Read procedure will continue reading from the file variable until the amount of data requested has been satisfied, or an [[eof]] is detected.  The read procedure generally stops when an [[eol]] is detected.
An integer's hexadecimal base can be indicated by prepending <syntaxhighlight lang="text" enclose="none">0x</syntaxhighlight>, <syntaxhighlight lang="text" enclose="none">0X</syntaxhighlight> or just <syntaxhighlight lang="text" enclose="none">x</syntaxhighlight> and <syntaxhighlight lang="text" enclose="none">X</syntaxhighlight> instead of the usual [[Dollar sign|<syntaxhighlight lang="text" enclose="none">$</syntaxhighlight> (dollar sign)]].


The '''readln''' procedure (note the '''ln''' at the end) behaves the same as read, except it absorbs the end of line character(s) as part of the text stream; they are ignored and '''not''' considered part of the data read.
=== difference between <syntaxhighlight lang="pascal" enclose="none">read</syntaxhighlight> and <syntaxhighlight lang="pascal" enclose="none">readLn</syntaxhighlight> ===
<syntaxhighlight lang="pascal" enclose="none">ReadLn</syntaxhighlight> will in contrast to <syntaxhighlight lang="pascal" enclose="none">read</syntaxhighlight> consume a trailing [[End of Line|line feed]].
The read line ending is platform-independent.
A line ending typical for Windoze-platforms will be read and does not pose a problem, even if the program is run on [[Linux]] or any other platform.


[[Category:File Handling]]
== production usage ==
[[category:Pascal]]
<syntaxhighlight lang="pascal" enclose="none">Read</syntaxhighlight> and <syntaxhighlight lang="pascal" enclose="none">readLn</syntaxhighlight> have a major drawback in that they expect the user to supply data in a given order.
If they 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 {{Doc|package=RTL|unit=system|identifier=val|text=<syntaxhighlight lang="pascal" enclose="none">val</syntaxhighlight> procedure}}.
<syntaxhighlight lang="pascal" line highlight="17">
program readNumbers(input, output, stderr);
 
{**
reads an integer from input
\param destination the variable to store the read value in
\returns true if reading was successful
*}
function readLnInteger(var 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
until eof() or readLnInteger(i);
if eof() then
begin
halt(1);
end
end.
</syntaxhighlight>
Beware, it is necessary to check for end of file.
Unlike <syntaxhighlight lang="pascal" enclose="none">readLn</syntaxhighlight> no default value is loaded.
 
== see also ==
* {{Doc|package=RTL|unit=system|identifier=read|text=<syntaxhighlight lang="pascal" enclose="none">system.read</syntaxhighlight>}} and {{Doc|package=RTL|unit=system|identifier=readln|text=<syntaxhighlight lang="pascal" enclose="none">system.readLn</syntaxhighlight>}}
* [[Why use Pascal#The Readln and Writeln effect|Why use Pascal, § “the <syntaxhighlight lang="pascal" enclose="none">readLn</syntaxhighlight> and <syntaxhighlight lang="pascal" enclose="none">writeLn</syntaxhighlight> effect”]]
 
[[Category:Code]]

Revision as of 21:56, 7 November 2018

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.

behavior

signature

Read as well as readLn share the same formal signature. As an optional first parameter a text variable can be specified where data are read from. If none 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.

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

While char, string and PChar can be stored more or less 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 Pascal source code. However, some compiler's (here FPC) allow additional formats:

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

difference between read and readLn

ReadLn will in contrast to read consume a trailing line feed. The read line ending is platform-independent. A line ending typical for Windoze-platforms will be read and does not pose a problem, even if the program is run on Linux or any other platform.

production usage

Read and readLn have a major drawback in that they expect the user to supply data in a given order. If they 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);

{**
	reads an integer from input
	
	\param destination the variable to store the read value in
	\returns true if reading was successful
*}
function readLnInteger(var 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
	until eof() or readLnInteger(i);
	
	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.

see also