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.
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: