Node:sscanf, Next:, 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: