Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ignoring integers that are next to characters using sscanf()

Tags:

c

Sorry for the simple question, but I'm trying to find an elegant way to avoid my program seeing input like "14asdf" and accepting it just as 14.

if (sscanf(sInput, "%d", &iAssignmentMarks[0]) != 0)

Is there an easy way to prevent sscanf from pulling integers out of mangled strings like that?

like image 552
ARW Avatar asked Jan 12 '12 21:01

ARW


People also ask

What is the function of sscanf ()?

Description. The sscanf() function reads data from buffer into the locations that are given by argument-list. Each argument must be a pointer to a variable with a type that corresponds to a type specifier in the format-string.

Does sscanf ignore whitespace?

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.

How do I ignore a character in scanf?

Explanation: The %*s in scanf is used to ignore some input as required. In this case, it ignores the input until the next space or newline. Similarly, if you write %*d it will ignore integers until the next space or newline.

What happens if sscanf fails?

sscanf() Return valueIf a matching failure occurs before the first receiving argument was assigned, returns zero. If input failure occurs before the first receiving argument was assigned, EOF is returned.


2 Answers

You can't directly stop sscanf() from doing what it is designed and specified to do. However, you can use a little-known and seldom-used feature of sscanf() to make it easy to find out that there was a problem:

int i;

if (sscanf(sInput, "%d%n", &iAssignmentMarks[0], &i) != 1)
    ...failed to recognize an integer...
else if (!isspace(sInput[i]) && sInput[i] != '\0')
    ...character after integer was not a space character (including newline) or EOS...

The %n directive reports on the number of characters consumed up to that point, and does not count as a conversion (so there is only one conversion in that format). The %n is standard in sscanf() since C89.

For extracting a single integer, you could also use strtol() - carefully (detecting error conditions with it is surprisingly hard, but it is better than sscanf() which won't report or detect overflows). However, this technique can be used multiple times in a single format, which is often more convenient.

like image 140
Jonathan Leffler Avatar answered Sep 28 '22 13:09

Jonathan Leffler


You want to read integers from strings. It is easier to do this with strtol instead of sscanf. strtol will return, indirectly via endptr, the address just after the last character that was succesfully read into the number. If, and only if, the string was a number, then endptr will point to the end of your number string, i.e. *endptr == \0.

char *endptr = NULL;
long n = strtol(sInput, &endptr, 10);
bool isNumber = endptr!=NULL && *endptr==0 && errno==0;

(Initial whitespace is ignored. See a strtol man page for details.

like image 45
Serge Wautier Avatar answered Sep 28 '22 11:09

Serge Wautier