* Help: need to prevent infinite loop
@ 2006-01-17 4:36 Shriramana Sharma
2006-01-17 7:14 ` Jesse Ruffin
0 siblings, 1 reply; 7+ messages in thread
From: Shriramana Sharma @ 2006-01-17 4:36 UTC (permalink / raw)
To: linux-c-programming
Hello. I have the following code:
#include "stdio.h"
int repeatinput;
int jday, jmon, jyear;
enum boolean { FALSE, TRUE };
void main(void)
{
do
{
repeatinput = FALSE;
printf("Date as YYYY-MM-DD : ");
if (scanf("%d-%d-%d", &jyear, &jmon, &jday) < 1) repeatinput = TRUE;
if (jyear < 1800 || jyear > 2399) repeatinput = TRUE;
if (repeatinput) printf ("Please enter a valid date.\n");
}
while (repeatinput);
printf ("Thanks for entering a valid date.\n");
}
If I compile it with gcc and execute it, and press an arrow key at the input
prompt and press enter, I get an infinite loop giving the date prompt and
saying "Please enter a valid date".
Wonder what's wrong with the code? Should not, at the second execution of the
loop, it wait for me to enter a correct input?
Thanks for your feedback.
--
Penguin #395953 resides at http://samvit.org
subsisting on SUSE Linux 10.0 with KDE 3.5
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Help: need to prevent infinite loop
2006-01-17 4:36 Help: need to prevent infinite loop Shriramana Sharma
@ 2006-01-17 7:14 ` Jesse Ruffin
2006-01-18 16:24 ` Shriramana Sharma
2006-01-22 10:20 ` Glynn Clements
0 siblings, 2 replies; 7+ messages in thread
From: Jesse Ruffin @ 2006-01-17 7:14 UTC (permalink / raw)
To: linux-c-programming
The problem is a general one that will affect many non digit characters.
scanf() on my computer returns 0, an early match error. But what you
probably don't expect, and I can't find in the info or man pages, is
that glibc scanf seems to unget() the input that it has read.
This means that that arrow gets put back in the stream, your program
loops, reads the same character again, and has the same matching errors
etc. etc. on into infinity.
What is you need to do is clear the stream between iterations.
This inelegant, but satisfactory, method fixes the problem:
#include "stdio.h"
int repeatinput;
int jday, jmon, jyear;
enum boolean { FALSE, TRUE };
/* Just large enough for YYYY-MM-DD + \n + \0 */
char buf[12];
void main(void)
{
do
{
repeatinput = FALSE;
printf("Date as YYYY-MM-DD : ");
/* Unequivocally get a whole line */
fgets(buf,12,stdin);
/* Scan the buffer instead */
if (sscanf(buf, "%d-%d-%d", &jyear, &jmon, &jday) < 1)
repeatinput = TRUE;
if (jyear < 1800 || jyear > 2399)
repeatinput = TRUE;
if (repeatinput)
printf ("Please enter a valid date.\n");
}
while (repeatinput);
printf ("Thanks for entering a valid date.\n");
}
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Help: need to prevent infinite loop
2006-01-17 7:14 ` Jesse Ruffin
@ 2006-01-18 16:24 ` Shriramana Sharma
2006-01-18 16:33 ` Steve Graegert
2006-01-22 10:20 ` Glynn Clements
1 sibling, 1 reply; 7+ messages in thread
From: Shriramana Sharma @ 2006-01-18 16:24 UTC (permalink / raw)
To: linux-c-programming
Tuesday, 17 January 2006 12:44 samaye, Jesse Ruffin alekhiit:
> This inelegant, but satisfactory, method fixes the problem:
> fgets(buf,12,stdin);
Thanks for your reply and sorry for the delay in mine.
The suggestion to use fgets reminded me of this gcc-generated warning with
gets:
samjnaa@linux:~/bin/learning> gcc -Wall -o gets gets.c
/tmp/ccA8bxgm.o: In function `main':
gets.c:(.text+0x25): warning: the `gets' function is dangerous and should not
be used.
Though I did not get such a warning with fgets, I wonder why this function is
considered dangerous. Could the same problem perhaps apply to fgets too and
gcc doesn't inform me of it?
--
Penguin #395953 resides at http://samvit.org
subsisting on SUSE Linux 10.0 with KDE 3.5
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Help: need to prevent infinite loop
2006-01-18 16:24 ` Shriramana Sharma
@ 2006-01-18 16:33 ` Steve Graegert
0 siblings, 0 replies; 7+ messages in thread
From: Steve Graegert @ 2006-01-18 16:33 UTC (permalink / raw)
To: linux-c-programming
On 1/18/06, Shriramana Sharma <samjnaa@gmail.com> wrote:
> Tuesday, 17 January 2006 12:44 samaye, Jesse Ruffin alekhiit:
>
> > This inelegant, but satisfactory, method fixes the problem:
> > fgets(buf,12,stdin);
>
> Thanks for your reply and sorry for the delay in mine.
>
> The suggestion to use fgets reminded me of this gcc-generated warning with
> gets:
>
> samjnaa@linux:~/bin/learning> gcc -Wall -o gets gets.c
> /tmp/ccA8bxgm.o: In function `main':
> gets.c:(.text+0x25): warning: the `gets' function is dangerous and should not
> be used.
>
> Though I did not get such a warning with fgets, I wonder why this function is
> considered dangerous. Could the same problem perhaps apply to fgets too and
> gcc doesn't inform me of it?
Shriramana,
As fgets(3), gets(3) reads into a buffer, but no check for buffer
overrun is performed, which can result in serious bugs. fgets(3) takes
the buffer size as the second argument and no more characters than
specified are written into the buffer.
\Steve
--
Steve Graegert <graegerts@gmail.com>
Software Consultant {C/C++ && Java && .NET}
Office: +49 9131 7123988
Mobile: +49 1520 9289212
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Help: need to prevent infinite loop
2006-01-17 7:14 ` Jesse Ruffin
2006-01-18 16:24 ` Shriramana Sharma
@ 2006-01-22 10:20 ` Glynn Clements
2006-01-22 11:28 ` Jesse Ruffin
1 sibling, 1 reply; 7+ messages in thread
From: Glynn Clements @ 2006-01-22 10:20 UTC (permalink / raw)
To: jesse; +Cc: linux-c-programming
Jesse Ruffin wrote:
> The problem is a general one that will affect many non digit characters.
>
> scanf() on my computer returns 0, an early match error. But what you
> probably don't expect, and I can't find in the info or man pages, is
> that glibc scanf seems to unget() the input that it has read.
It doesn't "unget" anything, it simply doesn't consume anything.
More generally, [f]scanf() only consumes the data which actually
matches the fields in the format string. The return value tells you
how many fields were assigned; if the return value is zero, nothing is
assigned and nothing is consumed.
--
Glynn Clements <glynn@gclements.plus.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Help: need to prevent infinite loop
2006-01-22 10:20 ` Glynn Clements
@ 2006-01-22 11:28 ` Jesse Ruffin
2006-01-23 5:57 ` Jesse Ruffin
0 siblings, 1 reply; 7+ messages in thread
From: Jesse Ruffin @ 2006-01-22 11:28 UTC (permalink / raw)
To: linux-c-programming
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
I had hoped to convey that the standard library uses an ungetc() like
operation on the data it acquires, hence the quotes. This does not
consume anything from the user's point of view, and my GNU libc (2.3.5)
does use ungetc() for [f]scanf in a macro form.
I'll have to go read the standard to make sure, but I don't see anywhere
that scanf has to put anything back after it gets it. My manual says
this to say generally:
| If processing of a directive fails, no further input is read, and
| scanf() returns. A "failure" can be either of the following: input
| failure, meaning that input characters were unavailable, or matching
| failure, meaning that the input was inappropriate (see below).
This says (to me at least) that input is read, then matched. if there is
no match it returns. I am curious if this non consumptive behavior is
specified in the standard. I would prefer a non consumptive version
myself as I assume that operations on a stream affect the state of the
stream, whether or not they succeed. You can always use the return code
to seek yourself back if necessary. Consumption also makes more sense
when applied to non seeking streams as the junk input (like in the code
under discussion) will get thrown out.
Jesse Ruffin
AJP Services
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
iD8DBQFD02xs8GGeAXLl3osRApIiAJ9Y9P+41L0yIPmp+DCyIvFNn0vX7QCfXfQW
+pqE6A8zCvgcgWQHSQp3mWo=
=OGj+
-----END PGP SIGNATURE-----
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Help: need to prevent infinite loop
2006-01-22 11:28 ` Jesse Ruffin
@ 2006-01-23 5:57 ` Jesse Ruffin
0 siblings, 0 replies; 7+ messages in thread
From: Jesse Ruffin @ 2006-01-23 5:57 UTC (permalink / raw)
To: linux-c-programming
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
The Standard I found, located at
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf
does state in section 7.19.6.2 Sec. 9:
An input item is read from the stream, unless the specification includes
an n specifier. An input item is defined as the longest sequence of
input characters which does not exceed any specified field width and
which is, or is a prefix of, a matching input sequence (^245). The first
character, if any, after the input item remains unread. If the length of
the input item is zero, the execution of the directive fails; this
condition is a matching failure unless end-of-file, an encoding error,
or a read error prevented input from the stream, in which case it is an
input failure.
However, Footnote 245 says the following:
245) fscanf pushes back at most one character onto the input stream.
Therefore some sequences that are acceptable to strtod, strtol, etc. are
unacceptable to fscanf.
So, although it SHOULD be non-consumptive, it MAY not in all cases,
although I haven't found one where it doesn't yet.
The standard also recommended the following method for looping through
stdin:
#include <stdio.h>
/* ... */
int count; float quant; char units[21]; char items[21];
do {
count = fscanf(stdin, "%f%20s of %20s", &quant, units, items);
fscanf(stdin, "%*[^n]"); /* This junks all input remaining */
} while (!feof(stdin) && !ferror(stdin));
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
iD8DBQFD1HA78GGeAXLl3osRAuWHAKCAhXqVwMiQ2lC5NA+cdd1sg9g1vACZAZPi
HN0wUvcR8Hp2aw5PFmMJnVY=
=V96c
-----END PGP SIGNATURE-----
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2006-01-23 5:57 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-01-17 4:36 Help: need to prevent infinite loop Shriramana Sharma
2006-01-17 7:14 ` Jesse Ruffin
2006-01-18 16:24 ` Shriramana Sharma
2006-01-18 16:33 ` Steve Graegert
2006-01-22 10:20 ` Glynn Clements
2006-01-22 11:28 ` Jesse Ruffin
2006-01-23 5:57 ` Jesse Ruffin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).