How do I make my program not break when symbol is non-numeric?
while (fscanf(file, "%d", &num) !=isdigit(num)) { has problems.
The return value should be a check against 1.
If the text version of the number is out of int range, using %d is undefined behavior.
It remains unclear where code should continue reading when things fail.
When the return value is 0, no conversion, go back to the file offset where code was plus 1 and then try again.
If we assume any number is in the [INT_MIN ... INT_MAX] range, we could use:
int retval;
long location = 0;
while ((retval = fscanf(file, "%d", &num)) != EOF && location != -1) {
if (retval == 1) {
// Perform your metric on `num`.
if (num < min) {
min = num;
min_count = 0;
}
if (num == min){
min_count += 1;
}
location = ftell(file); // Remember where we are
} else {
// Go back to where we were plus 1.
location++;
if (fseek(file, location, SEEK_SET) < 0) {
break;
}
// This is better than simply consuming a single character as the
// location in the file may not be where is was due to a fail conversion.
// C only specifies being able to back up at least 1 after failure
// and input like "+-1" might back up 1 or 2 places.
}
}
If I was truly going hard core, I think I would instead:
// Read one line at a time.
char buf[BUFSIZ + 1]; // Lines much bigger than this are already a problem for `scanf()`.
while (fgets(buf, sizeof buf, file)) {
char *p = buf;
while (*p) {
char *endptr;
errno = 0;
long long num = strtoll(p, &endptr, /* base */ 10);
if (endptr > p) {
// Success
if (errno) Handle_Overflow()
else {
// Perform metric on `num`.
...
}
p = endptr; // Continue where `strtoll()` stopped.
} else {
p++; Go to next character.
}
}
}
If I was truly going beyond, I think I would instead go for a state machine.
Note, such detail is prone to coding failure.
char sign = '+';
int ch;
while ((ch = fgetc(file)) != EOF) {
if (ch == '-' || ch = '+') {
sign = ch;
continue;
}
if (!isdigit(ch)) {
char sign = '+';
continue;
}
uintmax_t num = ch - '0';
while (isdigit((ch = fgetc(file))) {
// Maybe add code here to detect overflow.
num = num * 10 + ch - '0';
}
// Do metrics on sign,num
...
ungetch(ch, file); // Put back non-numeric digit
}
isdigit(num)does not do what you want it to do: see pubs.opengroup.org/onlinepubs/9699919799/functions/isdigit.html;fscanf()does not return what you expect it to return either: see pubs.opengroup.org/onlinepubs/9699919799/functions/fscanf.html1 2 3x4 5What do you want to handle these cases? Option 1: if you fail to read a number, stop scanning (result1 2 3). Option 2: ignore any non numeric character treating it as a space (in the previous case you expect to read 1,2,3,4,5). Option 3: ignore any non numeric character treating it as nothing (in the previous case you expect to read 1,2,34,5). Someone could come up with other options. What's yours?fscanf(file, "%d", &num)orisdigit(num)?isdigit(49)returns any value!=0, andisdigit(1)returns always0for not-a-digit.