When used separately,
get_line rarely cause issues. When used together, there can be some issues. Consider the following code:
a : integer; s : string(1..4); get(a); s := get_line; put(a); put_line(s);
Here is the dialog obtained when running the program containing this code:
4 raised CONSTRAINT_ERROR : testgetm.adb:14 length check failed
It allows the user to input the number 4, but then balks and pulls an exception. What went wrong? To see what happened we have to consider exactly what these input functions do. As we have seen, calls to
get for numeric and string input skip over blanks and line terminators that come before the number. That’s why it is possible to press the <return> key several times between numbers being entered. However these
get functions do not skip over any blanks and line terminators that come after the number. After the integer variable
a is read, the input pointer is set to the line terminator after 4.
get_line stops reading when it encounters a line terminator, it stops and sets the length of the string to zero to indicate a null string. As the size of the (fixed) string is expected to be 4 characters in length, an exception is actioned. One way to circumvent this is to type the string on the same line as the number 4. For example:
This illustrates another feature of numeric input. The
get function for numeric data stops reading when a non-numeric character is encountered. The non-numeric character “t” is not read and is still available to be read by the next call to an input function.
This solution is not really optimal. A better idea is to use the function
skip_line is called, it moves the input pointer to the next line. It is most useful when using a
get_line function after getting a numeric value. Here is an example of its use:
a : integer; s : string(1..4); get(a); skip_line; s := get_line; put(a); put_line(s);
Note that if we use a
unbound_string instead of the fixed string, then the program will not convulse, but it also will skip the string input… but it will print out a string. Why? Well the
unbound_string will actually store the line terminator in the string… so it does read something, just not what it wanted.
To make things more consistent, it is also possible to read all input in as strings using
get_line, and convert the string to numbers. Below is an example of the code. The first value is input to the
buf, which is then converted to a string, and then an integer, and assigned to the integer variable
a : integer; buf : unbounded_string; buf := get_line; a := integer'value(to_string(buf)); buf := get_line; put(a); put_line(buf);
Note that weird things can also occur when using consecutive
get_line() statements. For example consider the code:
s,t : string(1..4); get_line(s,len); put(s); put(len); get_line(t,len); put(t); put(len);
Here is an example of it running:
tool tool 4�# 0
The first string input “tool”. works, the second string reads in the line terminator. The same does not occur using the alternate form of
get_line. For example the code below works as it should.
s,t : string(1..4); s := get_line; put(s); t := get_line; put(t);