473,472 Members | 1,719 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

scanf/getchar sequence problem

/*
The below code on SGI will wait for you to enter 2 things, but
on Linux it will only wait the first time.

I can make the code work by replacing the scanf with:

char data [5];
fgets (data,5,stdin);
the_number = atoi (data);

But, instead I would like to modify the scanf, "/dev/tty", or
something simple like that.
*/

#include <stdio.h>
int main()
{
int c;
int the_number;
fprintf (stderr,"Enter Number :");
scanf ("%d",&the_number);
fprintf (stderr,"\nEnter a letter :");
c = getchar ();
if ( (c = getchar ()) == EOF )
freopen ("/dev/tty","r",stdin);
else
ungetc (c,stdin);
return (0);
}

Nov 14 '05 #1
13 3849


cl********@aol.com wrote:
/*
The below code on SGI will wait for you to enter 2 things, but
on Linux it will only wait the first time.

I can make the code work by replacing the scanf with:

char data [5];
fgets (data,5,stdin);
the_number = atoi (data);

But, instead I would like to modify the scanf, "/dev/tty", or
something simple like that.
*/

#include <stdio.h>
int main()
{
int c;
int the_number;
fprintf (stderr,"Enter Number :");
scanf ("%d",&the_number);
fprintf (stderr,"\nEnter a letter :");
c = getchar ();
if ( (c = getchar ()) == EOF )
freopen ("/dev/tty","r",stdin);
else
ungetc (c,stdin);
return (0);
}


Linux is right; SGI is wrong. The scanf() should consume
any initial white space, an optional sign character, and a
digit string, but should not consume the following '\n' (or
whatever else follows the digits). The subsequent getchar()
should retrieve the '\n' (or whatever).

My advice is to avoid scanf() for interactive input: it
can be tricky to use, and recovery from input errors is
difficult (consider what happens if the user enters "#\n"
at your first prompt). It is usually better to proceed along
the lines of the "cure" you discovered: Read the line with
fgets() and then interpret the characters yourself. It's
better to use strtod() or sscanf() than atoi(), because the
latter has essentially *no* way to diagnose erroneous input.

--
Er*********@sun.com
Nov 14 '05 #2
"Eric Sosman" <er*********@sun.com> wrote in message
news:d3**********@news1brm.Central.Sun.COM
cl********@aol.com wrote:
/*
The below code on SGI will wait for you to enter 2 things, but
on Linux it will only wait the first time.

I can make the code work by replacing the scanf with:

char data [5];
fgets (data,5,stdin);
the_number = atoi (data);

But, instead I would like to modify the scanf, "/dev/tty", or
something simple like that.
*/

#include <stdio.h>
int main()
{
int c;
int the_number;
fprintf (stderr,"Enter Number :");
scanf ("%d",&the_number);
fprintf (stderr,"\nEnter a letter :");
c = getchar ();
if ( (c = getchar ()) == EOF )
freopen ("/dev/tty","r",stdin);
else
ungetc (c,stdin);
return (0);
}


Linux is right; SGI is wrong. The scanf() should consume
any initial white space, an optional sign character, and a
digit string, but should not consume the following '\n' (or
whatever else follows the digits). The subsequent getchar()
should retrieve the '\n' (or whatever).


Yes, but note that there are two getchar() calls in the code, so it should
be possible to enter a char at the console (though the effect will not be
the intended one).

I wonder if the code run on Linux and the code run on SGI were really the
same.
--
John Carson

Nov 14 '05 #3


John Carson wrote:
"Eric Sosman" <er*********@sun.com> wrote

[...] The subsequent getchar()
should retrieve the '\n' (or whatever).


Yes, but note that there are two getchar() calls in the code, so it should
be possible to enter a char at the console (though the effect will not be
the intended one).


Oh, foozle. I'd like to say "That'll teach me not
to speed-read code," but experience suggests it won't ...

--
Er*********@sun.com

Nov 14 '05 #4
In comp.lang.c cl********@aol.com wrote:
/*
The below code on SGI will wait for you to enter 2 things, but
on Linux it will only wait the first time.
[snip] fprintf (stderr,"Enter Number :");
scanf ("%d",&the_number);
fprintf (stderr,"\nEnter a letter :");
c = getchar ();
if ( (c = getchar ()) == EOF )

[snip]

On Linux works as expected, ie. waits or not depending
on what data you feed (at least at an Xterm). Try to
output values of `c' to see what happens (could it be
that Enter generates more than one character?)

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 14 '05 #5

Eric Sosman wrote:
cl********@aol.com wrote:
/*
The below code on SGI will wait for you to enter 2 things, but
on Linux it will only wait the first time.

I can make the code work by replacing the scanf with:

char data [5];
fgets (data,5,stdin);
the_number = atoi (data);

But, instead I would like to modify the scanf, "/dev/tty", or
something simple like that.
*/

#include <stdio.h>
int main()
{
int c;
int the_number;
fprintf (stderr,"Enter Number :");
scanf ("%d",&the_number);
fprintf (stderr,"\nEnter a letter :");
c = getchar ();
if ( (c = getchar ()) == EOF )
freopen ("/dev/tty","r",stdin);
else
ungetc (c,stdin);
return (0);
}


Linux is right; SGI is wrong. The scanf() should consume
any initial white space, an optional sign character, and a
digit string, but should not consume the following '\n' (or
whatever else follows the digits). The subsequent getchar()
should retrieve the '\n' (or whatever).


This is solution temporarily OK'ed by boss:

#include <stdio.h>
int main()
{
int c;
int the_number;
char car_ret;

fprintf (stderr,"Enter Number :");

#ifdef __sgi
scanf ("%d",&the_number);
#elif defined (__linux)
scanf ("%d%c",&the_number,&car_ret);
#endif

fprintf (stderr,"\nEnter a letter :");
c = getchar ();
if ( (c = getchar ()) == EOF )
freopen ("/dev/tty","r",stdin);
else
ungetc (c,stdin);
return (0);
}

Nov 14 '05 #6
cl********@aol.com wrote:
[scanf("%d") leaves the newline unconsumed]

This is solution temporarily OK'ed by boss:

#include <stdio.h>
int main()
{
int c;
int the_number;
char car_ret;

fprintf (stderr,"Enter Number :");

#ifdef __sgi
scanf ("%d",&the_number);
#elif defined (__linux)
scanf ("%d%c",&the_number,&car_ret);
#endif


Fragile; a house of cards. If the user enters anything
at all between the final digit and the newline -- a space
character, say -- you'll be right back where you started.
I'll repeat my earlier advice: scanf() is not well suited
for interactive input, and you'd be better off using another
method altogether.

--
Eric Sosman
es*****@acm-dot-org.invalid
Nov 14 '05 #7
Eric Sosman wrote:

cl********@aol.com wrote:
[scanf("%d") leaves the newline unconsumed]

This is solution temporarily OK'ed by boss:

#include <stdio.h>
int main()
{
int c;
int the_number;
char car_ret;

fprintf (stderr,"Enter Number :");

#ifdef __sgi
scanf ("%d",&the_number);
#elif defined (__linux)
scanf ("%d%c",&the_number,&car_ret);
#endif


Fragile; a house of cards. If the user enters anything
at all between the final digit and the newline -- a space
character, say -- you'll be right back where you started.
I'll repeat my earlier advice: scanf() is not well suited
for interactive input, and you'd be better off using another
method altogether.


Is stderr well suited for interactive output?
I always thought that the purpose of the standard error stream
was to output error messages.

--
pete
Nov 14 '05 #8
Eric Sosman wrote:

I'll repeat my earlier advice: scanf() is not well suited
for interactive input, and you'd be better off using another
method altogether.


And it is a very good advice. The OP should follow it.
The substitution of scanf with a fgets() sscanf() pair isn't
much work and saves you from that problem (and others
you have not discovered yet).

char Buffer[ BUFFER_SIZE ]
fgets( Buffer, sizeof( Buffer ), stdin );
sscanf( "... whatever you want

The only problem is the BUFFER_SIZE. It doesn't matter which number
you choose, there is always the possibility that some user might overflow
it. If you set it large enough, say 4096, that probability is very low (although
not 0.0). In such cases it is often sufficient to just detect that fact (which
can easily be done: just look for a '\n' character in Buffer) and ask the user
for less input.

--
Karl Heinz Buchegger
kb******@gascad.at
Nov 14 '05 #9
Eric Sosman wrote:
cl********@aol.com wrote:
[scanf("%d") leaves the newline unconsumed]

This is solution temporarily OK'ed by boss:

#include <stdio.h>
int main()
{
int c;
int the_number;
char car_ret;

fprintf (stderr,"Enter Number :");

#ifdef __sgi
scanf ("%d",&the_number);
#elif defined (__linux)
scanf ("%d%c",&the_number,&car_ret);
#endif


Fragile; a house of cards. If the user enters anything
at all between the final digit and the newline -- a space
character, say -- you'll be right back where you started.
I'll repeat my earlier advice: scanf() is not well suited
for interactive input, and you'd be better off using another
method altogether.


Actually, used properly scanf is quite suitable, as long as you are
willing to have the overhead of that large interpreter.

/* get a numeric and flush the input line */
/* return 0 for success, non-zero otherwise */
int getnum(int *num)
{
int ok, ch;

ok = scanf("%d", num);
while (EOF != (ch = getchar()) && ('\n' != ch)) continue;
return (1 == ok);
}

although I would never use it in that form. I keep a separate
flushln(f) function about, and would simply write:

if (1 == scanf("%d", &num)) .....
if (EOF == flushln(stdin)) .....

as long as people realize that leading blanks and empty lines will
be skipped. The key to suitable use of scanf interactively is the
"if (1 == scanf(....". Anything other than one leads to confusion,
gnashing of teeth, and loss of hair. The advantage is the
elimination of presized buffers.

--
"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." - Keith Thompson
Nov 14 '05 #10
Richard Herring <ju**@[127.0.0.1]> wrote:
pete <pf*****@mindspring.com>
#include <stdio.h>
int main()
{
int c;
int the_number;
fprintf (stderr,"Enter Number :");
scanf ("%d",&the_number);
fprintf (stderr,"\nEnter a letter :");


Oh, I see. Well, the answer would be "yes", though personally, since
this is crossposted to clc++ I'd prefer cerr.

The user may have redirected stdout to a file or piped it to another
program, so they wouldn't see prompts directed to it. And stderr is
automatically flushed, so if you're lucky the prompts will appear before
the input operation starts.


If, yes. If you're unlucky, though, stderr will appear in the console
window, not in the user's main window, and he'll completely overlook it.
The sysadmin, OTOH, will be pissed off at you for spamming his log files
with completely meaningless messages. stderr is for error messages, not
for prompts. Besides, if stdout _is_ redirected, that was intentional.

Richard
Nov 14 '05 #11
In message <42***************@news.xs4all.nl>, Richard Bos
<rl*@hoekstra-uitgeverij.nl> writes
Richard Herring <ju**@[127.0.0.1]> wrote:
>> pete <pf*****@mindspring.com>
>>> #include <stdio.h>
>>> int main()
>>> {
>>> int c;
>>> int the_number;
>>> fprintf (stderr,"Enter Number :");
>>> scanf ("%d",&the_number);
>>> fprintf (stderr,"\nEnter a letter :");
Oh, I see. Well, the answer would be "yes", though personally, since
this is crossposted to clc++ I'd prefer cerr.

The user may have redirected stdout to a file or piped it to another
program, so they wouldn't see prompts directed to it. And stderr is
automatically flushed, so if you're lucky the prompts will appear before
the input operation starts.


If, yes. If you're unlucky, though, stderr will appear in the console
window,


What is a "console window"?
not in the user's main window, and he'll completely overlook it.
Just as he would if he redirected stdout to a file, or piped it to
another program.
The sysadmin,
What is a "sysadmin"?
OTOH, will be pissed off at you for spamming his log files
with completely meaningless messages.
Even back in the days when I had to manage a mainframe system, I don't
recall messages to stderr from user programs ever going anywhere but the
user's teletype. But yes, it's true that the way the standard streams
are connected to the hardware is beyond the scope of the C or C++
standards, so anything could happen.
stderr is for error messages, not
for prompts.
And stdout is for computed output, not for prompts. In the absence of a
stdprompt, one has to use one or the other, and the decision is not best
made on the basis of its name but on how it interacts with the outside
world.
Besides, if stdout _is_ redirected, that was intentional.


Of course. It's not something one does by accident. But intentions
differ.

--
Richard Herring
Nov 14 '05 #12
Richard Herring <ju**@[127.0.0.1]> wrote:
In message <42***************@news.xs4all.nl>, Richard Bos
<rl*@hoekstra-uitgeverij.nl> writes
The sysadmin,


What is a "sysadmin"?


Someone you are obviously in dire need of.

HTH; HAND.

Richard
Nov 14 '05 #13
In message <42***************@news.xs4all.nl>, Richard Bos
<rl*@hoekstra-uitgeverij.nl> writes
Richard Herring <ju**@[127.0.0.1]> wrote:
In message <42***************@news.xs4all.nl>, Richard Bos
<rl*@hoekstra-uitgeverij.nl> writes
>The sysadmin,


What is a "sysadmin"?


Someone you are obviously in dire need of.


What was your username again?

--
Richard "clickety click" Herring
Nov 14 '05 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

21
by: clusardi2k | last post by:
/* The below code on SGI will wait for you to enter 2 things, but on Linux it will only wait the first time. I can make the code work by replacing the scanf with: char data ; fgets...
5
by: Eduardo Olivarez | last post by:
The following code does not work correctly on my machine. Either one of the scanf()'s alone work perfectly. However, when they are combined, the second scanf() call just reads what the first one...
3
by: Vinicius | last post by:
Hello, the following code does not work: " .... void main(void) { char option; printf("Choose an option: ");
17
by: Lefty Bigfoot | last post by:
Hello, I am aware that a lot of people are wary of using scanf, because doing it improperly can be dangerous. I have tried to find a good tutorial on all the ins and outs of scanf() but been...
185
by: Martin Jørgensen | last post by:
Hi, Consider: ------------ char stringinput ..bla. bla. bla. do {
62
by: Argento | last post by:
I was curious at the start about how ungetc() returns the character to the stream, so i did the following coding. Things work as expected except if I change the scanf("%c",&j) to scanf("%d",&j). I...
9
by: Cao Yi | last post by:
Hi, here's a fract of codes, and what's the line "scanf("%lf%*", &cvi)" doing? ============================= do { printf("\nCoefficient: "); scanf("%lf%*", &cvi); getchar(); } while (cvi <=...
26
by: tesh.uk | last post by:
Hi Gurus, I have written the following code with the help of Ivor Horton's Beginning C : // Structures, Arrays of Structures. #include "stdafx.h" #include "stdio.h" #define MY_ARRAY 15
13
by: FerrisUML | last post by:
Hello everyone! I new to C and am having the following problem. In the below program, the last scanf is being ignored and the program exits. Can anyone see anything that im doing wrong? Thanks...
2
by: subramanian100in | last post by:
Consider the following program named as x.c #include <stdlib.h> #include <stdio.h> int main(void) { unsigned int u; char str;
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
0
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.