Yogi_Bear_79 wrote:
But there _is_ an integer - 7. there's then stuff after the integer.
It needs to fail if there are any characters other than integers or white
space
and what's "|| n_ptr <=0" supposed to do?
Not needed, removed, same results
sscanf isn't the best tool for the job for a couple of reasons, not the
least of which is that trying to convert a number of too large a
magnitude results in undefined behavior.
The following program will read a line at a time from stdin and attempt
to convert it to an integer using the strtol function. If the line
contains any invalid characters, an error message is displayed and the
offending character is pointed out. If a range error occurs (the
number was too large/small to store in a long int), an appropriate
message is diaplayed. This version uses 'long int' and accepts
negative numbers, remove the minus sign from the string of allowed
characters if you just want to accept positive numbers. The code is a
little verbose since it implements error checking.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#define BUF_MAX 80
int main (void) {
char buf[BUF_MAX];
long l;
size_t s;
while(fgets(buf, BUF_MAX, stdin) != NULL) {
if ((s = strspn(buf, "-0123456789 \t\n")) == strlen(buf)) {
errno = 0;
l = strtol(buf, NULL, 10);
if (errno == ERANGE) {
printf("number out of range!\n");
} else {
printf("number read was %ld\n", l);
}
} else {
while(s--)
putchar(' ');
putchar('^');
printf(" invalid character\n");
}
}
return 0;
}
The strspn function returns the number of characters in the input
string that are in the "allow" string, this must be the same as the
length of the string itself if all the characters are valid, otherwise
we print an error message displaying the location of the offending
character and continue.
The strtol function will skip leading whitespace and attempt to convert
the numeric part of the string to a long int. If an underflow or
overflow occurs then strtol returns LONG_MIN or LONG_MAX respectively
and sets errno to ERANGE. We just check errno and print an error if
appropriate, you could compare l to LONG_MIN or LONG_MAX to determine
the type of range error if desired.
If everything goes well, the converted number is displayed.
A couple of notes:
If the input consists of multiple numbers seperated by whitespace, only
the first one will be converted, you didn't specify what should happen
in this case.
If the input contains only of whitespace or the minus sign the
converted value will be 0.
Entering more than BUF_MAX characters at a time may cause unintended
(but not undefined) behavior.
If an invalid input line contains a tab character before the invalid
character, the error message may not correctly point to the invalid
character.
Addressing these caveats is left as an exercise to the reader.
Robert Gamble