scanf() quesion?

G

guoliang

help:

#include<stdio.h>

int main(void)
{
int a;
char b;

printf("int=");
scanf("%d",&a);
fflush(stdin);
printf("char=");
scanf("%c",&b);

printf("a=%d, str=%c\n",a,b);
return 0;
}
input:1 and return;
output:char=a=1, b=

how can i assigment :a=1,b='x'?
 
R

Richard Heathfield

guoliang said:
help:

#include<stdio.h>

int main(void)
{
int a;
char b;

printf("int=");

If you want the prompt to appear before the program blocks for input,
ensure that this happens, either by completing the line or by flushing
the stream with fflush(stdout); this is because the standard output
stream is typically line-buffered.
scanf("%d",&a);

When you call scanf, you are asking for a resource (in this case,
information from the standard input stream). Whenever you ask for a
resource, the possibility exists that you don't get what you ask for,
and you should anticipate and deal with this possibility.
fflush(stdin);

The behaviour of fflush is defined only for streams open for output or
update. Since stdin is not such a stream, you invoke undefined
behaviour.
printf("char=");
scanf("%c",&b);

printf("a=%d, str=%c\n",a,b);
return 0;
}
input:1 and return;
output:char=a=1, b=

The only reason this isn't impossible is that the fflush(stdin) rendered
the behaviour of your program undefined.
how can i assigment :a=1,b='x'?

a = 1;
b = 'x';
 
M

Martin Ambuhl

guoliang said:
help:

#include<stdio.h>

int main(void)
{
int a;
char b;

printf("int=");
scanf("%d",&a);
fflush(stdin);
printf("char=");
scanf("%c",&b);

printf("a=%d, str=%c\n",a,b);
return 0;
}
input:1 and return;
output:char=a=1, b=

how can i assigment :a=1,b='x'?

While I don't think very highly of your approach to input, we'll work
with that. (By the way, 'assignment' is a noun, 'assign' is the verb,
and we usually use that term for the context of assignment statement.
But let that pass.)

#include<stdio.h>

int main(void)
{
int a;
char b = 0;

printf("int=");
fflush(stdout); /* fflush is defined only on _output_
streams, and you actually do need it
here, but not for the reason you
think. */
scanf("%d", &a);
while (getchar() != '\n') {
/* eat chars through end-of-line */ }
printf("char=");
fflush(stdout); /* and you need it here */
scanf("%c", &b);
printf("a=%d, b='%c'\n", a, b);
return 0;
}
 
L

linarin

After the first scanf of int values,you must skip one byte,may be \r
or space etc.
here is sample:

int a;
char b;
printf("Input:\n");
scanf("%d\r%c",&a,&b);
printf("%d,%c\n",a,b);
return 0;
here accept the following input:
1¡¢
5 + [enter key]
A + [enter key]

2¡¢
1 B+[enter key]


but it is bad idea to input data using scanf.
 
A

Army1987

Richard Heathfield said:
guoliang said:


If you want the prompt to appear before the program blocks for input,
ensure that this happens, either by completing the line or by flushing
the stream with fflush(stdout); this is because the standard output
stream is typically line-buffered.


When you call scanf, you are asking for a resource (in this case,
information from the standard input stream). Whenever you ask for a
resource, the possibility exists that you don't get what you ask for,
and you should anticipate and deal with this possibility.


The behaviour of fflush is defined only for streams open for output or
update. Since stdin is not such a stream, you invoke undefined
behaviour.


The only reason this isn't impossible is that the fflush(stdin) rendered
the behaviour of your program undefined.

Even without it, scanf("%d", &a); doesn't discard the newline,
which will be the first character read by scanf("%c", &b);
 
R

Richard Heathfield

Army1987 said:
Even without it, scanf("%d", &a); doesn't discard the newline,
which will be the first character read by scanf("%c", &b);

Indeed. The OP would do better to eschew scanf completely, and use fgets
to capture input until such time as he is sufficiently skilled to
devise something better.
 
A

Ajinkya

After the first scanf of int values,you must skip one byte,may be \r
or space etc.
here is sample:

    int a;
    char b;
    printf("Input:\n");
    scanf("%d\r%c",&a,&b);
    printf("%d,%c\n",a,b);
    return 0;
here accept the following input:
1ã€
5 + [enter key]
A + [enter key]

2ã€
1 B+[enter key]

but it is bad idea to input data using scanf.

help:

int main(void)
{
 int a;
 char b;
 printf("int=");
 scanf("%d",&a);
 fflush(stdin);

i dont understand why fflush(stdin) is not working....its working for
me fine.
Can any one explain it.Is it compiler dependant?
 
C

Chris Dollin

Ajinkya said:
i dont understand why fflush(stdin) is not working....its working for
me fine.

You are unlucky, then.
Can any one explain it.Is it compiler dependant?

It is undefined by the C standard, so an implementation can
do /whatever it likes/, and it doesn't need to document its
decision.

Yours may happen to discard input. (How much input, and what happens
when stdin is connected to a file or a pipe or a network connection,
those are questions to wake you at night screaming.) Another
implementation might ignore it. Another may terminate your
program. Yet another may trash some random bytes of your code or
data. Yet another another may open a space-time rift and drop
you through it. All of these are OK according to the Standard,
since it leaves the behaviour completely open.

Watch out for weevils.
 
R

regis

Richard said:
guoliang said:

If you want the prompt to appear before the program blocks for input,
ensure that this happens, either by completing the line or by flushing
the stream with fflush(stdout); this is because the standard output
stream is typically line-buffered.

That's a thing I believed until recently, but now, I'm not anymore.
Unable to find a printf()+scanf() series that came to fail to display
the prompting message on time, I searched the Jan'99 Draft
and found this:

---------------------------
5.1.2.3 Environment (p. 18)

-- The input and output dynamics of interactive devices
shall take place as specified in 7.19.3. The intent of
these requirements is that unbuffered or line-buffered
output appear as soon as possible, to ensure that
prompting messages actually appear prior to a program
waiting for input.

7.19.3 File (p. 270)

[#3] When a stream is unbuffered, characters are intended to
appear from the source or at the destination as soon as
possible. Otherwise characters may be accumulated and
transmitted to or from the host environment as a block.
When a stream is fully buffered, characters are intended to
be transmitted to or from the host environment as a block
when a buffer is filled. When a stream is line buffered,
characters are intended to be transmitted to or from the
host environment as a block when a new-line character is
encountered. Furthermore, characters are intended to be
transmitted as a block to the host environment when a buffer
is filled, when input is requested on an unbuffered stream,

* or when input is requested on a line buffered stream that
requires the transmission of characters from the host
environment.*

Support for these characteristics is
implementation-defined, and may be affected via the setbuf
and setvbuf functions.
 
K

Keith Thompson

regis said:
Richard said:
guoliang said:

If you want the prompt to appear before the program blocks for input,
ensure that this happens, either by completing the line or by flushing
the stream with fflush(stdout); this is because the standard output
stream is typically line-buffered.

That's a thing I believed until recently, but now, I'm not anymore.
Unable to find a printf()+scanf() series that came to fail to display
the prompting message on time, I searched the Jan'99 Draft
and found this:

---------------------------
5.1.2.3 Environment (p. 18)

-- The input and output dynamics of interactive devices
shall take place as specified in 7.19.3. The intent of
these requirements is that unbuffered or line-buffered
output appear as soon as possible, to ensure that
prompting messages actually appear prior to a program
waiting for input.

7.19.3 File (p. 270)

[#3] When a stream is unbuffered, characters are intended to
appear from the source or at the destination as soon as
possible. Otherwise characters may be accumulated and
transmitted to or from the host environment as a block.
When a stream is fully buffered, characters are intended to
be transmitted to or from the host environment as a block
when a buffer is filled. When a stream is line buffered,
characters are intended to be transmitted to or from the
host environment as a block when a new-line character is
encountered. Furthermore, characters are intended to be
transmitted as a block to the host environment when a buffer
is filled, when input is requested on an unbuffered stream,

* or when input is requested on a line buffered stream that
requires the transmission of characters from the host
environment.*

Support for these characteristics is
implementation-defined, and may be affected via the setbuf
and setvbuf functions.
[...]

And see paragraph 7:

At program startup, three text streams are predefined and need not
be opened explicitly -- _standard input_ (for reading conventional
input), _standard output_ (for writing conventional output), and
_standard error_ (for writing diagnostic output). As initially
opened, the standard error stream is not fully buffered; the
standard input and standard output streams are fully buffered if
and only if the stream can be determined not to refer to an
interactive device.

If standard output refers to an interactive device, it can be either
unbuffered or line buffered. If it happens to be unbuffered, then
something like

printf("prompt: ");
fgets(line, N, stdin);

will work properly (i.e., the prompt will appear before the fgets()
call). If it happens to be line buffered, a call to fflush(stdout) is
required to get the same behavior. Such a call won't do any harm even
if stdout is unbuffered.
 
C

CBFalconer

linarin said:
After the first scanf of int values,you must skip one byte,may be \r
or space etc.
here is sample:

int a;
char b;
printf("Input:\n");
scanf("%d\r%c",&a,&b);
printf("%d,%c\n",a,b);
return 0;
here accept the following input:
1¡¢
5 + [enter key]
A + [enter key]

2¡¢
1 B+[enter key]

but it is bad idea to input data using scanf.

No, but it is an extremely bad idea to use it without checking the
return value.

Please do not top-post. Your answer belongs after (or intermixed
with) the quoted material to which you reply, after snipping all
irrelevant material. See the following links:

--
<http://www.catb.org/~esr/faqs/smart-questions.html>
<http://www.caliburn.nl/topposting.html>
<http://www.netmeister.org/news/learn2quote.html>
<http://cfaj.freeshell.org/google/> (taming google)
<http://members.fortunecity.com/nnqweb/> (newusers)
 
R

regis

Keith said:
5.1.2.3 Environment (p. 18)

-- The input and output dynamics of interactive devices
shall take place as specified in 7.19.3. The intent of
these requirements is that unbuffered or line-buffered
output appear as soon as possible, to ensure that
prompting messages actually appear prior to a program
waiting for input.

7.19.3 File (p. 270)

[#3] When a stream is unbuffered, characters are intended to
appear from the source or at the destination as soon as
possible. Otherwise characters may be accumulated and
transmitted to or from the host environment as a block.
When a stream is fully buffered, characters are intended to
be transmitted to or from the host environment as a block
when a buffer is filled. When a stream is line buffered,
characters are intended to be transmitted to or from the
host environment as a block when a new-line character is
encountered. Furthermore, characters are intended to be
transmitted as a block to the host environment when a buffer
is filled, when input is requested on an unbuffered stream,
or when input is requested on a line buffered stream that
requires the transmission of characters from the host
environment.
And see paragraph 7:

At program startup, three text streams are predefined and need not
be opened explicitly -- _standard input_ (for reading conventional
input), _standard output_ (for writing conventional output), and
_standard error_ (for writing diagnostic output). As initially
opened, the standard error stream is not fully buffered; the
standard input and standard output streams are fully buffered if
and only if the stream can be determined not to refer to an
interactive device.

If standard output refers to an interactive device, it can be either
unbuffered or line buffered. If it happens to be unbuffered, then
something like

printf("prompt: ");
fgets(line, N, stdin);

will work properly (i.e., the prompt will appear before the fgets()
call). If it happens to be line buffered, a call to fflush(stdout) is
required to get the same behavior. Such a call won't do any harm even
if stdout is unbuffered.

The problem I have when I read 7.19.3[#3] is how
the sentence starting with "Furthermore..." should be
linked with the previous sentences, i.e., how the paragraph
would be indented if split into item-lists and sublists.

But, if I read you well, should I understand that
the sentence starting with "Furthermore..."
is a continuation of the case "When a stream is line buffered...",
and should not apply to all three cases mentioned above ?

Second, how to understand the expression "are indented to"?
Does it free an implementation from any obligation ?

Also, the expression "can be determined not to refer to":
is the implementation allowed to fail to determine it
when it really is ?
 
K

Keith Thompson

regis said:
Keith said:
5.1.2.3 Environment (p. 18)

-- The input and output dynamics of interactive devices
shall take place as specified in 7.19.3. The intent of
these requirements is that unbuffered or line-buffered
output appear as soon as possible, to ensure that
prompting messages actually appear prior to a program
waiting for input.

7.19.3 File (p. 270)

[#3] When a stream is unbuffered, characters are intended to
appear from the source or at the destination as soon as
possible. Otherwise characters may be accumulated and
transmitted to or from the host environment as a block.
When a stream is fully buffered, characters are intended to
be transmitted to or from the host environment as a block
when a buffer is filled. When a stream is line buffered,
characters are intended to be transmitted to or from the
host environment as a block when a new-line character is
encountered. Furthermore, characters are intended to be
transmitted as a block to the host environment when a buffer
is filled, when input is requested on an unbuffered stream,
or when input is requested on a line buffered stream that
requires the transmission of characters from the host
environment.
And see paragraph 7:
At program startup, three text streams are predefined and need
not
be opened explicitly -- _standard input_ (for reading conventional
input), _standard output_ (for writing conventional output), and
_standard error_ (for writing diagnostic output). As initially
opened, the standard error stream is not fully buffered; the
standard input and standard output streams are fully buffered if
and only if the stream can be determined not to refer to an
interactive device.
If standard output refers to an interactive device, it can be either
unbuffered or line buffered. If it happens to be unbuffered, then
something like
printf("prompt: ");
fgets(line, N, stdin);
will work properly (i.e., the prompt will appear before the fgets()
call). If it happens to be line buffered, a call to fflush(stdout) is
required to get the same behavior. Such a call won't do any harm even
if stdout is unbuffered.

The problem I have when I read 7.19.3[#3] is how
the sentence starting with "Furthermore..." should be
linked with the previous sentences, i.e., how the paragraph
would be indented if split into item-lists and sublists.

But, if I read you well, should I understand that
the sentence starting with "Furthermore..."
is a continuation of the case "When a stream is line buffered...",
and should not apply to all three cases mentioned above ?

No, the "Furthermore..." sentence applies to all three. In fact, it
explicitly refers to all three cases:

Furthermore, characters are intended to be transmitted as a block
to the host environment

when a buffer is filled [fully buffered],

when input is requested on an unbuffered stream [unbuffered],

or when input is requested on a line buffered stream that
requires the transmission of characters from the host
environment [line buffered].
Second, how to understand the expression "are indented to"?
Does it free an implementation from any obligation ?

(Intended, not indented).

The sentence in question is:

When a stream is _unbuffered_, characters are intended to appear
from the source or at the destination as soon as possible.

The intent, I think, is that an implementation should satisfy this
requirement unless there's a good reason not to. The phrase "as soon
as possible" isn't precise enough to allow for a strict determination
of whether a given implementation conforms or not.
Also, the expression "can be determined not to refer to":
is the implementation allowed to fail to determine it
when it really is ?

Presumably, yes. Otherwise, it probably would have said

... are fully buffered if and only if the stream does not refer to
an interactive device.

rather than

... are fully buffered if and only if the stream can be determined
not to refer to an interactive device.

The standard (implicitly) recognizes that this determination might not
always be possible.
 
C

CBFalconer

Ajinkya said:
.... snip ...

i dont understand why fflush(stdin) is not working....its working
for me fine. Can any one explain it. Is it compiler dependant?

It is undefined for input files. You may have a system that
extended its operation. That does not apply in general. See the C
standard. N1124.pdf is also good.

--
Some useful references about C:
<http://www.ungerhu.com/jxh/clc.welcome.txt>
<http://www.eskimo.com/~scs/C-faq/top.html> (C-faq)
<http://benpfaff.org/writings/clc/off-topic.html>
<http://anubis.dkuug.dk/jtc1/sc22/wg14/www/docs/n869/> (C99 std)
<http://www.dinkumware.com/refxc.html> (C-library}
<http://gcc.gnu.org/onlinedocs/> (GNU docs)
<http://clc-wiki.net/wiki/C_community:comp.lang.c:Introduction>
 
C

Chris Torek

Richard said:
If you want [stdout output] to appear before the program
blocks for [stdin] input, ensure that this happens, either by
completing the line or by flushing the stream with fflush(stdout); ...

Best to use fflush(stdout).

That's a thing I believed until recently, but now, I'm not anymore.
Unable to find a printf()+scanf() series that came to fail to display
the prompting message on time ... [excerpt from Standard deleted]

If you have access to a Linux or Unix box, try:

./prog | tee save_output

and observe the fact that printf() output does not appear as
desired unless the fflush(stdout) calls are in place.

(This is one reason people use "script" instead of "tee". When
using "prog | tee", the implementation determines that stdout is
not connected to an "interactive device".)

(Programs that *do* use fflush(stdout) are well-behaved even when
running underneath pipes. Given the existence of "script", this
is not crucial, but it is convenient.)
 
R

Richard Heathfield

Chris Torek said:
If you have access to a Linux or Unix box, try:

./prog | tee save_output

and observe the fact that printf() output does not appear as
desired unless the fflush(stdout) calls are in place.

Ouch! A lesson learned.
 
A

Army1987

regis said:
That's a thing I believed until recently, but now, I'm not anymore.
Unable to find a printf()+scanf() series that came to fail to display
the prompting message on time, I searched the Jan'99 Draft
and found this:

I have written a program with putchar()s a character from a string
determined from its first line argument (the first character if
there's no first line argument), and then calls itself (via system()) with
an argument which causes it to write the next character.
<semi-ot reason="the behaviour of system() itself is
implementation-defined">
If I don't fflush(stdout) after putchar, the string is displayed
backwards. Figuring out why is left as an exercise.</semi-ot>
 
A

Army1987

scanf("%d", &a);
while (getchar() != '\n') {
/* eat chars through end-of-line */ }

what if it hits EOF? (BTW, I think you can use scanf("%d%*[^\n]%*c", &a);
The asterisks mean "discard". %*[^\n] means "discard all consecutive
next characters which aren't \n" and %*c means "discard next character".)
 
Z

zwgao83

help:

#include<stdio.h>

int main(void)
{
int a;
char b;

printf("int=");
scanf("%d",&a);
fflush(stdin);
printf("char=");
scanf("%c",&b);

printf("a=%d, str=%c\n",a,b);
return 0;}

input:1 and return;
output:char=a=1, b=

how can i assigment :a=1,b='x'?

it works fine for me .my environment is winxp+mingw gcc 3.4.2.
i find the fflush refrence from msdn:

The fflush function flushes a stream. If the file associated with
stream is open for output, fflush writes to that file the contents of
the buffer associated with the stream. If the stream is open for
input, fflush clears the contents of the buffer. fflush negates the
effect of any prior call to ungetc against stream. Also, fflush(NULL)
flushes all streams opened for output. The stream remains open after
the call. fflush has no effect on an unbuffered stream.

if you comment out fflush(stdin); ,the result is the same to yours:
char=a=1,b=
 

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,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top