scanf - The Unknown Workhorse

C-Scene
Issues 1..9
Authors
Algorithms
Books
Patterns
Graphics
Miscellaneous
UNIX
Web & XML
Windows
Feedback
FAQs
Changes
Submissions

Content
1.   Introduction
2.   Pitfalls to avoid
3.   Parsing
3.1.   "Trial and Error" parsing
3.2.   Incremental parsing
4.   Using character set formats
5.   Conclusion
6.   References

by Jürgen Hermann
last updated 2000/02/16 (version 1.2)
also available as XML

NoteThis article is work in progress and not yet finished!

Introduction
 

The scanf family of functions, while quite powerful, is most often used only by beginners (because they do not know other ways of input) or for simple conversions from string to other types (where the strtoX() family of functions is much more appropriate).

Problems of scanf and fscanf, regarding keeping track of position...

Note Due to the problems associated with scanf and fscanf, we only use sscanf in the following examples. You should do the same in your code.

Pitfalls to avoid
 

One of the most common problem beginners have with scanf is the need to provide pointers to the variables that ultimately shall hold the parsed values. Since scanf is a function that takes a variable number of arguments, they are not type-checked as usual. Because of this, you can provide non-pointer arguments, pointers to the wrong type, or pointers to strings instead of just strings, and the compiler will not fetch these errors at compile time. If you are lucky, you get a segment violation at run-time; if not, you'll get other behaviour. !!! \% vs. %% !!!

Note Some compilers (notably, gcc) support type-checking for literal format strings by parsing the format string during compile-time and then applying the appropriate type checks.

The following code shows those common errors and the correct code on consecutive lines:


int i;
short h;
char buf[80];
char* str = buf;

/* providing the variable instead of a pointer to it */
sscanf("%d", i);        /* wrong */
sscanf("%d", &i);       /* right */

/* providing a pointer to the wrong type (or a wrong format
   to the right pointer) */
sscanf("%d", &h);       /* wrong */
sscanf("%hd", &h);      /* right */

/* providing a pointer to a string pointer instead of the
   string pointer itself (some people think "once &, always &) */
sscanf("%s", &str);     /* wrong */
sscanf("%s", str);      /* right */

Another common error is not to check the return type of scanf, which you always should do. scanf returns the number of sucessfully scanned fields, so a proper scanf calls looks like this:


int x, y;
if (2 == sscanf(coord_string, "%d,%d", &x, &y)) {
    plot(x, y);
} else {
    perror("bad coordinates");
}

Parsing
 

"Trial and Error" parsing
 


Incremental parsing
 



Using character set formats
 


Conclusion
 


References
 

Brian W. Kernighan, Dennis M. Ritchie, The C Programming Language.
Prentice Hall, 1988, 2nd edition, ISBN 0-13-110362-8.


This article is Copyright © 2000 by Jürgen Hermann and Copyright © 2000 by C-Scene. All Rights Reserved.


[Back to top] Copyright © 1997-2000 by C-Scene. All Rights Reserved.

Part of the graphics and stylesheets used to generate this site are
Copyright © 1999-2000 by Apache Software Foundation.