[comp.lang.pascal] TURBO Pascal READ

ZRWA001%DTUZDV1.BITNET@wiscvm.wisc.EDU (Helmut Waelder) (04/23/87)

Hi folks,
I'm using TURBO Pascal 3.01A on a Tandon AT under MS-DOS 3.1 .
The following program discovers a bug in turbos READ procedure:

(*$R+,U+,B-*)     (* I always use this directives *)
program readbug;
var r:real;
    a,b:char;
begin
readln(r,a,b);
writeln(r:8:3,a,b);
end.

The input line contains a real number and two characters:
12.34 ET
The output is:
  12.340 E
You will notice that the value of variable a is always a blank character and
an input of:
12.34ET
brings up an I/O error 10. So I think there must be always a blank after a
read of a number. But is this standard pascal? A simple way out of this is to
code   readln(r,a,a,b);  but it's not so easy to explain to the students in
the programming course why they have to do this.

Helmut
Acknowledge-To: Helmut Waelder <ZRWA001@DTUZDV1>

ken@rochester.ARPA (Ken Yap) (04/23/87)

Well, let me guess what is going on. When read sees 12.34E it thinks an
exponent is coming up. But the T invalidates that. It is possible to
design the input reader so that it pushes the E back onto the input
buffer when the T is seen. It's just that Turbo Pascal didn't implement
this. So, yes it's a bug.  Complain.

I just tested Berkeley pi and the program works correctly there.

	Ken

jfjr@mitre-bedford.arpa (04/23/87)

  I noticed similar behavior and wrote about it to info-ibmpc
last summer. MS-DOS screws up buffering input into pascal
programs (turbo-pascal) at least. I wrote a simple program

program test(input,output);

var ch:char;

begin
writeln('enter character');
read(ch);
writeln(ch);
end.

(its been a while since I wrote pascal so to anybody who will
remark on any syntax/semantic errors rest assured those battles
were fought last summer)

If you compile and run this with Turbo (com option)
and respond with a string say "abc", then the
program will run correctly the first time, echoing an a. The second time
you run it it will ignore you're input, whatever that may be and
echo a 'b'. This will go on until the string 'abc' including cr and lf
are consumed. I should back off a little. I havent tried it
since last summer and turbo and/or MS-DOS might have been fixed

since then but it drove me nuts then. The moral of this story
(I have had similar input buffering problems with stdin in
Micro-soft C) is that one should be very careful with 
standard input, console etc on an MS-DOS machine.

By the way it didn't seem to matter what compiler options I chose

                                       Jerry Freedman,Jr

Slomcenski.WBST@Xerox.COM (04/24/87)

>
>  I noticed similar behavior and wrote about it to info-ibmpc
>last summer. MS-DOS screws up buffering input into pascal
>programs (turbo-pascal) at least. I wrote a simple program
>
>program test(input,output);
>
>var ch:char;
>
>begin
>writeln('enter character');
>read(ch);
>writeln(ch);
>end.
>
>If you compile and run this with Turbo (com option)
>and respond with a string say "abc", then the
>program will run correctly the first time, echoing an a. The second time
>you run it it will ignore you're input, whatever that may be and
>echo a 'b'. This will go on until the string 'abc' including cr and lf
>are consumed. I should back off a little. I havent tried it
>since last summer and turbo and/or MS-DOS might have been fixed
>since then but it drove me nuts then. The moral of this story

In fact TURBO and/or MS-DOS aren't broke in this case! I believe that what
you are seeing is the fact that MS-DOS "remembers" up to 16 characters
typed at the keyboard in its internal type-ahead buffer. To guarantee that
one and only one char is read by the program, the internal type-ahead buffer
should be flushed by either an MS-DOS call (facilities to flush any remaining
keys is provided by MS-DOS), or by TURBO code like:

  while keypressed do read(ch);

The following should do what you expect it to:

program test(input,output);

var ch:char;

begin
while keypressed do read(ch); (* flush any old chars in kbd buffer *)
writeln('enter character');
read(ch);
writeln(ch);
end.

  ~Bob

Slomcenski.WBST@Xerox.COM (04/24/87)

>
>readln(r,a,b);
>writeln(r:8:3,a,b);
>
>

>The input line contains a real number and two characters:
>12.34 ET
>The output is:
>  12.340 E
>
>an input of:
>12.34ET
>brings up an I/O error 10.

The catch is that the format of a real may (or may not) contain the
scientific notation 'E+xx' or 'E-xx' following the digits. In the first
case, readln
interprets '12.34' as the real (the number terminates when TURBO finds
any
char that is not part of the real format, in this case ' '). In the
second
case, readln sees the scientific notation '12.34E' and expects the next
char to
be a '+', '-', or the digits indicating an exponent. When it encounters
the
'T' -- it generates the I/O error 10.

>So I think there must be always a blank after a read of a number.
>

Input of a number DOES NOT have to be followed by a ' '!! In fact, in
the
first case, the blank is interpreted as the value for the char variable
a.
The second case would have worked fine except that the char after the
digits happened to be 'E' which is STILL part of a real number
representation.

  ~Bob
  

ZRWA001%DTUZDV1.BITNET@WISCVM.WISC.EDU (04/24/87)

Hi folks,
I have seen: my example was mad. The problem is not the E after a integer
or real number, the problem is: every character immediatly after the last
digit of the number causes an I/O error except for the blank. And when I
read a character after a number, the only character I can get correctly is
a blank.
This is not a problem of the input buffer, this is a problem of the read
procedure of turbo. It's absolutely impossible to read a character other
than blank after a number. And this is *NOT* Standard Pascal.

Sorry for the stupid example with the 'E' after the real number :-)

Helmut
Acknowledge-To: Helmut Waelder <ZRWA001@DTUZDV1>

kvancamp@ARDEC.arpa (04/24/87)

>I don't care what
>anybody says about buffering, programs shouldn't behave
>that way. This kludgy MS-DOS buffering makes life real interesting
>when you are inheriting stdin and stdin has been redirected from
>a file.

I have to agree with this remark.  But then, Pascal never had any decent I/O 
to begin with -- just look at its unforgiving reads of reals.  That's why I 
(and most people I know who need to read numeric data in Pascal) use my own 
general-purpose input routine that reads a line of data as a string (using 
readln, not read), then evaluates it byte-by-byte to decode the answer in a 
reasonable way.  The one I use most is meant to read any number of reals, 
but is easily adapted to include chars.  It's a simple routine, but if 
anyone would like a copy let me know.  

		  --Ken Van Camp <kvancamp@ARDEC.ARPA>

bobmon@iuvax.UUCP (Che' Flamingo) (04/26/87)

Slomcenski.WBST@Xerox.COM writes:
>>
>>readln(r,a,b);
>>writeln(r:8:3,a,b);
>
>>The input line contains a real number and two characters:
>>12.34 ET
>>The output is:
>>  12.340 E
>>
>>an input of:
>>12.34ET
>>brings up an I/O error 10.
>
	[...]
>
>>So I think there must be always a blank after a read of a number.
>>
>
>Input of a number DOES NOT have to be followed by a ' '!! In fact, in the
>first case, the blank is interpreted as the value for the char variable a.
>The second case would have worked fine except that the char after the
>digits happened to be 'E' which is STILL part of a real number representation.

According to my v3.0 manual (p.109),

    With a numeric variable (Integer or Real), Read expects a string of
    characters which complies with the format of a numeric constant of the
    relevant type as defined on page 43. [ e.g., exponents -- RAM]  Any blanks,
    TABs, CRs, or LFs preceding the string are skipped.  The string must be no
    longer than 30 characters, **and it must be followed by a blank, a TAB, a 
    CR, or a Ctrl-Z.  If the string does not conform to the expected format, an 
    I/O error occurs.** [emphasis is mine -- RAM]

As far as I can see, you must either use a dummy variable to absorb the blank,
or (if you know how long the number is and it's REALLY important) read the
number as a character string and parse it yourself.  Or terminate the number
with a carriage-return.

~-~-~-~-~
RAMontante		bobmon@iuvax.cs.indiana.edu  -OR-  {?}!iuvax!bobmon
Computer Science
Indiana University				"Have you hugged ME today?"