4

我有一个这样的文件:

name1 nickname1
name2 nickname2
name3 nickname3

我希望我的程序读取该文件并显示名称/昵称夫妇。

这是我所做的:

users_file = fopen("users", "r");

  while(!feof(users_file))
  {
    fscanf(users_file, "%s %s", &user.username, &user.name);
    printf("%s | %s\n", user.username, user.nickname);
  }

这是输出:

 name1 | nickname1 
 name2 | nickname2      
 name3 | nickname3 
 name3 | nickname3

为什么最后一个重复?谢谢

4

3 回答 3

3

您需要在feof()之后立即检查fscanf(),或者,检查fscanf()自身的返回值。最后一个是重复的,因为fscanf()没有将任何新数据读入user.username并且user.nickname由于达到了 eof。

可能的修复:

/*
 * You could check that two strings were read by fscanf() but this
 * would not detect the following:
 *
 *    name1 nickname1
 *    name2 nickname2
 *    name3 nickname3
 *    name4
 *    name5
 *
 * The fscanf() would read "name4" and "name5" into
 * 'user.username' and 'user.name' repectively.
 *
 * EOF is, typically, the value -1 so this will stop
 * correctly at end-of-file.
 */
while(2 == fscanf(users_file, "%s %s", &user.username, &user.name))
{
    printf("%s | %s\n", user.username, user.nickname);
}

或者:

/*
 * This would detect EOF correctly and stop at the
 * first line that did not contain two separate strings.
 */
enum { LINESIZE = 1024 };
char line[LINESIZE];
while (fgets(line, LINESIZE, users_file) &&
       2 == sscanf(line, "%s %s", &user.username, &user.name))
{
    printf("%s | %s\n", user.username, user.name);
}
于 2012-03-08T16:10:55.227 回答
1

如果您将循环更改为:

while((fscanf(users_file, "%s %s", &user.username, &user.name))
{
    printf("%s | %s\n", user.username, user.nickname);
}

然后它应该可以工作,注意我们不检查 EOF,我们让 fscanf 为我们检查。

于 2012-03-08T16:12:14.370 回答
0

feof()如果已看到文件结束条件,则该函数返回 true。如果您从文件中读取,情况可能并非如此。

有多种方法可以解决这个问题,可能有用的东西(本质上就是 hmjd 所说的)是:

while (fscanf(users_file, "%s %s", &user.username, &user.name) == 2) {
  ...
}

的返回值fscanf是成功转换和分配的转换完成的次数,因此如果您在读取时收到 EOF,这将与您期望的两次不同。

于 2012-03-08T16:18:12.743 回答