Calling scanf("%lf", &something)
will populate something
if and only if the input is a valid floating point number. The string none
is not such a valid number.
The reason you're getting two 3
values is probably because nan
is a valid floating point number, so scanf
finds the n
and says "Hah, this will be a nan
". But then it finds, much to its disappointment, the o
and decides it's no longer valid.
But it has already read the no
from the input stream. It then goes back and does the same thing with the ne
(a).
After that, you start giving it valid numbers again so it carries on.
If you want to be able to handle strings and numbers, you're going to have to use the least restrictive (string) and then decide. Something like this (though scanf("%s")
is dangerous for real code, it's probably okay for classwork):
The following code does that and (as you should) checks the return value from scanf/sscanf
to ensure it was correctly scanned:
#include <stdio.h>
#include <string.h>
int main() {
static char bigstring[1000];
double sc[5];
for (int i = 0; i < 5; i++) {
sc[i] = 3;
if (scanf("%s", bigstring) != 1) {
puts("*** Could not get input");
return 1;
}
if (strcmp("none", bigstring) == 0) {
puts("Got 'none', converting to -999");
sc[i] = -999;
} else if (sscanf(bigstring, "%lf", &sc[i]) != 1) {
printf("*** Could not convert input '%s' to float", bigstring);
return 1;
} else {
printf("Got %f\n", sc[i]);
}
}
puts("\nThe five entered numbers were:");
for (int i = 0; i < 5; i++) {
printf(" %lf\n", sc[i]);
}
}
Running that works properly with basic test data:
pax:~$ printf "34\nnone\n56\n89\n111\n" | ./qq
Got 34.000000
Got 'none', converting to -999
Got 56.000000
Got 89.000000
Got 111.000000
The five entered numbers were:
34.000000
-999.000000
56.000000
89.000000
111.000000
(a) Interestingly, it appears this only happens with real user input, not piping data through the program as per my printf
statement.
The ideal behaviour, in my opinion, would be to leave the input stream pointing at the invalid data. In other words, unless the exact text is valid (like nan
), the pointer should not move at all. However, there's a footnote in the C standard that allows for this behaviour if, for example, the input stream is not seekable:
fscanf
pushes back at most one input character onto the input stream.
So, while it may be able to back up further than that on a pipeline, that may not be the case when dealing with terminal input.
When I enter x
as input, it appears it does push that back, because every single following array element is populated with 3
, meaning it's reading that x
continuously. Anything starting with an n
seems to consume that and the following character only.