www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2000/09/27/12:55:18

Date: Wed, 27 Sep 2000 19:54:54 +0200
From: "Eli Zaretskii" <eliz AT is DOT elta DOT co DOT il>
Sender: halo1 AT zahav DOT net DOT il
To: Solaryn AT hotmail DOT com
Message-Id: <3405-Wed27Sep2000195453+0300-eliz@is.elta.co.il>
X-Mailer: Emacs 20.6 (via feedmail 8.2.emacs20_6 I) and Blat ver 1.8.5h
CC: djgpp-workers AT delorie DOT com
In-reply-to: <200009241000.GAA12654@delorie.com> (dj@delorie.com)
Subject: Re: DJGPP Bug Activity
References: <200009241000 DOT GAA12654 AT delorie DOT com>
Reply-To: djgpp-workers AT delorie DOT com
Errors-To: nobody AT delorie DOT com
X-Mailing-List: djgpp-workers AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

> Date: Sun, 24 Sep 2000 06:00:10 -0400
> From: "DJ's Server" <dj AT delorie DOT com>
>
> /* Start : test.c */
> #include <stdio.h>
> #include <string.h>
> 
> int main (void) {
>   char input [80];
>   int done = 0;
> 
>   while (! done) {
>     scanf ("%79[^\n]", input);
>     printf ("Input: %s\n", input);
>     if (! strcmp (input, "QUIT"))
>        done = 1;
>   }
>   return (0);
> }
> /* End   : test.c */
> 
> Compiled with: gcc -o test.exe test.c
> 
> I don't claim to know scanf all that well.  However, in all the cases that I
> have used ?scanf, it has accepted %[\^n] or %[\^n]s (with or without the width
> value) to denote reading a string until a \n (newline) is reached (or when
> included, the width is exceeded).  Under this instance, however, as soon as the
> enter key is pressed in the above example (regardless of input; although I have
> not had time to attempt every possible permutation), the loop will repeatedly
> pass the first entry to any successive calls to scanf, causing it to ignore any
> new input (this does occur outside loops as well).

This is not a bug, but a well-documented requirement of ANSI C
Standard.  The relevant excerpts (taken from the Draft C9X Standard,
section 7.19.6.2, "The fscanf function") are:

  12  The conversion specifiers and their meanings are:
      ...
      `['  Matches a nonempty sequence of characters from a set of
	   expected characters (the "scanset").
      ...
  16  Trailing whitespace (including new-line characters) is left
      unread unless matched by a directive.
  17  If conversion terminates on a conflicting input character, the
      offending input character is left unread in the input stream.

So, in this case, `scanf' reads everything up to the first new-line,
but leaves the new-line in the buffer.  The next pass through the loop
sees only that buffered new-line, which doesn't match "%[^\n]", and so
is again left in the buffer, thus causing an infinite loop.  You can
see that `scanf' didn't convert anything by examining its return
value: it is zero for all the passes through the loop but the first
one.

To get the behavior you want (a single line read for each pass through
the loop), either call "getc(stdin)" after `scanf' (to consume the
new-line character), or change the format specifier to "%79[^\n]%*1[\n]".
The latter causes `scanf' to read the string up to the new-line and
then read and discard exactly one new-line.

> For the record, the Borland compiles Turbo C 3.0 and Borland C 4.5
> did not have this problem, so this is being made with that limited
> reference.  The scanf documentation also seems to support the
> operation I received under the above mentioned compilers.

I tested this with Turbo C 2.0 and on 2 Unix systems (Irix and Linux),
and got the exact behavior as with DJGPP.  So I cannot reproduce a
different behavior you saw with Borland 3.0 and 4.5; are you sure you
ran the exact same program?

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019