【问题标题】:Why does fscanf only read the first word of one string from file为什么 fscanf 只从文件中读取一个字符串的第一个单词
【发布时间】:2019-12-22 04:50:56
【问题描述】:

当我尝试使用fscanf() 读取我的结构的文件信息时遇到问题。它只是读取字符串的第一行,循环永远不会结束。我该如何解决这个问题?

结构

typedef struct {
    int id;
    char name[80];
    char nameStadium[80];
    int numberPlacesStadium;
    float funds;
    float monthlyExpenses;
    int active;
} Team;

我用这段代码来阅读

void showAll(void)
{
    FILE* file;
    Team team;

    file = fopen("file.txt", "rt");

    if (file == NULL)
    {
        printf("!!!Cant open file!!!\n");
        return;
    }

    rewind(file);

    printf("\n\n=== TEAMS ======\n");
    printf("%s\t%s\n", "ID", "NAME");

    while (fscanf(file, "%6d %s %s %6d %f %f %03d\n", &team.id, team.name, team.nameStadium, &team.numberPlacesStadium, &team.funds, &team.monthlyExpenses, &team.active) != EOF)
    {
        if (team.active != 0)
        {
            printf("%d\t%s\n", team.id, team.name);
        }
    }

    fclose(file);

}

我不明白为什么fscanf() 只得到第一个单词而不是完整的字符串

有人知道怎么解决吗?

【问题讨论】:

  • 1) 不与EOF 比较,与预期成功比较while (fscanf(file, "%6d %s %s %6d %f %f %03d\n", ....) == 7) 2) 发布样本 file.txt。更好的是minimal reproducible example 3) %03d 是有问题的。试试%3d。 4) 名称/体育场是否包含空格?
  • 您的问题标题指出“fscanf 只读取第一个单词”,但后来在文本中说“它只读取第一行”,那么 fscanf 在第一个单词或第一行之后停止工作了吗?如果它在尝试将team.name 读取为字符串 (%s) 时在第一个单词之后停止,那么这篇文章 (stackoverflow.com/questions/1247989/…) 可能会有所帮助。无论如何,正如@chux - Reinstate Monica 已经评论的那样,示例输入很有帮助。
  • char *path="file.txt"; if( (file = fopen(path, "r")) == NULL ) { perror(path); ...} 。错误消息很重要。他们应该告诉你失败的原因并被写入正确的流中。
  • %s 扫描格式在第一个空格处停止,而在打印格式中,它会打印整个字符串——空格、换行符等等。因此,您可以使用与生成数据相同的格式打印无法回读的数据。你怎么知道哪些词属于体育场名称?您能否使用扫描集(例如%79[^0-9])将输入控制到第一位数字(假设体育场名称不包含数字,这可能不安全)。人们使用分隔符(除了空格)是有原因的——这就是一个例子。

标签: c file scanf


【解决方案1】:

我刚刚使用我按照您发布的格式制作的示例文本文件测试了您的代码。除了您没有正确关闭文件之外,所有内容都已读入并且似乎很好。它应该是这样的。

fclose(file);

如果您希望您的代码能够读取带有空格的字符串,最好的办法是使用分隔符系统。下面的代码读取它们的类型(假设整数之间没有空格),读取 不是 逗号的 80 个字符序列(将是名称),以及然后继续以逗号分隔的其他数字。

  while (fscanf(file, "%d, %80[^,], %80[^,], %d, %f, %f, %d\n", &team.id, 
     team.name, team.nameStadium, &team.numberPlacesStadium, &team.funds, 
    &team.monthlyExpenses, &team.active) != EOF) 
  {
      if (team.active != 0)
    {
        printf("%d\t%s %s\n", team.id, team.name, team.nameStadium);
    }
  }

我已经对其进行了测试,它确实可以工作,但请记住,这也不是最优雅的解决方案。

这些是我的文本文件中的行的样子:

 133222, Bears, Bears Stadium, 444333, 23, 35.3, 52
 666222, Eagles, Eagles Stadium, 322222, 13, 56.3, 54

【讨论】:

  • 你的字符串有多个单词吗??关于 fclose 错误是帖子中的错字,问题可能与我使用 Visual Studio IDE 的事实有关吗?
  • 是的,但是你的字符串没有空格,它们有一个特殊字符,如果你有空格它就不能正常工作
  • 我的意思是,从技术上讲,你可以,但是在扫描时看起来很草率并且难以跟踪。为了方便和稳定,大多数带有文本文件的文件 I/O 都使用某种分隔符来完成,并且该分隔符通常是逗号。这是 Access 和 Excel 等数据库的标准。
猜你喜欢
  • 2016-01-18
  • 2022-11-30
  • 2015-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多