Reputation: 3416
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?
Upvotes: 6
Views: 1016
Reputation: 753940
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.
Upvotes: 3
Reputation: 16290
This is easy. No fancy C++ required! Just do:
char unusedChar;
if (sscanf(sInput, "%d%c", &iAssignmentMarks[0], &unusedChar) == 1)
Upvotes: 2
Reputation: 21878
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.
Upvotes: 2
Reputation: 4457
If you can use c++ specific capabilities, there are more clear ways to test input strings using streams.
Check here: http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.2
If you're wondering, yes this did come from another stack overflow post. Which answers this question: Other answer
Upvotes: 0
Reputation: 123468
scanf
isn't that smart. You'll have to read the input as text and use strtol
to convert it. One of the arguments to strtol
is a char *
that will point to the first character that isn't converted; if that character isn't whitespace or 0, then the input string wasn't a valid integer:
char input[SIZE]; // where SIZE is large enough for the expected values plus
// a sign, newline character, and 0 terminator
...
if (fgets(input, sizeof input, stdin))
{
char *chk;
long val = strtol(input, &chk, 10);
if (*chk == NULL || !isspace(*chk) && *chk != 0)
{
// input wasn't an integer string
}
}
Upvotes: 0