scanf behaviour

M

mdbenchrifa

(e-mail address removed) a écrit :
Hello.

I maybe reinvent the weel ...
I'm trying to read positive integer number with the help of scanf, if
the input value is not positive number but negaive one zero or char , i
have to reread the input until I get the needed pos. number

I wrote the code , but it doesn't work the way it should : if i put
some char into input, the program goes infinite loop instead of
promting me to enter a new value.

Please shed some light on what is the problem. thanks
Code:
#include <stdio.h>

int main()
{
	int n;
	while (1)
	{
		printf("Please enter positive number \n");
		if ( scanf("%d",&n)!=1 || n<=0 )
		{
			printf("Illegal input!\n");
			continue;
		}

	return 0;
	}
return 1;
}

Just add gets(str) like
int main()
{
int n;
char str[10];
while (1)
{
printf("Please enter positive number \n");
scanf("%d",&n);
if ( n<=0 )
{
printf("Illegal input!\n");
gets(str);
continue;
}


return 0;
}

system("PAUSE");
return 1;
}
 
R

Richard Heathfield

(e-mail address removed) said:

Just add gets(str)

While you're at it, drive to the hottest crime-spot you can find, wind down
the driver's window of your car, leave the keys in the ignition, and go for
a six-hour walk.
 
G

Guest

(e-mail address removed) a écrit :
[...]
I wrote the code , but it doesn't work the way it should : if i put
some char into input, the program goes infinite loop instead of
promting me to enter a new value.

Please shed some light on what is the problem. thanks
Code:
#include <stdio.h>

int main()
{
	int n;
	while (1)
	{
		printf("Please enter positive number \n");
		if ( scanf("%d",&n)!=1 || n<=0 )
		{
			printf("Illegal input!\n");
			continue;
		}[/QUOTE]
[...]
Just add gets(str) like[/QUOTE]

Please take a look at http://c-faq.com/stdio/getsvsfgets.html
 
D

Dik T. Winter

> Ian Collins said:
>
> But in C, it isn't, and we discuss C here, not Solaris.

It is also not on Solaris, at least not on the version I am using
(SunOS 5.8). Can Ian Collins can tell me were it is defined. It
is not in the man page for fflush on the system I use.
 
I

Ian Collins

Dik said:
It is also not on Solaris, at least not on the version I am using
(SunOS 5.8). Can Ian Collins can tell me were it is defined. It
is not in the man page for fflush on the system I use.

From 5.9 onwards.
 
D

Dik T. Winter

>
> From 5.9 onwards.

So your statement:
"This non-standard behaviour probably goes back to pre-standard days and
should be avoided in portable code."
is nonsense?
 
A

Alan Curry

So your statement:
"This non-standard behaviour probably goes back to pre-standard days and
should be avoided in portable code."
is nonsense?

Using http://www.freebsd.org/cgi/man.cgi we can see that fflush on input
streams was defined with useful semantics in SunOS 4.1.3 (the earliest
version available there, from 1990) and still has the same definition in
recent versions. There was a period from 5.6 to 5.8 where the description was
omitted from the man page.
 
I

Ian Collins

Alan said:
Using http://www.freebsd.org/cgi/man.cgi we can see that fflush on input
streams was defined with useful semantics in SunOS 4.1.3 (the earliest
version available there, from 1990) and still has the same definition in
recent versions. There was a period from 5.6 to 5.8 where the description was
omitted from the man page.
Thanks, I thought that was the case, but I couldn't find the reference.
 
D

Dik T. Winter

> >
> >
> > Using http://www.freebsd.org/cgi/man.cgi we can see that fflush on input
> > streams was defined with useful semantics in SunOS 4.1.3 (the earliest
> > version available there, from 1990) and still has the same definition in
> > recent versions. There was a period from 5.6 to 5.8 where the description was
> > omitted from the man page.
> >
> Thanks, I thought that was the case, but I couldn't find the reference.[/QUOTE]

From the SunOS 5.10 manpage:
"If stream points to an input stream or an update stream into which the
most recent operation was input, that stream is flushed if it is
seekable and is not already at end-of-file."
No flushing if the stream is not seekable (so not for a pipe, FIFO, socket
or TTY device).
 
S

Simon Biber

CBFalconer said:
It can be built around the routines I showed. The only problem is
with exponential notation, otherwise 1 char lookahead does fine.
The problem case is: "1.23ex" which requires 2 char lookahead, or 2
level ungetc. scanf suffers from this too.

scanf needs 3 char ungetc to handle "1.23e-x". The 'x', '-' and 'e' are
read and then put back into the buffer. The next character read should
be 'e'.

I tested with this program:

#include <stdio.h>

int main(void)
{
float f = 0.0f;
int r, c;
r = scanf("%f", &f);
c = getchar();
printf("converted %d args, got value %f, next char is %c\n", r, f, c);
return 0;
}

Run as:
gcc 123ex.c -o 123ex
echo 1.23e-x | ./123ex
Or equivalent with the respective compiler.

The scanf in Solaris's C library, FreeBSD's C library and Cygwin's
newlib C library handle this properly, ungetcing 3 characters, so the
next character read is 'e'.

Linux's glibc C library and DJGPP's C library, Microsoft Visual C++,
LCC-Win32, Borland C++ and Turbo C all only manage to ungetc one
character, so the next character read is 'x'.
 
C

CBFalconer

Simon said:
scanf needs 3 char ungetc to handle "1.23e-x". The 'x', '-' and 'e'
are read and then put back into the buffer. The next character read
should be 'e'.

Unfortunately the C standard only guarantees one level, so this
action is impossible in portable code. It can't be grafted on
after the fact because any such graft would be ignored by all other
input routines.
 
K

Keith Thompson

Richard Heathfield said:
Ian Collins said:


How can flushing input make sense? You flush toilets, not taps.

The Solaris version makes a fair amount of sense to me as well. C's
fflush() function doesn't *have* to follow the exact semantics of a
toilet.

In Solaris, fflush(stdin) discards any buffered input. If C defined a
discard_buffered_input() function, I don't think anyone would object
-- at least not on the same basis on which you object to
fflush(stdin). The C standard easily *could* have defined fflush() on
an input stream to work the way it does on Solaris. It just didn't.

One endpoint's input is often another endpoint's output; flushing
either makes an equal amount of sense, at least to me.

(And, if I recall correctly, "FLUSH(INPUT)" in UCSD Pascal did the
same thing as fflush(stdin) does in Solaris C; I used it regularly and
never had any problem with the name.)

fflush() on an input stream invokes undefined behavior because the C
standard says it does, and for no other reason. If you judge the
behavior of every standard C library function based on the meanings of
the English words that make up its name, you're going to run into
problems; it's not likely that your common sense will coincide with
that of the standard committee in every instance. (And even if it
did, many of the committee's decisions were based on existing
practice, not necessarily on common sense.)

fflush(stdin) invokes undefined behavior. Why? Because the standard
says so. Next!
 
K

Keith Thompson

Richard Heathfield said:
Keith Thompson said:


May I quote you? :)

You've already demonstrated that you can. In addition to that, you
certainly may (though it's a bit late for me to say otherwise).
 
T

trm

Richard said:
(e-mail address removed) said:


Try driving on the wrong side of the road. That works without
a glitch too - mostly.

My drivers' manual claims this leads to undefined behaviour. But
I've tested it across both the Atlantic and the English Channel
and it works fine over there.
 
R

Richard Heathfield

trm said:
My drivers' manual claims this leads to undefined behaviour.

It does.
But
I've tested it across both the Atlantic and the English Channel
and it works fine over there.

It works fine most places, most of the time - except of course for the one
time that it fatally doesn't. Undefined Behaviour - Just Say No.
 
J

J. J. Farrell

Richard said:
Ian Collins said:



But in C, it isn't, and we discuss C here, not Solaris.


Unlikely. Do you have evidence to support that suggestion?

Why do you consider it unlikely? I think the most likely reason for an
implementation to define extensions of this sort to its applicable
standards is to support functionality which was defined before those
standards existed. That's the case here, but that's what I would have
expected.
 
R

Richard Heathfield

J. J. Farrell said:
Why do you consider it unlikely?

Call me Mr Cynical if you like, but I've seen plenty of probablys that
turned out to be ohmaybenots. If he knew himself to be right, he would not
have said "probably", and it is my experience that most people who guess
guess wrong. Hence "unlikely".
 
D

Dik T. Winter

> J. J. Farrell said: ....

Note that on Solaris it is not defined on all input streams. There are
some for which it is undefined, notably for the device where it is wanted
in most cases.
>
> Call me Mr Cynical if you like, but I've seen plenty of probablys that
> turned out to be ohmaybenots. If he knew himself to be right, he would not
> have said "probably", and it is my experience that most people who guess
> guess wrong. Hence "unlikely".

In this case there is evidence that it comes from System V Unix. BSD
Unix did not have it. On the SunOS 4.1.3 manpage it is mentioned as
System V behaviour.
 
A

av

Unfortunately the C standard only guarantees one level, so this
action is impossible in portable code. It can't be grafted on
after the fact because any such graft would be ignored by all other
input routines.

i know i'm for you a ungly troll but what is the reason why it is not
possible (or 'good' for the standard C) to have a buffer of 256 chars
for FILE?

i remember i have a buffer of +-256 chars for FILE object and ungetc
if > +-256 ungetc return fail

what is the problem with all this (have a buffer of 256 chars for FILE
object that all input/output function can to use)[oltre a non essere
"standard C"]? thank you
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top