> Ada.Text_IO.Get is defined to read only legal characters; if it raises an
> exception it reads NOTHING. Therefore, the illegal characters remain in the
> input stream; if you do the same read again, you'll get the same error
> (because the same characters are still there).
Just a clarification here. It depends a bit more on the situation
than Randy focused on. Let's take the case of an enumeration type
type Colors is (red, green, blue);
Now instantiate Ada.Text_IO.Enumeration_IO for this type:
package Color_IO is new Ada.Text_IO.Enumeration_IO (Enum => Colors);
Now Color_IO.Get will try to read valid Colors tokens. But this is
a 2-stage process: first read a token _syntactically_, then check
whether it's within the Colors type. If _either_
(1) Get cannot read a valid token, _or_
(2) Get did read a token that was syntactically valid but not in Colors,
Get raises Ada.Text_IO.Data_Error.
Suppose the input pointer is looking at
since an enumeration token can;t begin with a digit, Data_Error is
raised. The RM _requires_ that the character that causes input to cease
must remain in the input stream. In this case, it was the 1, so nothing
Now suppose the input pointer is looking at
this token is syntactically valid, but not in Colors. The
character that causes input to cease is the <enter>. Why? Well,
to know that the token was bad, Get had to read the token! All
very logical. Trouble is, here as well, Data_Error is raised!
So the same exception is raised for "syntactic" as well as "semantic"
invalidity. So the client program gets no info as to whether the
token was consumed or not.
Analogous examples can be given for numeric tokens, but the enum ones
make it really obvious what's going on.
I run into this with students all the time. I advise them to use the
Skip_Line hack for simple cases where ditching the line is OK.
For real "industrial strength" interactive input, AFAIK there is no
general alternative to reading a line into a string (using Get_Line),
then parsing the tokens yourself. Of course, the IO libs help here
by providing a Get-from-string that behaves like the file one.
The difference is that now your program "owns" the string, and
can handle an exception by resorting to a char-by-char parse.
Even this doesn;t solve it entirely, because a string is, by
definition, an array of _Character_, and if the *&^%$ thing in
the input is not in Character, I think you're back to Rick's problem.
> This behavior was defined in Ada 83, and Ada 95 left it alone for
> compatibility purposes. This is the number one not-a-bug bug report that we
> get here at RRS, and I wish it had been defined more intuitively...
Interesting. The original edition of Booch's "Software Engineering
with Ada" (1983) contained an example of an input loop with exception
handler. But he had no reliable compiler to test with, so the example
did not include the Skip_Line. I can remember reading e-mail
threads just like this one 15 years ago - everyone thought their
compilers were junk, but in fact it was Booch's example that was junk.
Needless to say, he corrected the error in his next reprint!
A REALLY GOOD discussion of interactive input would be a contribution
to us all. Maybe we can craft one as a group here, and put it on the