Node:sscanf, Next:Formatted input conversion specifiers, Previous:Formatted string input, Up:Formatted string input
sscanf
The sscanf
function accepts a string from which to read input,
then, in a manner similar to printf
and related functions, it
accepts a template string and a series of related arguments. It tries
to match the template string to the string from which it is reading
input, using conversion specifier like those of printf
.
The sscanf
function is just like the deprecated parent
scanf
function, except that the first argument of sscanf
specifies a string from which to read, whereas scanf
can only
read from standard input. Reaching the end of the string is treated as
an end-of-file condition.
Here is an example of sscanf
in action:
sscanf (input_string, "%as %as %as", &str_arg1, &str_arg2, &str_arg3);
If the string sscanf
is scanning overlaps with any of the arguments,
unexpected results will follow, as in the following example. Don't do this!
sscanf (input_string, "%as", &input_string);
Here is a good code example that parses input from the user with
sscanf
. It prompts the user to enter three integers separated by
whitespace, then reads an arbitrarily long line of text from the user
with getline
. It then checks whether exactly three arguments
were assigned by sscanf
. If the line read does not contain the
data requested (for example, if it contains a floating-point number or
any alphabetic characters), the program prints an error message and prompts
the user for three integers again. When the program finally receives
exactly the data it was looking for from the user, it prints out a message
acknowledging the input, and then prints the three integers.
It is this flexibility of input and great ease of recovery from errors
that makes the getline
/sscanf
combination so vastly
superior to scanf
alone. Simply put, you should never use
scanf
where you can use this combination instead.
#include <stdio.h> int main() { int nbytes = 100; char *my_string; int int1, int2, int3; int args_assigned; args_assigned = 0; while (args_assigned != 3) { puts ("Please enter three integers separated by whitespace."); my_string = (char *) malloc (nbytes + 1); getline (&my_string, &nbytes, stdin); args_assigned = sscanf (my_string, "%d %d %d", &int1, &int2, &int3); if (args_assigned != 3) puts ("\nInput invalid!"); } printf ("\nThanks!\n%d\n%d\n%d\n", int1, int2, int3); return 0; }
Template strings for sscanf
and related functions are somewhat
more free-form than those for printf
. For example, most
conversion specifiers ignore any preceding whitespace. Further, you
cannot specify a precision for sscanf
conversion specifiers, as
you can for those of printf
.
Another important difference between sscanf
and printf
is
that the arguments to sscanf
must be pointers; this allows
sscanf
to return values in the variables they point to. If you
forget to pass pointers to sscanf
, you may receive some strange
errors, and it is easy to forget to do so; therefore, this is one of the
first things you should check if code containing a call to sscanf
begins to go awry.
A sscanf
template string can contain any number of any number of
whitespace characters, any number of ordinary, non-whitespace
characters, and any number of conversion specifiers starting with
%
. A whitespace character in the template string matches zero or
more whitespace characters in the input string. Ordinary,
non-whitespace characters must correspond exactly in the template string
and the input stream; otherwise, a matching error occurs. Thus, the
template string " foo "
matches "foo"
and " foo "
,
but not " food "
.
If you create an input conversion specifier with invalid syntax, or if you don't supply enough arguments for all the conversion specifiers in the template string, your code may do unexpected things, so be careful. Extra arguments, however, are simply ignored.
Conversion specifiers start with a percent sign (%
) and terminate
with a character from the following table: