On using sscanf
Previously, we have a short tutorial on scanf. To continue with the usage of commonly used api’s, I am going to elaborate on sscanf today.
Imagine you are in a scenario where you have a c string (character array) containing several different values i.e. an integer, a float and a smaller string and you want to extract each of those values into separate variables, then the function that comes to rescue is sscanf.
The large string here is “sen” containing a number 88, followed by a c string “string” and a float 3.27. We extract all three of these values into three respective variables num, substring, and fl.
char sen = "88 string 3.27"; char substring; int num; float fl; sscanf(sen, "%d %s %f", &num, substring, &fl); printf("%d %s %f\n", num, substring, fl);
This would print “88 string 3.270000” on the screen.
There are certain important points to understand about the above usage.
- Each data type in the “sen” is by default separated by a space. If there is a space i.e. “string” is replaced with “another string”, then only “another” is taken as first string and format specifier would expect “string” to be accepted in place of %f
- Note that you cannot substitute a double for a float implicitly since that would corrupt the value of double. Hence use a %f with a variable of type float. If one is interested in using doubles, then corresponding format specifier is needed i.e. %lf with value being extracted into a double variable.
- Similar to the principle of scanf, in the sscanf call, both ‘num’ and ‘fl’ are prepended with a & operator while extracting input, where as “substring” already being the name of array returns the address of first element. Hence it is not prefixed with a & operator.
If the intention is to skip a string in the middle then it needs to be specified in the format string.
char sen = "88 string skips 3.27"; sscanf(sen, "%d %s skips %f", &num, substring, &fl);
The resultant variables will be filled with the same values as earlier i.e. the string “skips” would be skipped as written in the sscanf call. So basically any part of the original string that one wishes to ignore can be mentioned in the format string of sscanf.
However, it is important to note that the ‘skipped’ part exactly matches i.e. changing the sscanf call to contain even ‘skip’ (note missing s in the end) or ‘skipss’, it will corrupt the results.
But there is a better way to skip a string in the middle without precisely specifying it.
Why does the above code prints ‘this – 30’ ?
The %*s tells that the format specifier expects a string here, but the * says to ignore it rather than expecting a corresponding field to copy it to. The function returns 2 for two values being successfully read.
Another important aspect is return type. sscanf() returns the number of elements successfully copied. So testing return value would always tell you as many items are correctly parsed. This is demonstrated by example.
int retval = sscanf(sen, "%d %s skips %f", &num, substring, &fl); printf("Return value is: %d --- and fields are - %d %s %f\n", retval, num, substring, fl);
Return value is: 3 --- and fields are - 88 string 3.270000
int retval = sscanf(sen, "%d %s skipsssss %f", &num, substring, &fl); printf("Rreturn value is: %d --- and fields are - %d %s %f\n", retval, num, substring, fl);
Return value is: 2 --- and fields are - 88 string -107374176.000000
The last example above means that two fields i.e. 88 and ‘string’ were successfully filled and others are not. The last negative value is just garbage printed in one instance on my machine. The return value could be as bad as 0 in case of a matching failure. As a rule when this value is less than the number of ‘%‘ in format string and equivalent parameters, you know there was a parsing error.
If you want to limit the number of characters read in say a specific string that can be done as follows:
char sen = "limitedonestring"; char substring; sscanf(sen, "%9s", substring); printf("Extracted string is: %s\n", substring);
This would print “Extracted string is: limitedon”. Note that length of substring is restricted to 9, by specifying it between % and s. This prevents buffer overflows.
Probably one more thing worth mentioning is that 'space' usually is a type separator, but sscanf can work even without it provided a type with a known size or valid characters is used. For example,
int n; char ar; sscanf("3487str", "%d%s", &n, ar); printf("%d %s\n", n, ar);
would print '3487 str' having extracted the integer n and c string ar correctly
Edited by Roger, 19 February 2013 - 02:33 PM.