confused about behaviour of scanf

L

Lalatendu Das

Dear friends,
I am getting a problem in the code while interacting with a nested
Do-while loop
It is skipping a scanf () function which it should not. I have written
the whole code below. Please help me in finding why such thing is
happening and what the remedy to it is. Kindly bear with my English.


int
main ()
{
int num1[4] , i = 0 ;
char ch ;

do
{
do
{
printf ("Enter the number in the array \n");
scanf("%d",&num );
i++;
} while (i<=3);

printf("Do u want to refill the array again y/n
\n");
scanf ("%c", &ch); /* This line is skipped, it
is not
prompting to
give input
from keyboard
*/

} while (ch = = 'y') ; /* In gdb 'ch' is
showing the value same as
it has at the time of declaration i.e.
some garbage */

return 0;
}

I know this is very silly question for many of u but still I am in
ambiguity to resolve it . So please send me all possible way of
resolving it. and why such problem occurring. The environment in which
I have done it is gcc-3.2.2, red hat Linux -9 , debugged using gdb .
 
A

alok

add fflush(stdin) to clear input buffer

int main ()
{
int num[4] , i = 0 ;
char ch ;

do
{
do
{
printf ("Enter the number in the array \n");
scanf("%d",&num );
i++;
} while (i<=3);

fflush(stdin);
printf("Do u want to refill the array again y/n\n");
scanf ("%c", &ch);
} while (ch == 'y') ;

return 0;

}
 
M

Matt

Hi Lalatendu,

There's a '\n' remainning in input stream after the outer loop, it then
was read by scanf ("%c", &ch). (you can see it in gdb just after this
line).

You can use fflush(stdin) to clean the unwanted '\n' before scanf next
value.

Matt
 
A

Artie Gold

Matt said:
Hi Lalatendu,

There's a '\n' remainning in input stream after the outer loop, it then
was read by scanf ("%c", &ch). (you can see it in gdb just after this
line).

You can use fflush(stdin) to clean the unwanted '\n' before scanf next
value.

Matt
Well, it looks like we're two-for-two on answers to this thread (but at
least *this* poster found part of the solution.

fflush() is only defined for *output* streams. In this case a simple
getc() would suffice to read (and discard) the trailing newline character.

Just as an aside, this is one of the reasons why scanf() shoul dprobably
be avoided in most cases. A call to fgets() followed by a call to
sscanf() is typically preferred.

HTH,
--ag
 
M

Michael Mair

Lalatendu said:
Dear friends,
I am getting a problem in the code while interacting with a nested
Do-while loop
It is skipping a scanf () function which it should not. I have written
the whole code below. Please help me in finding why such thing is
happening and what the remedy to it is. Kindly bear with my English.


int
main ()
{
int num1[4] , i = 0 ;
char ch ;

do
{
do
{
printf ("Enter the number in the array \n");
scanf("%d",&num );
i++;
} while (i<=3);

printf("Do u want to refill the array again y/n
\n");
scanf ("%c", &ch); /* This line is skipped, it
is not
prompting to
give input
from keyboard
*/

} while (ch = = 'y') ; /* In gdb 'ch' is
showing the value same as
it has at the time of declaration i.e.
some garbage */

return 0;
}

I know this is very silly question for many of u but still I am in
ambiguity to resolve it . So please send me all possible way of
resolving it. and why such problem occurring. The environment in which
I have done it is gcc-3.2.2, red hat Linux -9 , debugged using gdb .


See the comp.lang.c FAQ 12.17, 12.18a, 12.19, 12.20 and search
the comp.lang.c archives.

Note: fflush(stdin) is _not_ the solution. getchar() can be.

Cheers
Michael
 
A

alok

i m running this program in MS VC++ & after using fflush(stdin) , it
is working fine .
so y fflush(stdin) is _not_ the solution ?
 
A

alok

i m running this program in MS VC++ & Solaris gcc after using
fflush(stdin) , it is working fine .
so y fflush(stdin) is _not_ the solution ?
 
A

Anand

[Corrected quoting]
--- Quoting from others ---------
<Quote>
It is proper Usenet etiquette to include the relevant portions of the
text you are replying to. To do this using Google groups, please follow
the instructions below, penned by Keith Thompson:

If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.
</Quote>
>
i m running this program in MS VC++ & Solaris gcc after using
fflush(stdin) , it is working fine .
so y fflush(stdin) is _not_ the solution ?

Because the standard says so
C99 7.19.5.2
"
Ifstream points to an output stream or an update stream in which the
most recent operation was not input, the fflush function causes any
unwritten data for that stream to be delivered to the host environment
to be written to the file; otherwise, the behavior is undefined.
"

Since it is undefined anything can happen. It might be working for you
now and it might be the feature of the compiler not the language.
 
P

pemo

Anand said:
[Corrected quoting]
--- Quoting from others ---------
<Quote>
It is proper Usenet etiquette to include the relevant portions of the text
you are replying to. To do this using Google groups, please follow the
instructions below, penned by Keith Thompson:

If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.
</Quote>
i m running this program in MS VC++ & Solaris gcc after using
fflush(stdin) , it is working fine .
so y fflush(stdin) is _not_ the solution ?

Because the standard says so
C99 7.19.5.2
"
Ifstream points to an output stream or an update stream in which the most
recent operation was not input, the fflush function causes any unwritten
data for that stream to be delivered to the host environment to be written
to the file; otherwise, the behavior is undefined.
"

Since it is undefined anything can happen. It might be working for you now
and it might be the feature of the compiler not the language.

It would be sooo simple if there were a way to test stdin for
eof/empty-buffer :)
 
B

Barry Schwarz

i m running this program in MS VC++ & after using fflush(stdin) , it
is working fine .
so y fflush(stdin) is _not_ the solution ?

it s nt the sltn because fflush is defined only for output streams .
Calling fflush for an input stream invokes undefined behavior. One of
the unluckiest manifestations of undefined behavior is the appearance
of working as expected and thereby misleading you to think it is
correct. This usually lasts until you have to demo the product to
your boss or a client.

The discussion of MS VC++ features/anomalies/ is properly done in one
of the microsoft.*.* groups. This group is about standard C


<<Remove the del for email>>
 
E

Ed Prochak

pemo said:
alok wrote: []
i m running this program in MS VC++ & Solaris gcc after using
fflush(stdin) , it is working fine .
so y fflush(stdin) is _not_ the solution ?

Because the standard says so
C99 7.19.5.2
[]

It would be sooo simple if there were a way to test stdin for
eof/empty-buffer :)

There is
while ( !fgets( buffer, size, STDIN) ) { ...
or
while ( !(nextch=getchar()) ) { ...

Do people not read the documentation of the functions they use?


ed
 
F

Flash Gordon

Ed said:
pemo said:
alok wrote: []
i m running this program in MS VC++ & Solaris gcc after using
fflush(stdin) , it is working fine .
so y fflush(stdin) is _not_ the solution ?

Because the standard says so
C99 7.19.5.2
[]
It would be sooo simple if there were a way to test stdin for
eof/empty-buffer :)

There is
while ( !fgets( buffer, size, STDIN) ) { ...
or
while ( !(nextch=getchar()) ) { ...

Neither of your suggestions tests for an empty buffer for an empty
buffer since the functions you are calling will just sit there until
either there is something in the buffer or they detect an end-of-file or
error condition. Your use of getchar is completely wrong, since it
returns EOF, not 0, or either end-of-file or error. You don't attempt to
distinguish between an error and end-of-file (which can be done).
Do people not read the documentation of the functions they use?

Obviously not.

Standard C provides no mechanism for detecting whether there is anything
in the buffer ready to be read, which I consider to be a shame. It
would, IMHO, be useful if standard C had a bufempty function with four
return values, empty, non-empty, full and unknown, but it does not exist
in standard C.
 
M

Michael Mair

Ed said:
pemo said:
[]
alok wrote:
[]
i m running this program in MS VC++ & Solaris gcc after using
fflush(stdin) , it is working fine .
so y fflush(stdin) is _not_ the solution ?


Because the standard says so
C99 7.19.5.2
[]

It would be sooo simple if there were a way to test stdin for
eof/empty-buffer :)


There is
while ( !fgets( buffer, size, STDIN) ) { ... ITYM: stdin
or
while ( !(nextch=getchar()) ) { ...
ITYM: EOF != (nextch = getchar())
Do people not read the documentation of the functions they use?

"Real men don't need to read the manual" or, in this case, the
documentation... ;-(

Cheers
Michael
 
M

Michael Mair

alok said:
i m running this program in MS VC++ & Solaris gcc after using
fflush(stdin) , it is working fine .
so y fflush(stdin) is _not_ the solution ?

Apart from the missing context: Please try to write something
resembling written English, especially write whole words.

As others have told you: fflush(stdin) has no defined behaviour
from the standard C point of view.

Slighty off-topic example:
Consider the many breaking changes from MSVC++6 to
MSVC++2003 and 2005 which nearly all concern the change from
not standard-conforming to standard-conforming behaviour (especially
for the C++ part). If the people relying on non-standard stuff had
written the things as standard-conforming as possible, they would
not have had to rewrite huge parts of their code.

So, as there exists a perfectly portable and viable solution to
your problem, it is reasonable to use it instead of a solution
which may not work after a change of platform, operating system,
compiler or even compiler version.

Cheers
Michael
 
K

Keith Thompson

Ed Prochak said:
pemo said:
alok wrote: []
i m running this program in MS VC++ & Solaris gcc after using
fflush(stdin) , it is working fine .
so y fflush(stdin) is _not_ the solution ?


Because the standard says so
C99 7.19.5.2
[]

It would be sooo simple if there were a way to test stdin for
eof/empty-buffer :)

There is
while ( !fgets( buffer, size, STDIN) ) { ...
or
while ( !(nextch=getchar()) ) { ...

Which, as others have pointed out, doesn't check for an empty buffer.

A feature I've seen elsewhere is the ability to flush the input buffer
before reading input after a prompt. For example, given:

printf("Enter a string: ");
fflush(stdout); /* make sure the prompt appears */
flush_input_buffer(stdin);
fgets(s, LEN, stdin);

any characters typed by the user before the prompt appears would be
discarded. Ordinarily they'd be saved in the typeahead buffer; if the
user guessed wrong about wnat the next prompt was going to be, bad
things could happen.

C provides no standard way to do this, mostly because it doesn't
assume stdin is an interactive device such as a keyboard. <OT>I've
used systems that had this feature; I think it was FLUSH(INPUT); in
UCSD PAscal.</OT>
 
J

John Bode

Lalatendu said:
Dear friends,
I am getting a problem in the code while interacting with a nested
Do-while loop
It is skipping a scanf () function which it should not. I have written
the whole code below. Please help me in finding why such thing is
happening and what the remedy to it is. Kindly bear with my English.

The problem is that you have a stray newline character stuck in the
input stream after the first scanf(). For example, suppose you type
1234 at the prompt and hit Return. The input stream then contains the
characters '1', '2', '3', '4', and '\n'. The "%d" conversion specifier
tells scanf() to skip any leading whitespace, and to read and convert
all numeric (decimal) characters up to the first non-numeric character.
So the first scanf() reads the '1', '2', '3', and '4' characters from
the input stream and stops. This leaves the '\n' character still in
the input stream. The "%c" conversion specifier tells scanf() to read
and assign the next character. So the second scanf() call sees the
'\n' in the input stream and assigns it to ch, but to you it looks like
the second scanf() is being skipped.

There are several ways around this. The simplest option is to change
the second scanf() to use the "%s" conversion specifier and read a
string instead of a single character. The "%s" conversion specfier
will skip any leading whitespace, so stray newlines won't cause
problems (however, other stray characters might; that's a different
thread, though). It means changing ch from a single char to an array,
but that's no big deal:

char ch[2];
....
printf("Do you want to refill the array again y/n: ");
fflush(stdout);
scanf("%1s", ch);
if (ch[0] == 'y')
{
...
}

It's not a robust solution, but it'll get you past this particular
issue.
int
main ()
{
int num1[4] , i = 0 ;
char ch ;

do
{
do
{
printf ("Enter the number in the array \n");
scanf("%d",&num );
i++;
} while (i<=3);

printf("Do u want to refill the array again y/n
\n");
scanf ("%c", &ch); /* This line is skipped, it
is not
prompting to
give input
from keyboard
*/

} while (ch = = 'y') ; /* In gdb 'ch' is
showing the value same as
it has at the time of declaration i.e.
some garbage */

return 0;
}

I know this is very silly question for many of u but still I am in
ambiguity to resolve it . So please send me all possible way of
resolving it. and why such problem occurring. The environment in which
I have done it is gcc-3.2.2, red hat Linux -9 , debugged using gdb .
 
C

chump1708

Lalatendu said:
Dear friends,
I am getting a problem in the code while interacting with a nested
Do-while loop
It is skipping a scanf () function which it should not. I have written
the whole code below. Please help me in finding why such thing is
happening and what the remedy to it is. Kindly bear with my English.


int
main ()
{
int num1[4] , i = 0 ;
char ch ;

do
{
do
{
printf ("Enter the number in the array \n");
scanf("%d",&num );
i++;
} while (i<=3);

printf("Do u want to refill the array again y/n
\n");
scanf ("%c", &ch); /* This line is skipped, it
is not
prompting to
give input
from keyboard
*/

} while (ch = = 'y') ; /* In gdb 'ch' is
showing the value same as
it has at the time of declaration i.e.
some garbage */

return 0;
}

I know this is very silly question for many of u but still I am in
ambiguity to resolve it . So please send me all possible way of
resolving it. and why such problem occurring. The environment in which
I have done it is gcc-3.2.2, red hat Linux -9 , debugged using gdb .


what if we use
scanf ("% c", &ch); //using a space between % and c
Does this help to eliminate the new line charater in the buffer????
 
L

Lalatendu Das

Alok
whatever u have suggested is the same which came to my mind
also . but it fails when tried . it might work in vc++ or any other
but in redhat linux 9/ gcc 3.2.2 (as i have mentioned before) it fails
to work . so i need a solution which work for everything.

And have also asked one of my teacher about this then , he told me to
scan a pointer using fgets(). just before scanf it will eradicate the
problem .
char *test ;
test = (char *) malloc(11);
fgets( test , 11 , stdin);
though this works but this is not a rsonable and genuine way to
eradiacate the problem as where i will implement such things it will
going to change the design .
 

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

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top