2 番目のケースでは、fscanf は 3 ではなく 2 を返します。したがって、コードを次のように書き直すことができます。
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);
}