473,320 Members | 1,914 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

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 3839


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
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

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.