在第二种情况下,fscanf 将返回 2 而不是 3。因此您可以像这样重写代码:
while (1) {
int ret = fscanf(f, "%s %d %d\n", tempName, &tempLoc, &tempNum);
if (ret == EOF) {
break;
}
if (ret == 2) {
tempNum = 1;
} else if (ret != 3) {
// line appear invalid, deal with the error
}
insertFirst (inList, tempName, tempLoc, tempNum);
}
一种更老套的方法是在调用 fscanf 之前将 tempNum 设置为 1,然后像上面那样检查 EOF。但我认为上面的代码更清晰。
编辑:为避免溢出,这会更好。代码会执行得更好,但这更难编写。就像上面一样,我没有为错误条件编写任何代码,但你肯定想处理它们
char lineBuf[255];
while (fgets(lineBuf, sizeof(lineBuf), f) != NULL) {
int spaceIdx, ret;
const int len = strlen(lineBuf);
if (len == (sizeof(lineBuf) - 1) {
// line is too long - either your buf is too small and you should tell the user
// that its input is bad
// I recommend to treat this as an error
}
lineBuf[len - 1] = '\0'; // remove \n
--len; // update len, we've removed one character
if (isspace(*lineBuf)) {
// error, line should not start with a space
}
spaceIdx = strcspn(lineBuf, "\t ");
if (spaceIdx == len) {
// error, no space in this line
}
// Ok, we've found the space. Deal with the rest.
// Note that for this purpose, sscanf is a bit heavy handed (but makes the code
// simpler). You could do it with strtol.
// Also, the first space in the format string is important, so sscanf skips
// all the space at the beginning of the string. If your format requires only
// one space between fields, you can do sscanf(lineBuf + spaceIdx + 1, "%d %d"...
ret = sscanf(lineBuf + spaceIdx, " %d %d", &tempLoc, &tempNum);
if (0 == ret) {
// error, no ints
}
else if (1 == ret) {
tempNum = 1;
}
// at that point, you could copy the first part of lineBuf to tempName, but then
// you have to deal with a potential overflow (and spend time on an useless copy),
// so use lineBuf instead
lineBuf[spaceIdx] = '\0';
insertFirst (inList, lineBuf, tempLoc, tempNum);
}