| | |
scanf discussion
Please support our C advertiser: Programming Forums - DaniWeb Sister Site
![]() |
>I disagree. You have to have all kinds of special code to get scanf() to work properly.
Only if you aren't using scanf for what it was designed in the first place. When you have to write workaround code to get a function to work, you're using the wrong tool or using it the wrong way. This is probably not the best place to critique your link, but I'll do it anyway. I'll quote you (WaltP) with > and the link with quote tags.
I'm not sure if he's being humble or really hasn't studied scanf fully. As some background, I, on the other hand, have studied it completely for many years, and also implemented it completely for both C89 and C99 several times (each in a different way). I like to think I have a strong understanding of how scanf works, and that's what guides my opinions. But that's probably also going to give me more of a liberal perspective because I'm not afraid of the function in any way as it holds no mysteries for me. 
While he's not wrong (assuming it's a he), getchar has the same problem. This is related to how streams work, not scanf specifically.
Sure, scanf does a lot. But so does printf (probably even more so), and I don't see this guy railing on printf for taking up instruction space.
This whole part of the argument strikes me as unnecessary fluff that gets in the way of the real issues and tries to bolster the argument.
Assuming you only need a character and there's no special formatting, I agree that getchar is the better choice. But the author is talking about a strict subset of how you might use the %c specifier.
Yea, if you have to clear the "keyboard" buffer like that, something is wrong with your input process. It's not scanf or getchar that left garbage in the stream, but the programmer's sloppy use of them. A good input method won't throw anything away unconditionally, which makes that discarding loop little more than a kludgy hack.
The difference is that scanf can be fixed while gets can't. If you aren't providing a minimum field width for %s, you shouldn't be using it in the first place. Lack of understanding about the specifiers doesn't make scanf bad. You can do the same thing with fgets if you don't know what you're doing:
I usually teach %s as requiring a field width and if you omit the field width, you get undefined behavior. That's not far from the truth, so it tends to work well. 
It's necessary after every input function at all to check the return status to see if it worked. That's programming 101, not an issue with scanf specifically.
In much the same way I could argue that this use of fgets fails as a viable input mechanism because you can't tell if there's more input on the line:
You might say "Sure, but you're using fgets wrong if you want to check for long lines!", and I'd retort with "And you're using scanf wrong if you want to error check poorly formatted user input". scanf was designed for formatted input. User input can't be guaranteed to be formatted in the console. This is a case of the wrong tool being used for the job.
This is orders of magnitude more complicated, more error prone, and could easily result in the very code bloat that the author complains about for scanf. The strto* functions aren't exactly trivial, and you'd end up writing application specific parsing algorithms each and every time you want a number because any generic solution would cause the same problems that you're "solving" by not using sscanf.
scanf is designed for production code, but it's not a panacea. This author seems to think that scanf is a jack of all trades meant to be used everywhere, when it really isn't.
Why the loop? What if "whitespace" for the locale isn't limited to those characters? Yet you can still use scanf to solve the problem without the bugs or complexity (or poor style by assuming a character set) by adding a leading space to the format string:
>Best to switch to fgets() and be safe.
fgets has problems too. You're not going to find an input mechanism to switch to that doesn't have confusing issues.
>Then for formatted input use sscanf() to break the input apart.
All of the scanf problems are still there with sscanf. You don't have to deal with extra characters on the stream, but you still have to deal with error checking the source outside of sscanf. So if you're getting the string from the user, for sscanf to work properly, you'd have to fit a validation step between fgets and sscanf to verify that the string is in the correct format (or if sscanf fails).
Despite what the regulars here say, switching from scanf to fgets/sscanf isn't going to solve all of your problems with scanf.
Only if you aren't using scanf for what it was designed in the first place. When you have to write workaround code to get a function to work, you're using the wrong tool or using it the wrong way. This is probably not the best place to critique your link, but I'll do it anyway. I'll quote you (WaltP) with > and the link with quote tags.
•
•
•
•
Admittedly, I've never studied the scanf() fully.

•
•
•
•
They want to read a character from the keyboard so they very logically use the format string "%c". Then wonder why the next read is messed up. How are they supposed to know that after the character was read there was a \n left behind?
•
•
•
•
To examine the size of the scanf() function, I built the following programs to check the executable sizes.
This whole part of the argument strikes me as unnecessary fluff that gets in the way of the real issues and tries to bolster the argument.•
•
•
•
So use getchar() instead. It's easier and designed exactly for the task at hand.
•
•
•
•
Just remember to clear the keyboard buffer. In either case, the trailing \n will be left in the input stream.
•
•
•
•
scanf() and gets() have the exact same problem with memory overrun.
c Syntax (Toggle Plain Text)
char s[10]; if ( fgets ( s, INT_MAX, stdin ) != NULL ) { /* ... */ }

•
•
•
•
It is therefore necessary after every scanf() call that reads non-character data (ints, floats, etc.) to check the return status to see if it worked.
•
•
•
•
Based on these tests, I would say scanf() just failed as a viable input mechanism.
c Syntax (Toggle Plain Text)
char s[10]; if ( fgets ( s, sizeof s, stdin ) != NULL ) { char *nl = strchr ( s, '\n' ); if ( nl != NULL ) *nl = '\0'; /* ... */ }
•
•
•
•
So individual parsing of the user's keyboard input is the only way to make your input bulletproof. You have to take over and use tried and true conversion functions to read numbers and not rely on scanf() to do the job.
•
•
•
•
scanf() is not designed for production code, but for creating test programs to see if other aspects of the program are working. scanf() will replace the complicated input routines so that other modules can be exercised and perfected. Then the scanf() is replaced with the real input function that gets the actual data from a file, a device, wherever the actual data is stored.
•
•
•
•
This will keep reading until there is a non-whitespace character entered, effectively clearing the buffer from previous scanf() calls.
c Syntax (Toggle Plain Text)
scanf ( " %c", &ch );
fgets has problems too. You're not going to find an input mechanism to switch to that doesn't have confusing issues.
>Then for formatted input use sscanf() to break the input apart.
All of the scanf problems are still there with sscanf. You don't have to deal with extra characters on the stream, but you still have to deal with error checking the source outside of sscanf. So if you're getting the string from the user, for sscanf to work properly, you'd have to fit a validation step between fgets and sscanf to verify that the string is in the correct format (or if sscanf fails).
Despite what the regulars here say, switching from scanf to fgets/sscanf isn't going to solve all of your problems with scanf.
•
•
•
•
>I disagree. You have to have all kinds of special code to get scanf() to work properly.
Only if you aren't using scanf for what it was designed in the first place. When you have to write workaround code to get a function to work, you're using the wrong tool or using it the wrong way.
scanf() is dangerous and inadequate reading strings (only reads to whitespace, and can easily blow your buffer if no spaces are in the input)It's overkill if you want to read a single character. Why bring in the code for translating %d, %i, %f, etc. when
getchar() does exactly the same thing in a small footprint?After reading a number, the input stream still has characters left and must be cleared if reading strings next. This requires "fix-up" code.
I am of course targeting those that learn
scanf() in school. Instructors never seem to explain any of the problems associated with the function, letting their students flounder. They are not taught the formatting characters required to use scanf() cleanly. That's why all the forums are inundated with questions about skipped input, partial input, and looping input. •
•
•
•
I'm not sure if he's being humble or really hasn't studied scanf fully. As some background, I, on the other hand, have studied it completely for many years, and also implemented it completely for both C89 and C99 several times (each in a different way). I like to think I have a strong understanding of how scanf works, and that's what guides my opinions. But that's probably also going to give me more of a liberal perspective because I'm not afraid of the function in any way as it holds no mysteries for me.
scanf() to be inadequate for production code because of it's lack of error checking, ability to bulletproof, and convoluted format specifiers attempting to correct anomalies. Therefore I use it only for testing.•
•
•
•
While he's not wrong (assuming it's a he), getchar has the same problem. This is related to how streams work, not scanf specifically.
Yes,
getchar() has the same problem (but it's less hidden IMO). My complaint is the function footprint in this case. I see a lot of code that uses only one scanf(), and that's to read a single character.•
•
•
•
Sure, scanf does a lot. But so does printf (probably even more so), and I don't see this guy railing on printf for taking up instruction space.This whole part of the argument strikes me as unnecessary fluff that gets in the way of the real issues and tries to bolster the argument.
printf(). Yes, formatted input is necessary, but scanf() has too many problems. sscanf() simply clears up the biggest problems. But using fgets() first allows the input to be checked before translating bad data. Can't do that with scanf().•
•
•
•
Yea, if you have to clear the "keyboard" buffer like that, something is wrong with your input process. It's not scanf or getchar that left garbage in the stream, but the programmer's sloppy use of them.
•
•
•
•
The difference is that scanf can be fixed while gets can't. If you aren't providing a minimum field width for %s, you shouldn't be using it in the first place. Lack of understanding about the specifiers doesn't make scanf bad.
•
•
•
•
It's necessary after every input function at all to check the return status to see if it worked. That's programming 101, not an issue with scanf specifically.
•
•
•
•
You might say "Sure, but you're using fgets wrong if you want to check for long lines!", and I'd retort with "And you're using scanf wrong if you want to error check poorly formatted user input". scanf was designed for formatted input. User input can't be guaranteed to be formatted in the console. This is a case of the wrong tool being used for the job.
•
•
•
•
This is orders of magnitude more complicated, more error prone, and could easily result in the very code bloat that the author complains about for scanf. The strto* functions aren't exactly trivial, and you'd end up writing application specific parsing algorithms each and every time you want a number because any generic solution would cause the same problems that you're "solving" by not using sscanf.
strto*() functions. Parsers are the most bulletproof functions available -- because you write them to exacting specifications. And they can be added to a library for easy retrieval.•
•
•
•
scanf is designed for production code, but it's not a panacea. This author seems to think that scanf is a jack of all trades meant to be used everywhere, when it really isn't.
•
•
•
•
Despite what the regulars here say, switching from scanf to fgets/sscanf isn't going to solve all of your problems with scanf.
------------
•
•
•
•
You might say "Sure, but you're using fgets wrong if you want to check for long lines!", and I'd retort with "And you're using scanf wrong if you want to error check poorly formatted user input".
scanf() is meant for user input! Meatware sitting at a keyboard! Isn't that the definition of "poorly formatted input?" At least with fgets() you have the chance to test the input before translation and actually doing error cleanup before it's too late.•
•
•
•
scanf was designed for formatted input. User input can't be guaranteed to be formatted in the console. This is a case of the wrong tool being used for the job.
scanf() is designed for user input, and user input cannot be guaranteed to be formatted, then scanf() is the wrong tool for the job! Doh! Allow me to reiterate:
You said it yourself....
The 3 Laws of the Procrastination Society:
1) Never do today that which can be put off until tomorrow
2) Tomorrow never comes
1) Never do today that which can be put off until tomorrow
2) Tomorrow never comes
I didn't realize you were the one who wrote those articles. 
%s isn't the only way to read strings, but I'll take your point as talking only about %s without a field width.
So is printf for a lot of ways it's used. I don't see that as a flaw in printf, do you? 
If you're using the function incorrectly, and then kludging up your code to fix it, I'd call that sloppy.
Why is that an error? Did it occur to you that the R might be there in anticipation of the next input request? One of my biggest pet peeves is code that always clears the line to remove "garbage", when what I typed was most certainly not garbage.
So you advocate ignoring the standard library and writing your own parsers from scratch?
Here:
Using sscanf doesn't correct the majority of the issues you raise in your articles.
C doesn't recognize meatware or keyboards. scanf is meant for formatted input from stdin. It happens that stdin is often connected to an interactive input device these days, but I would claim that the design of scanf is meant more for filter programs where input is piped or redirected from a formatted source.

•
•
•
•
scanf() is dangerous and inadequate reading strings (only reads to whitespace, and can easily blow your buffer if no spaces are in the input)
•
•
•
•
It's overkill if you want to read a single character.

•
•
•
•
It's not a sloppy programmer...
•
•
•
•
If you are reading a %d field and enter 23R you get no indication of an error.
•
•
•
•
Parsers are the most bulletproof functions available -- because you write them to exacting specifications.
•
•
•
•
What?!?! Where do you get the idea I think it is "meant to be used everywhere"?
•
•
•
•
scanf() is a Jack of all trades function. It has been designed to handle as many input types as possible, from simple characters to scientific notation and complex values. And because of this, the design seems lacking in some areas.
I don't know the key to success, but the key to failure is trying to please everybody. -- Bill Cosby
That's how I feel about scanf().
•
•
•
•
No, but it solves most of them...
•
•
•
•
But scanf() is meant for user input! Meatware sitting at a keyboard!
Surprise!!!!
I didn't say it's a flaw in scanf(). Reading a char is necessary and useful when reading formatted input that contains varied field types, including char. But for reading only 1 char, that's my argument. Just as using printf() to output only a single char is IMO a misuse.
Given what a student programmer generally knows, how is using scanf() to read an int and leaving the return in the buffer sloppy on the programmer's part? Code must be added to clear the buffer or a convoluted format specifier must be handed to them. And I'll bet many, if not most, instructors have no idea how to clear the buffer using scanf() while reading a number. Especially with ill-formatted input via user-error.
Since I came up with the example, you can be absolutely assured that the R in "23R" is an invalid input, not meant for the next input.
For bullet-proof input, especially from the keyboard, absolutely. If you know for a fact that the input will be formatted correctly each and every time from stdin, scanf() is fine. But it just isn't so when people are involved in generating the input.
Often? These days? Are you saying that stdin at during the beginning development of C was never attached to a keyboard? During development of the language and run-time all input was piped into the test code? And attaching it to the keyboard is rare -- and a new development? I know you;re not that naive... 
Yes, C is a 'deviceless' language. But stdin has always been attached to the keyboard from the beginning, and can be redirected from elsewhere. I therefore agree with you, scanf() was not meant for user input but formatted input. And because of that it's just barely adequate for user/keyboard input. And C by definition and design was not meant for user interaction. Unfortunately, it does need to interact, and scanf() has been the function of choice.
I still say there are better ways to get user input.
•
•
•
•
So is printf for a lot of ways it's used. I don't see that as a flaw in printf, do you?
•
•
•
•
If you're using the function incorrectly, and then kludging up your code to fix it, I'd call that sloppy.
•
•
•
•
Why is that an error? Did it occur to you that the R might be there in anticipation of the next input request? One of my biggest pet peeves is code that always clears the line to remove "garbage", when what I typed was most certainly not garbage.
•
•
•
•
So you advocate ignoring the standard library and writing your own parsers from scratch?
•
•
•
•
C doesn't recognize meatware or keyboards. scanf is meant for formatted input from stdin. It happens that stdin is often connected to an interactive input device these days, but I would claim that the design of scanf is meant more for filter programs where input is piped or redirected from a formatted source.
Yes, C is a 'deviceless' language. But stdin has always been attached to the keyboard from the beginning, and can be redirected from elsewhere. I therefore agree with you, scanf() was not meant for user input but formatted input. And because of that it's just barely adequate for user/keyboard input. And C by definition and design was not meant for user interaction. Unfortunately, it does need to interact, and scanf() has been the function of choice.
I still say there are better ways to get user input.
The 3 Laws of the Procrastination Society:
1) Never do today that which can be put off until tomorrow
2) Tomorrow never comes
1) Never do today that which can be put off until tomorrow
2) Tomorrow never comes
•
•
•
•
But for reading only 1 char, that's my argument. Just as using printf() to output only a single char is IMO a misuse.

•
•
•
•
Given what a student programmer generally knows, how is using scanf() to read an int and leaving the return in the buffer sloppy on the programmer's part?
•
•
•
•
And I'll bet many, if not most, instructors have no idea how to clear the buffer using scanf() while reading a number. Especially with ill-formatted input via user-error.

•
•
•
•
Since I came up with the example, you can be absolutely assured that the R in "23R" is an invalid input, not meant for the next input.
•
•
•
•
If you know for a fact that the input will be formatted correctly each and every time from stdin, scanf() is fine.
•
•
•
•
I know you;re not that naive...
•
•
•
•
I still say there are better ways to get user input.
Certainly I am grateful to Ptolemy and WaltP for continuing this conversation; if only because indirectly expose a fundamental principle of the heritage of the C language. Which is that “C was developed by people that knew for people that know” or in other words “created by programmers for programmers”
Therefore someone that wants to be a programmer; and I don't mean “programmer as: I compiled this
code and it works”, ( for that we always have Visual Basic ); needs to stand in borrowed knowledge.
At least until understanding comes along.
For that reason I still stand behind my words:
Never was my intention to propose the avoidance all together of the usage of scanf, but rather a direct hint to the OP that perhaps “he/she was not ready to use it”. Using a wore out cliché : “There is a time and place for using scanf” And the time is not when you don't know when you need to use a loop, nor how to use a break statement. And the place is not when you don't know how to control the flow of the program, nor how to deal with user input.
As it has been said in the past: “You need to learn how to walk before you can run”
And this all too cavalier usage of scanf to gather inputted information doesn't help in the pursue of a secure footage. Too many “gotchas”, even for knowledgeable people.
As an example I would like to bring to attention a post from the original thread that started this dialog:
As a response to my posted snippet;
Not seeing that there was a point to it. Which it was to clear the buffer input as soon as possible in case that the right answer was entered. Knowing that in the event of a successful input the “enter key” would be there; why not to get rid of it, and clear the way for any other gathering input function or call
to collect the right data? In this case so the last getchar() would be able to pause the program as intended.
Instead attention was only shown to the getchar inside the while loop.
As I said too many “gotchas”.
Therefore someone that wants to be a programmer; and I don't mean “programmer as: I compiled this
code and it works”, ( for that we always have Visual Basic ); needs to stand in borrowed knowledge.
At least until understanding comes along.
For that reason I still stand behind my words:
•
•
•
•
>Haven't you figure out yet why you should avoid using scanf?
To which Ptolemy responded:
>I don't think you should avoid scanf. I think you should learn how it works so that you can use it intelligently.
As it has been said in the past: “You need to learn how to walk before you can run”
And this all too cavalier usage of scanf to gather inputted information doesn't help in the pursue of a secure footage. Too many “gotchas”, even for knowledgeable people.
As an example I would like to bring to attention a post from the original thread that started this dialog:
As a response to my posted snippet;
C Syntax (Toggle Plain Text)
/* skunk.c */ #include <stdio.h> int main( void ) { int i = 0; char c = '\0'; fputs( "Enter an integer: ", stdout ); fflush( stdout ); while( scanf( "%d%c", &i, &c ) != 2 ) { while ( ( c = getchar() ) != '\n' && c != EOF ); printf( "Invalid input! Please enter the value again: " ); fflush( stdout ); } printf( "i = %d\n", i ); getchar(); return 0; }
•
•
•
•
Ptolomy wrote:
>while( scanf( "%d%c", &i, &c ) != 2 )
There's really no point reading c here because the next thing you do is getchar into c.
to collect the right data? In this case so the last getchar() would be able to pause the program as intended.
Instead attention was only shown to the getchar inside the while loop.
As I said too many “gotchas”.
Last edited by Aia; Oct 23rd, 2007 at 7:04 pm.
Good... Because this is exactly the type of input that has caused massive brain hemorrhages in students on help forums. 
I never said ignore them. Only gets(). And if you noticed, I also suggested using
Two responses:
#1:
Agreed. And my point is that students are users that simply do not understand the function and instructors should either:
1) stop teaching it early
2) explain it has problems and use it sparingly -- if things don't work you've been warned
3) teach the darn thing! Give the student a full day on format specifiers and the anomalies the function causes.
They do none of the above, it seems, from the questions posted here.
#2:
Then what the heck are you arguing about? "I'm not trying to convince you that scanf is suitable for user input" is exactly my point. All I'm talking about is user input, because that is what
You're welcome. These discussions are fun, and I always glean new insights. Sometimes I even change my mind 
Yes...
•
•
•
•
Not just scanf. If I don't know for a fact that the input will be formatted correctly each and every time. It looks like you want me to ignore scanf, sscanf, strto*, ato*, and any other existing parsing mechanism in favor of my own hand rolled application-specific parser.
sscanf(). I personally don't like strto*() functions. But I do use ato*() functions, even with their potential traps. And that's because in those programs I've already validated the input and know the functions won't cause problems. You simply can't validate input with scanf(). But you can with sscanf(). •
•
•
•
I think you got mixed up somewhere along the line. I'm not trying to convince you that scanf is suitable for user input. I'm addressing your attacks on scanf by showing you that it's the user of the function and not the function itself that's the problem.
#1:
Agreed. And my point is that students are users that simply do not understand the function and instructors should either:
1) stop teaching it early
2) explain it has problems and use it sparingly -- if things don't work you've been warned
3) teach the darn thing! Give the student a full day on format specifiers and the anomalies the function causes.
They do none of the above, it seems, from the questions posted here.
#2:
Then what the heck are you arguing about? "I'm not trying to convince you that scanf is suitable for user input" is exactly my point. All I'm talking about is user input, because that is what
scanf() is used for 99% of the time. •
•
•
•
Certainly I am grateful to Ptolemy and WaltP for continuing this conversation; if only because indirectly expose a fundamental principle of the heritage of the C language. Which is that “C was developed by people that knew for people that know” or in other words “created by programmers for programmers”
Yes...
The 3 Laws of the Procrastination Society:
1) Never do today that which can be put off until tomorrow
2) Tomorrow never comes
1) Never do today that which can be put off until tomorrow
2) Tomorrow never comes
![]() |
Similar Threads
- Source code for printf, scanf, cin, cout? (C)
- Scanf problem (C)
- scanf - compiles but causes error (C++)
Other Threads in the C Forum
- Previous Thread: Integer Value!
- Next Thread: fork->how parent refer child process results
| Thread Tools | Search this Thread |
#include adobe ansi api array arrays asterisks binarysearch calculate centimeter char convert copyimagefile cprogramme creafecopyofanytypeoffileinc createcopyoffile csyntax directory dynamic fflush file fork forloop framework frequency getlasterror givemetehcodez grade graphics gtkgcurlcompiling hacking hardware highest homework i/o inches incrementoperators infiniteloop kernel km linked linkedlist linux linuxsegmentationfault list lists locate logical_drives looping loopinsideloop. match matrix microsoft motherboard multi mysql number open opendocumentformat opensource owf pattern pdf performance pointer pointers posix probleminc process program programming radix recursion recv repetition research scanf scheduling scripting segmentationfault send sequential shape socket socketprograming stack standard string strings structures systemcall testautomation threads turboc unix user variable voidmain() wab windows.h






