burkie@uxe.cso.uiuc.edu (06/03/89)
char c;
...
scanf("%c", &c);
...
I find that sometimes the program above doesn't stop
at the scanf to wait for input, esp. if there are other
input, print etc. statements.. Do I have to flush some
buffers etc for this to work properly?
In response to
int x, y;
while (...) {
scanf("%d, %d", &x, &y);
}
if I type 'a' on the keyboard, why
does the loop keep running, skipping over the scanf ?
Thanks.
-Salman
burkie@uxe.cso.uiuc.edu
henry@utzoo.uucp (Henry Spencer) (06/04/89)
In article <225800176@uxe.cso.uiuc.edu> burkie@uxe.cso.uiuc.edu writes: >scanf("%c", &c); >... >I find that sometimes the program above doesn't stop >at the scanf to wait for input, esp. if there are other >input, print etc. statements.. Do I have to flush some >buffers etc for this to work properly? There is often buffering of input; in particular, many systems (all Unix systems, in particular) essentially do input a line at a time regardless of whether you're only asking for it a character at a time. Actually inputting a character at a time is complicated and somewhat system-dependent; queries on how it should be done should go to comp.unix.questions (or other appropriate operating-system group), not comp.lang.c. >while (...) { > scanf("%d, %d", &x, &y); > >if I type 'a' on the keyboard, why >does the loop keep running, skipping over the scanf ? Because the scanf is failing. You should NEVER NEVER NEVER do a scanf without checking the returned value to find out whether it worked. -- You *can* understand sendmail, | Henry Spencer at U of Toronto Zoology but it's not worth it. -Collyer| uunet!attcan!utzoo!henry henry@zoo.toronto.edu
scs@adam.pika.mit.edu (Steve Summit) (06/05/89)
In article <225800176@uxe.cso.uiuc.edu> burkie@uxe.cso.uiuc.edu manages to ask about nearly all of scanf's crippling problems. The short (unhelpful, but adamantly-held-by-me) answer is "don't use scanf." Unfortunately, it's nearly impossible not to use scanf, because it's so damn convenient, and all the C books teach you about it early, because it's the apparently easiest way of having little toy programs ask the user questions. >char c; >scanf("%c", &c); > >I find that sometimes the program above doesn't stop >at the scanf to wait for input, esp. if there are other >input, print etc. statements.. Do I have to flush some >buffers etc for this to work properly? If you are trying to wait for the user to hit a key, this is not the way to do it. scanf is both buffered and, typically, line based. Not only are all characters the user types saved until explicitly read (even if by a later scanf which you had wanted to wait for new input) but scanf normally can't even start processing input until the user has pressed the return key, so scanf("%c") won't necessarily give you character-at-a-time input. (Whether input is character-at-a-time or "line buffered" is actually not a function of scanf at all, but of the operating system and/or device driver which is supplying scanf with characters.) If you're using MS-DOS, a function usually called kbhit() will tell you whether the user has hit a key or not. (One of the two nice things I can say about DOS is that it makes this common operation easy.) If you're not using DOS, try to figure out a way not to need to do this or, barring that, read comp.lang.c and/or comp.unix.wizards, where the question has just been asked for the 47th time this month. (The answer depends entirely on what system you're using.) Flushing the input buffer, though occasionally important, is likewise system-dependent. (fflush on stdin works on some systems, but is nonportable and does nothing about characters read by the operating system but not yet delivered to the stdio package.) >In response to > >int x, y; >while (...) > scanf("%d, %d", &x, &y); > >if I type 'a' on the keyboard, why >does the loop keep running, skipping over the scanf ? Scanf's most miserable problem is that it doesn't discard unrecognized input. (This is a documented feature, so don't try getting it changed. It is only a miserable problem when scanf is being used for interactive user input, which is what everybody uses it for.) The 'a' sits there in the input buffer, causing each scanf to fail, and the correct digits you probably typed after the 'a' are never seen. If you're writing a non-toy program, one that should deal gracefully with incorrect user input, the best way of handling it is to read an entire line of text with fgets, then pick it apart, perhaps with sscanf: char line[MAXLINE]; while (...) { fgets(line, MAXLINE, stdin); if(sscanf(line, "%d, %d", &x, &y) != 2) {error... } } The other thing that will significantly reduce difficulties with scanf et al is to check the return value, as I did in the example above. If scanf isn't able to convert the number of items requested, something is wrong, and to continue without complaining or correcting it is invariably folly. Steve Summit scs@adam.pika.mit.edu P.S. Two other relevant reminders: 1. Do use fgets, not gets, because fgets lets you announce your buffer size and prevent overflow. 2. Remember to pass addresses to *scanf (burkie did, but forgetting to is a common problem).
minar@reed.bitnet (Nelson Minar,(???)) (02/28/90)
I apologize: I know this problem was just asked on the net, but I cannot seem to find the old articles that pertain to it. I am using scanf() to input doubles (%lf) in a Turbo C 2.0 program. When it tries to do the scanf() there is a runtime error: scanf() : floating point formats not linked. Abnormal program termination (or something very similar) how does one force the TC linker to work around this bug, from within the IDE? Does it have something to do with how I have the project set up? (the program that does the scanf() doesn't do anything fancier with floating points than divide them, and the declarations involving doubles are in a header file) please mail the answer: the net has already seen this question once.. thanks!
840445m@aucs.uucp (Alan McKay) (03/01/90)
eat this you nasty line-eater!! ------------------------------------------ I actually have 2 questions both of which are related. This first is just a matter of syntax ... I want to declare an array of 20 strings of length 5, and I am doing the following: char array[20][5]; /* is this correct? */ Ok, that is the easy one. Now, each of these 20 strings gets read from the keyboard and I am using 'scanf' to do it. However, I want to ensure that only the first 4 characters get read into the string ( saving the last space for \0, of course ). I am not sure how to do this. Is there some way I can specify that in my format statement? I tried "%4s" but that does not seem to do it. scanf( "%4s", array[0] ); /* to read in the first string */ What is happening now is that if more characters are entered they end up over-writing array[1] .. [2] ... etc depending upon how man are entered. I am using Turbo-C (what version??) but it is absolutely mandatory that the solution be totally portable since I will be re-compiling on a number of other systems, and running the program there as well. Oh, and finally, I do not read this group so could you please reply via e-mail rather than a follow-up? Thank you very much.
spm2d@watt1.acc.Virginia.EDU (Steven Paul Miale) (10/04/90)
Recently, I have heard that many implementations of C have a buggy version of scanf() attached which may cause a hard drive crash; these assertations are from the famous C authorities here in Charlottesville. They also claim that most scanf() versions are buggy, and to use other read commands (such as gets() ) or to write your own routines. Is there any truth to this rumor? I have repeatedly told these few not to blast all versions of C because a few may have bad implementations, but they keep pestering me and I want some *real* C programmers to set it straight. Please E-mail me, as I usually do not keep up with this newsgroup. --- Steven Miale spm2d@virginia.edu
baldwin@usna.NAVY.MIL (J.D. Baldwin.) (10/11/90)
OK, I don't want to jump the gun and call this a "compiler bug" just yet,
but I'm mighty stumped by the following code (this is as simple as I can
make the example without the bug disappearing):
-------Cut here---------
#include <stdio.h>
#include <stdlib.h>
double * ar_1;
double x;
void main(void)
{
ar_1 = (double *) calloc(1, sizeof(double));
fflush(stdin);
/* scanf("%lf", &x); */
scanf("%lf", &(ar_1[0]));
printf("%lf\n", ar_1[0]);
}
-------Cut here---------
Here's the problem: when I compile and run this code under Turbo C 2.01, it
works fine--accepts a floating-point number and prints it out. When I
compile and run the SAME code under Turbo C++ 1.00, I hit the (uncommented)
scanf and get the following message:
scanf : floating point formats not linked
Abnormal program termination
It does not pause to get input before delivering this message.
Now it gets weird: I uncomment the first "scanf" call. Still works as
advertised under Turbo C 2.01--this time gets two doubles, and throws the
first one away. Now it works the same way under Turbo C++ 1.00 also!
If, instead of calloc-ating ar_1, I declare it as double ar_1[10], and get
rid of the calloc() line, it works the way it's supposed to in both compilers
(whether or not the extraneous scanf() is present).
I've tried setting and unsetting every possible compiler option--especially
the ones about making use of a 80287 co-processor (I have one) or FP
emulation, 8086 or 80286 code, etc., etc. I am running a Zenith Z-248
(AT compatible) and Zenith DOS 3.3 "plus." Of course I can get around
this problem by scanning in a temporary variable and re-assigning it,
but I'd rather understand what the heck's going on here!
I'd appreciate any help. If posted, I'll see it (I check all these groups--
and please note the followup redirection); if e-mailed, I'll echo it back to
the net. Thanks in advance.
--
From the catapult of: |+| "If anyone disagrees with anything I
_, J. D. Baldwin, Comp Sci Dept |+| say, I am quite prepared not only to
__||____:::)=}- U.S. Naval Academy|+| retract it, but also to deny under
\ / baldwin@cad.usna.navy.mil |+| oath that I ever said it." --T. Lehrer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ebm@corvair.almaden.ibm.com (Eli Messinger) (10/11/90)
To recap: I'm trying to scan a line of the form ccssss(tab)d, where c are single characters, s is a >=0 length string, and d is an integer. The problem is that there seems to be no simple way to make scanf() scan for a >=0 length string. If you use %s, then scanf skips blank space, and in the case where the string is empty, gets the wrong answer. If you use %[^t] then an empty string matches 0 characters, which causes the scanf() to halt. The consensus is: Don't use scanf. (One solution that was proposed by a few different people is to scan the line as: %[^\t]%d, then pick the first two characters off). -- "Hang on to your ego." --Brian Wilson CSNET: ebm@ibm.com / UUCP: ..!uunet!ibmarc!ebm / BITNET: ebm@almaden
baldwin@usna.NAVY.MIL (J.D. Baldwin.) (10/11/90)
In article <344@usna.NAVY.MIL> I, with brain engaged firmly in neutral, wrote: [a bunch of code and text describing a problem in which] > > scanf("%lf", &(ar_1[0])); [resulted in] > > scanf : floating point formats not linked > Abnormal program termination Within hours, several people from across the nation answered me with "Yeah! I got something like that, too! I dunno why." This makes me feel much better--I wasn't the only one who hadn't read the FAQ list thoroughly recently. It took a Mr. Karl Heuer, of Interactive Systems, Cambridge, MA to set me straight by quoting, of all things, the FAQ list. The perceptive Mr. Heuer clearly knew that I must feel like a buffoon and kindly did not dwell on my error. I really *do* read these things. I swear. This one got by me. It's worth repeating here for those others (and now I know you're out there): >65. I'm having trouble with a Turbo C program which crashes and says > something like "floating point not loaded." > >A: Some compilers for small machines, including Turbo C and Ritchie's > original pdp11 compiler, attempt to leave out floating point support > if it looks like it will not be needed. In particular, the non- > floating-point versions of printf and scanf save space by not > including code to handle %e, %f, and %g. Occasionally the > heuristics for "is the program using floating point?" are > insufficient, and the programmer must insert one dummy explicit > floating-point operation to force loading of floating-point support. > Unfortunately, an apparently common sort of program (thus the > frequency of the question) uses scanf to read, and/or printf to > print, floating-point values upon which no arithmetic is done, which > elicits the problem under Turbo C. > > In general, questions about a particular compiler are inappropriate > for comp.lang.c . Problems with PC compilers, for instance, will > find a more receptive audience in a PC newsgroup. Apologies to the net. Thanks to Mr. Heuer. -- From the catapult of: |+| "If anyone disagrees with anything I _, J. D. Baldwin, Comp Sci Dept |+| say, I am quite prepared not only to __||____:::)=}- U.S. Naval Academy|+| retract it, but also to deny under \ / baldwin@cad.usna.navy.mil |+| oath that I ever said it." --T. Lehrer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
AHB3@Lehigh (10/16/90)
The problem is a bug. Pure and simple. I have heard that Turbo C 1.0 had the same problem. What is happening is the compiler doesn't realize that the variable being passed in is a floating point number, so it don't link in the floating point routines to scanf. When you uncomment the first scanf line, the compiler links the floating point routines into scanf. If you didn't know, the compiler doesn't know that the scanf routine will try to print a floating point number. Only scanf knows. The format string used by scanf is just a string to the compiler. Therefore, until they fix the bug (again), people will have to use temporary variables for floats and doubles. Arthur H. Boyd Lehigh U.
silver@xrtll.uucp (Hi Ho Silver) (10/20/90)
In article <15109018:58:51AHB3@lehigh.bitnet> AHB3@Lehigh writes:
$the compiler. Therefore, until they fix the bug (again), people will
$have to use temporary variables for floats and doubles.
Or you put a statement like
exp(1);
somewhere in your program. This will cause floating point library code
to be linked in.
--
HI ROGER |Nikebo says "Nikebo knows how to post. Just do it."| silver@xrtll
_________|-----------------------|_______________|------------|_____________
yunexus!xrtll!silver (L, not 1) | Hi Ho Silver | costing the net thousands
Silver: Ever Searching for SNTF |i need a grilf | upon thousands of dollars
root@candle.uucp (Bruce Momjian) (05/24/91)
I have been programming in C for almost 2 years, but have found the scanf family of functions to be confusing. Does anyone have addional documentation or explaination about how [f|s]scanf works beyond the manual page entries I have read. I thought I was the only one confused sometimes about it's behavior, but yesterday found that the other C programmer at my office also has had trouble with this major function.