spm2d@watt1.acc.Virginia.EDU (Steven Paul Miale) (10/12/90)
I have received many replies to my question about the safety of using scanf() in a program, including one flame, remarkably. I have decided to post the answers (overwhelmingly anti-scanf(), BTW). Keep in mind that this "survey" is not big enough to be judged accurate. However, I would still be cautious about using scanf() until then. First, the flame, just received: Date: Fri, 5 Oct 90 11:37:16 -0500 From: Judge Dredd <bob@en.ecn.purdue.edu> Message-Id: <9010051637.AA21255@en.ecn.purdue.edu> To: spm2d@watt1.acc.virginia.edu Subject: Re: scanf() problems Newsgroups: comp.lang.c In-Reply-To: <1990Oct4.130831.7814@murdoch.acc.Virginia.EDU> Organization: Purdue University Engineering Computer Network Status: RO In article <1990Oct4.130831.7814@murdoch.acc.Virginia.EDU> you write: >Recently, I have heard that many implementations of C have a buggy version ... >Please E-mail me, as I usually do not keep up with this newsgroup. Ever think that after taking the time to read your question that some of us might like to SEE THE ANSWERS?!?! Ever think how rude it is to jump into a group, tell it you want to use its resources, and then add that you won't be around long enough to read the answer, so you'll be sucking all the replies into your mailbox where only you can read them? Ever think that most of the people that read the group don't even post? They simply read the group to LEARN? Ever think that this learning is from reading people's questions and the POSTED replies? I understand how you might not have the time or whatever to read the group. No problem. So what's the solution? Well, if you look at any of the "netiquette" files floating around you'll see that the "proper" B thing to do in cases like this is to ask your question, request email, and ANNOUNCE IN THE ORIGINAL POSTING that you will be posting a summary in a week or whatever. And then do it. Also, you should keep ALL replies in a file for a reasonable amount of time and email that file to anyone who requests it. -- Bob Rusbasan bob@en.ecn.purdue.edu <ahem>. Now, some real answers: From: tanner@cdis-1.compu.com To: spm2d@watt1.acc.virginia.edu Subject: Re: scanf() problems Newsgroups: comp.lang.c In-Reply-To: <1990Oct4.130831.7814@murdoch.acc.Virginia.EDU> Organization: CompuData, Inc. (DeLand) X-Snail: 1409 E New York Ave; DeLand, FLA 32724. X-Phone: +1 904 736 0866 Message-Id: <00002CB@cdis-1.compu.com> Status: RO Even a working scanf() is bad news; avoid it like the plague. It does a poor job of coping with bad input, and will surely confuse interactive users. Use fgets() or something, and parse the input yourself. Even using sscanf() on the fgets()ed input is far better than using scanf(). -- uflorida!ki4pv!cdis-1!tanner {uunet dsinc}!cdin-1!cdis-1!tanner To: Steven Paul Miale <spm2d@watt1.acc.virginia.edu> Subject: Re: scanf() problems From: "Roy M. Silvernail" <cybrspc!roy@cs.umn.edu> Message-Id: <moHLq1w163w@cybrspc> Date: Fri, 05 Oct 90 19:53:57 CDT In-Reply-To: <1990Oct4.130831.7814@murdoch.acc.Virginia.EDU> Organization: Villa CyberSpace, Minneapolis, MN Status: RO spm2d@watt1.acc.Virginia.EDU (Steven Paul Miale) writes: > 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 While I haden't heard of scanf() crashing a disk, I still never use it. The reason is that scanf() expects input to be formatted properly, and you cannot guarantee that a user will not make a mistake. Input routines should always, IMHO, read to a buffer and _validate the inputted data_. At the least, a scanf() call may return unexpected data and/or leave unread data in the stdin buffer. At worst, data read may overwrite the end of an array and cause no end of havoc. 'Tis much safer to gets(), validate the string returned, and sscanf() the string. -- Roy M. Silvernail | #include <stdio.h> | Does virtual now available at: | main(){ | reality need cybrspc!roy@cs.umn.edu | float x=1; | swap space? (cyberspace... be here!)| printf("Just my $%.2f.\n",x/50);} | -- me B From: Dave Eisen <dkeisen@gang-of-four.stanford.edu> Message-Id: <9010050530.AA25480@Gang-of-Four.Stanford.EDU> To: spm2d@watt1.acc.virginia.edu Subject: Re: scanf() problems Newsgroups: comp.lang.c In-Reply-To: <1990Oct4.130831.7814@murdoch.acc.Virginia.EDU> Organization: Sequoia Peripherals Cc: Status: RO Even if scanf works, it doesn't work. You never want to use it because if the user doesn't happen to enter a statement that matches the correct format, scanf doesn't react intelligently. Uses gets and then sscanf the buffer you read into. -- Dave Eisen Home: (415) 323-9757 dkeisen@Gang-of-Four.Stanford.EDU Office: (415) 967-5644 1447 N. Shoreline Blvd. Mountain View, CA 94043 Reply-To: Stephen Clamage <steve@taumet.com> Message-Id: <9010051513.AA02049@taumet.com> Date: Fri, 5 Oct 90 15:13:07 GMT From: Stephen Clamage <steve@taumet.com> X-Local-Time: Fri, 5 Oct 90 08:13:07 PDT To: spm2d@watt1.acc.virginia.edu Subject: Re: scanf() problems Newsgroups: comp.lang.c References: <1990Oct4.130831.7814@murdoch.acc.Virginia.EDU> Status: RO In comp.lang.c you write: >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. Floating-point conversion routines in most C libraries tend not to be very good, since they are not usually written by numerical analysts. Unless you have an excellent reference, are a trained numerical analyst, or have a very restricted set of possible values to contend with, you may not be able to do any better. "Sigplan Notices", vol 25, No 6, June 1990, contains a pair of articles describing how to read and write floating-point values. It is hard to get right. I have never heard of scanf crashing a hard drive, but then I don't use scanf much -- actually never, except in throw-away test programs. Scanf does not give you proper control over reading input data produced by humans, which is full of weird typos and other errors. It does not give any good recovery mechanism when errors are encountered. It is generally clunky and error-prone to use (the most common error is to use the %f conversion to read a value into a double). If your C library has good implementations of strtoi(), strtol(), and strtod(), you can make a more robust program using these plus character input routines such as you describe. If you want a quick-and-dirty throw-away program, scanf should suffice if it doesn't trash your disk. -- Steve Clamage, TauMetric Corp, steve@taumet.com From: Richard Bumby <bumby@math.rutgers.edu> Message-Id: <9010051926.AA17708@math.rutgers.edu> To: spm2d@watt1.acc.virginia.edu Cc: bumby@math.rutgers.edu Subject: Re: scanf() problems In-Reply-To: USENET article <1990Oct4.130831.7814@murdoch.acc.Virginia.EDU> Status: RO In article <1990Oct4.130831.7814@murdoch.acc.Virginia.EDU> you wrote: > 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'm not a real C programmer, but I have used Whitesmith's C for an MC68000 based machine and Manx Aztec-C for the IBMPC. In both cases, there is more than one version of formatted I/O included in the libraries, and the two versions have different behavior in identical situations. It seems to be difficult to get this right. The main reason for using scanf() is to have a single function to use during development so that you don't have to think about I/O. You can usually learn the one or two strange features of the version that you have. Once you know what kind of input to expect, you will do much better with a customized interface -- and you can be reasonably sure that it will be portable, too. -- --R. T. Bumby ** Math ** Rutgers ** New Brunswick ** NJ08903 ** USA -- above postal address abbreviated by internet to bumby@math.rutgers.edu voice communication unreliable -- telephone ignored -- please use Email Date: Fri, 5 Oct 90 18:10:52 EDT From: Larry Jones <sdrc!scjones%thor@uunet.uu.net> Message-Id: <9010052210.AA00032@thor> To: uunet!watt1.acc.Virginia.EDU!spm2d@uunet.uu.net Subject: Re: scanf() problems In-Reply-To: your article <1990Oct4.130831.7814@murdoch.acc.Virginia.EDU> News-Path: sdrc!uunet!know!zaphod.mps.ohio-state.edu!wuarchive!udel!haven!uvaarpa!murdoch!watt1.acc.Virginia.EDU!spm2d Status: RO > 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. I think you need some new C authorities. ;-) Most versions of scanf work just fine, although they do not all agree on all of the finer and more obscure details of formatting. On the other hand, scanf is deceptively easy to use and nearly impossible to use in a completely correct and robust manner, which has lead many people to recommend using a combination of fgets and sscanf instead of scanf. Perhaps that was the point your local experts were trying to make. ---- Larry Jones UUCP: uunet!sdrc!thor!scjones SDRC scjones@thor.UUCP 2000 Eastman Dr. BIX: ltl Milford, OH 45150-2789 AT&T: (513) 576-2070 I don't like these stories with morals. -- Calvin
ttobler@unislc.uucp (Trent Tobler) (10/20/90)
[many comments on the evils of scanf] People, scanf is not BAD, only people who use it as their primary input function. Scanf is a very powerful pattern matching function and can save a lot of code in parsers and tokenizers. I think the main reason everyone is anti-scanf is that in many languages, there is a primary input function (readln, input, etc.), and scanf is often assigned this purpose by many C programming classes/tutorials. This is the reason that many of the problems of scanf are encountered. I believe that scanf should be taught only after a strong knowlegde in C is attained. The gets function should be used as the beginning primary input function. Later, when files are learned, this should switch to fgets, to avoid the problem of overflow allocated string space. Scanf should not ever be considered a primary input function. Use it to parse, and match patterns from the input stream. I think most people who abhore scanf have been told by other people that scanf is EVIL. More than likely, it was after a catastrophic failure from thier use of it as a primary input function. Improper use can cause infinite loops, lockups, and core dumps. But, on the other side, scanf is a very powerful tool . It can reduce time to develop a program, reduce code size, and even make a program more maintainable. Trent Tobler.
donn@brat.UUCP (Donn Pedro) (10/26/90)
In article <1990Oct20.001637.28244@unislc.uucp>, ttobler@unislc.uucp (Trent Tobler) writes: > > [many comments on the evils of scanf] > > People, scanf is not BAD, [ rest of the sensible talk deleted for brevity.] We discussed scanf() in my C course today. The insructor basically said to be cautious of scanf() but not fearful to use it. He said it can be a very useful and powerful tool *as long as* you understand it's limitations and foibles. To paraphrase: Commnads don't kill data. People kill data. Donn F Pedro ....................a.k.a. uunet!nwnexus!mcgp1!brat!donn else: {the known world}!uunet!nwnexus!mcgp1!brat!donn
poser@csli.Stanford.EDU (Bill Poser) (10/28/90)
I don't see why it is necessary to worry about scanf(). It is safe to use directly only when you are quite sure of the input format, which is not very often. But you can use its parsing facilities safely by reading input using a safe getline function (I often use one that strips comments and allows quoting of newlines in place of one that merely counts input characters to prevent overflowing the buffer) and then using sscanf(). Except for one-shot programs I suggest avoiding fscanf() altogether and using sscanf plus a safe input function.
adrian@mti.mti.com (Adrian McCarthy) (10/30/90)
The VAX C 3.0 library version of sscanf() doesn't handle unsigned values at
all (according to the docs). In particular I needed a text to unsigned long
conversion. I used the strtoul() function, but I was wondering if anyone
knows if 3.1 added this functionality to sscanf().
Also, does Henry Spencer's commandment about checking the return values of all
functions for errors apply to sscanf()? Since sscanf() is supposed to return
the number of successful conversions, it seems reasonable to do things like:
if (sscanf(str, "%d %d", &x, &y) != 2) {
fprintf(stderr, "Error parsing string.\n");
exit(PARSE_ERROR);
}
Right?
Aid. (adrian@gonzo.mti.com)
henry@zoo.toronto.edu (Henry Spencer) (10/31/90)
In article <1204@mti.mti.com> adrian@mti.UUCP (Adrian McCarthy) writes: >Also, does Henry Spencer's commandment about checking the return values of all >functions for errors apply to sscanf()? ... > if (sscanf(str, "%d %d", &x, &y) != 2) { So long as you are checking the return value, and not just blindly assuming that sscanf will work, that satisfies the intent of the commandment. -- "I don't *want* to be normal!" | Henry Spencer at U of Toronto Zoology "Not to worry." | henry@zoo.toronto.edu utzoo!henry
msb@sq.sq.com (Mark Brader) (11/07/90)
> ... it seems reasonable to do things like: > if (sscanf(str, "%d %d", &x, &y) != 2) { > fprintf(stderr, "Error parsing string.\n"); > exit(PARSE_ERROR); > } Sure. But don't imagine that you've checked the syntax of the string by doing that. If it's supposed to contain precisely two numbers and nothing else, one way to do it is: char junk; ... if (sscanf(str, "%d %d%c", &x, &y, &junk) != 2) { fprintf(stderr, "Error parsing string.\n"); exit(PARSE_ERROR); } If there is anything after the second number, sscanf() will now return 3. Notice incidentally that this is one of the few places where it's reasonable in C to have a scalar variable of type char. Normally time efficiency is more important than space efficiency for scalars, so you use int, but here the address of the variable must be char * to match the %c directive, and you aren't going to read from it anyway. -- Mark Brader "Exercise 5-3: ... When should you SoftQuad Inc., Toronto have stopped adding features...?" utzoo!sq!msb, msb@sq.com -- Kernighan & Pike This article is in the public domain.
jhp@apss.ab.ca (Herbert Presley) (06/06/91)
I am a new C programmer and I've been trying to get an answer through the net for the following problem. Unfortunately, my postings don't seem to be getting through for some reason. I kinda feel intimidated because, like most new programmers, I am probably asking a question that has a VERY simple response, and I can't help but feel that it's a problem that I am creating by my lack of knowledge. For your information, I run a Turbo C compiler on an XT (true) compatible. scanf() and gets() will not accept keyboard input in the same program if scanf() is used first. I am using scanf() to accept an integer from the keyboard and gets() to accept a string. Because scanf() aborts input at the first whitespace, you cannot enter a sentence string (or, is this something I am doing wrong because of my inexperience)? So in instances where you are attempting to enter a formatted integer variable and a string in the same program, I find that using scanf() first makes gets() skip the wait for keyboard input. Unfortunately, I have no mentor in my world who knows very much about C. I began with C through a couple of courses at our local Technical College and they don't seem to offer a great deal of ongoing support. ___________________________________________________________________________ email : jhp@apss.ab.ca mail : c/o APSS, 10320 - 146 St., Edmonton, Alberta, Canada T5N 3A2 phone : (403) 451-7151
gordon@osiris.cso.uiuc.edu (John Gordon) (06/07/91)
jhp@apss.ab.ca (Herbert Presley) writes: >scanf() and gets() will not accept keyboard input in the same program if >scanf() is used first. I am using scanf() to accept an integer from the >keyboard and gets() to accept a string. Because scanf() aborts input at >the first whitespace, you cannot enter a sentence string (or, is this something >I am doing wrong because of my inexperience)? So in instances where you are >attempting to enter a formatted integer variable and a string in the same >program, I find that using scanf() first makes gets() skip the wait for >keyboard input. Here is your problem: scanf() leaves a carriage return hanging in the input buffer. Since gets() ends on a carriage return, it picks this up immediately and quits. My solution is to do a getchar() right after a scanf() and suck up the floating carriage return. --- John Gordon Internet: gordon@osiris.cso.uiuc.edu #include <disclaimer.h> gordon@cerl.cecer.army.mil #include <clever_saying.h>
darwinl@alliance.uucp (Darwin Ling) (06/07/91)
In article <2759@apss.apss.ab.ca> jhp@apss.ab.ca (Herbert Presley) writes: > >I am a new C programmer and I've been trying to get an answer through the net >for the following problem. Unfortunately, my postings don't seem to be getting >through for some reason. > >I kinda feel intimidated because, like most new programmers, I am probably >asking a question that has a VERY simple response, and I can't help but feel >that it's a problem that I am creating by my lack of knowledge. > >For your information, I run a Turbo C compiler on an XT (true) compatible. > >scanf() and gets() will not accept keyboard input in the same program if >scanf() is used first. I am using scanf() to accept an integer from the >keyboard and gets() to accept a string. Because scanf() aborts input at >the first whitespace, you cannot enter a sentence string (or, is this something >I am doing wrong because of my inexperience)? So in instances where you are >attempting to enter a formatted integer variable and a string in the same >program, I find that using scanf() first makes gets() skip the wait for >keyboard input. > >Unfortunately, I have no mentor in my world who knows very much about C. I >began with C through a couple of courses at our local Technical College and >they don't seem to offer a great deal of ongoing support. >___________________________________________________________________________ > > email : jhp@apss.ab.ca > mail : c/o APSS, 10320 - 146 St., Edmonton, Alberta, Canada T5N 3A2 > phone : (403) 451-7151 You can try the following : Use fgets to get whatever from the standard input.... For string, if the last string character is a '\n' , ie a newline character, replace it with '\0'. You can find the last character's position by strlen (str) - 1 . For integer , do the same thing to eliminate the '\n' , then convert the integer string to integer using sscanf (str, "%d", &integer_value) str is the string you get from fgets.. sscanf works exactly the same as scanf except sscanf scans from a string, while scanf scans its input from the standard input... You can use the desired format for the integer Hope that helps ------------------------------------------------------------------ Darwin Ling Alliance Technologies , Inc Advanced Development group uunet : uunet!alliance!darwinl ------------------------------------------------------------------
black@beno.CSS.GOV (Mike Black) (06/07/91)
NEVER USE THESE FUNCTIONS! 1. scanf() and fscanf() - if you don't input the EXACT format you are scanning for, your input stream will no proceed any further. i.e. scanf("%d",&i) will stop when you type "hello" and will not scan blasted thing until you read in the hello with another function. 2. gets() - It doesn't check to make sure you don't overrun the char array you pass it. INSTEAD USE THESE! 1. fgets() followed by sscanf() - This gives you complete control over your input stream by allowing you to discard garbage. i.e. char buf[100]; fgets(buff,100,stdin); if(sscanf(buf,"%d",&i) != 1) puts("You typed the wrong thing!"); 2. fgets() - it's the same as gets with 2 more arguments, the main one of which is the maximum length of your array. One of the other benefits of using fgets() and sscanf() on numeric input is it's generally quite faster than fscanf(). Try it! Mike... -- ------------------------------------------------------------------------------- : usenet: black@beno.CSS.GOV : land line: 407-494-5853 : I want a computer: : real home: Melbourne, FL : home line: 407-242-8619 : that does it all!: -------------------------------------------------------------------------------
darcy@druid.uucp (D'Arcy J.M. Cain) (06/07/91)
In article <1991Jun6.182118.16211@ux1.cso.uiuc.edu> John Gordon writes: >jhp@apss.ab.ca (Herbert Presley) writes: >>scanf() and gets() will not accept keyboard input in the same program if [ description of the usual scanf/gets problem deleted ] > Here is your problem: scanf() leaves a carriage return hanging in the >input buffer. Since gets() ends on a carriage return, it picks this up >immediately and quits. My solution is to do a getchar() right after a scanf() >and suck up the floating carriage return. Actually he has two problems. First he didn't read the FAQ and secondly he is getting advice from people who haven't read the FAQ. Here is the definitive answer: READ THE FREQUENTLY ASKED QUESTIONS In particular question #77 answers this: 77. When I read from the keyboard with scanf(), it seems to hang until I type one extra line of input. A: scanf() was designed for free-format input, which is seldom what you want when reading from the keyboard. In particular, "\n" in a format string does not mean "expect a newline", it means "discard all whitespace". It is usually better to fgets() to read a whole line, and then use sscanf() or other string functions to parse the line buffer. If you are going to answer questions please read the FAQ first. This is also excellent advice before asking one. -- D'Arcy J.M. Cain (darcy@druid) | D'Arcy Cain Consulting | There's no government Toronto, Ontario, Canada | like no government! +1 416 424 2871 |
crr@cbnewsm.att.com (Chris Riley (201) 564-2516) (06/08/91)
In article <2759@apss.apss.ab.ca> jhp@apss.ab.ca (Herbert Presley) writes: >I kinda feel intimidated because, like most new programmers, I am probably >asking a question that has a VERY simple response, and I can't help but feel >that it's a problem that I am creating by my lack of knowledge. That's ok. That's what stuff like comp.lang.c is for. >scanf() and gets() will not accept keyboard input in the same program if >scanf() is used first. I am using scanf() to accept an integer from the >keyboard and gets() to accept a string. Because scanf() aborts input at >the first whitespace, you cannot enter a sentence string (or, is this something >I am doing wrong because of my inexperience)? So in instances where you are >attempting to enter a formatted integer variable and a string in the same >program, I find that using scanf() first makes gets() skip the wait for >keyboard input. It is generally unsafe to use scanf() to read from the keyboard. Since scanf() will loose data if the data isn't formatted the way it likes, it is dangerous to use scanf() unless the data you are reading was generated by another program. A safer method is to read a string with gets() or fgets(), then use sscanf() to look for the data in the string. If the data isn't in the right format, you have a chance to try to figure out what it is. -- Chris Riley chris.riley@attbl.att.com
naftaly@dazixco.ingr.com (Naftaly Stramer) (06/13/91)
Where can I find those Frequently Asked Questions ? -- Naftaly Stramer (303)581-1477 DAZIX, An Intergraph Company Internet: naftaly@dazixco.ingr.com 6285 Lookout Road UUCP: ..uunet!ingr!dazixco!naftaly Boulder, CO 80301 Please excuse my english