I am using a for loop with fscanf to input 5 columns from a file into an array of structs.Each struct has 5 variables: 1 string and 4 ints, the first fscanf reads a string name and stores it as part of a struct the other 4 input integers into said struct(all to different variables of the struct). With normal input it works fine. but when a character is input into one of the integer columns the scanf puts 0 for that and the rest of the values of that struct and uses char as if it was a new struct i.e it skips everything after it and uses the unwanted char as name with the remaining values of the row as its input. My question is if there is a way to ignore the unwanted struct generated by that input or a way of simply preventing that the char is recognised and that particular scanf is just skiped? I have tried using fgets instead of scan but it did not work, Also i cannot use the 0 to sort out the unwanted values becuase 0 could be input as a normal value. I understand ideally having a look at the code would be of help but i prefer not to post it for plaigirism reasons as this is for uni and i dont crave those plaigirism meetings. Thanks in advance and sorry if the question is not well explained. :)
问题:
回答1:
You need to check the return value of fscanf()
to ensure that it succeeded, if it fails it does not modify parameters beyond the specifier that failed
char name[100];
int value1;
int value2;
int value3;
int value4;
if (fscanf(file, "%99s%d%d%d%d", name, &value1, &value2, &value3, &value4) == 5)
success();
else
failure();
Of course, it's up to you what success()
and failure()
will actually do, but that way you prevent undefined behavior.
回答2:
The key is " input 5 columns" which implies a line of text. Using fscanf()
is challenging to synchronize with a line, especially if you want to interpret the text in alternate ways. Best to handle reading and parsing separately.
char buf[100];
while (fgets(buf, sizeof buf, istream)) {
char s[sizeof buf];
s[0] = 0;
int i[4] = { 0,0,0,0 }; // default values
// c is the count of scanned variables
int c = sscanf(buf, "%s%d%d%d%d", s, &i[0], &i[1], &i[2], &i[3]);
printf("%d: %s %d %d %d %d\n", c, s, i[0], i[1], i[2], i[3]);
}
" but when a character is input into one of the integer columns the scanf puts 0 for that " is likely false. What you are seeing is the previous value.
回答3:
The short answer is, fscanf
is the wrong tool for this job.
I'm guessing this is the sort of file you want to read:
abc 1 2 3 4
def 5 6 7 8
ghi 9 10 11 12
So even if you had perfect code for reading this data using fscanf
, because of the way fscanf
works, your code would also perfectly happily read this garbagey-looking file, creating the same three records:
abc 1 2 3 4 def
5 6 7 8 ghi 9
10 11 12
The much better way to read formatted lines of text is to read them a line at a time using fgets
, and then break each line up into its fields.
Me, I always use a function called getargs
which breaks a line up into whitespace-separated "words" in an argc
and argv
, just like main()
receives. Unfortunately getargs
is not standard. But there's a version described in these class notes that you could use.
You can use the standard library function strtok
to do more or less the same thing. (Unfortunately I can't show you how to do it, because I never use strtok
.)
Finally, you can use sscanf
, as chux already suggested. You said you'd tried this and it "didn't work", but if you give us some more details, we might be able to help you get it working.