【问题标题】:Sscanf reads a line twice?Sscanf 读取一行两次?
【发布时间】:2014-12-01 21:11:54
【问题描述】:

我要做的就是从文本文件中读取数字,对它们做一些事情,然后继续。

文本文件格式如下:

0,0,16
0,3,17
0,4,10
...etc.

这是我打印文本文件的代码:

#include <stdio.h>
#include <stdlib.h>
FILE *fp;    

main()
{
        char line[10];
        int row,column,data;
        fp = fopen("data.txt","rt");
        while(fgets(line, 10, fp) != NULL)
        {
            sscanf(line,"%d,%d,%d\n",&row,&column,&data);
            printf("[Row: %d Column: %d Data %d]\n", row, column, data);
        }
        fclose (fp);
}

每当我运行它时,它会输出每行两次,所以它说

[Row: 0 Column: 0 Data 16]
[Row: 0 Column: 0 Data 16]
...

而不是

[Row: 0 Column: 0 Data 16]
...

我很困惑为什么会这样......

【问题讨论】:

  • 我真的不明白我应该怎么做才能修复这个代码
  • @user2154420:根据您指定的data.txt,我认为此代码没有任何问题。每条记录后面有空行吗?
  • 在使用 sscanf 处理“行”之前检查它的长度,并确保它比您期望的最小值长。您还应该检查扫描的返回值。
  • 啊哈!即使我的文本编辑器将它显示为一行又一行,但在两行之间还有一个额外的换行符,所以我不得不退格每一行。另外,我不明白这是一个重复的问题......这似乎很不同,另一个问题的答案根本没有帮助我

标签: c io text-files scanf csv


【解决方案1】:

接受回答后

意外空行问题的症结只是读取文件输入的一个潜在问题。与其一个一个地解决问题,不如使用更强大的错误处理。

在格式中以良好的节奏使用"%n" 记录扫描的偏移量并提供额外信息来评估行的正确性。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    FILE *fp;    
    char line[10];
    int row,column,data;
    fp = fopen("data.txt","rt");
    while(fgets(line, sizeof line, fp) != NULL)
    {
        int n1, n2;
        int cnt = sscanf(line," %n%d ,%d ,%d %n", 
            &n1, &row, &column, &data, &n2);
        if (n1 > 0 && line[n1] == '\0') 
          Handle_Line_Is_Entirely_Whitespace();
        else if (cnt != 3 || line[n2]) 
          Handle_IncorrectlyFormattedLine();
        else 
          printf("[Row: %d Column: %d Data %d]\n", row, column, data);
    }
    fclose (fp);
    return 0;  
}

更强大的方法是使用strtol() 扫描ints。

【讨论】:

    【解决方案2】:

    如果data.txt 中的每条记录后都有空行,请检查line[0] 是否为'\n'

    检查此代码是否适合您:

    #include <stdio.h>
    #include <stdlib.h>
    FILE *fp;    
    
    int main()
    {
            char line[10];
            int row,column,data;
            fp = fopen("data.txt","rt");
            while(fgets(line, 10, fp) != NULL)
            {
                if(line[0] == '\n')
                    continue;
                sscanf(line,"%d,%d,%d\n",&row,&column,&data);
                printf("[Row: %d Column: %d Data %d]\n", row, column, data);
            }
            fclose (fp);
            return 0;
    }
    

    输入文件data.txt

    0,0,16
    
    0,3,17
    
    0,4,10
    1,2,3
    

    输出

    [Row: 0 Column: 0 Data 16]
    [Row: 0 Column: 3 Data 17]
    [Row: 0 Column: 4 Data 10]
    [Row: 1 Column: 2 Data 3]
    

    【讨论】:

    • 是的!这就是发生的事情!
    • 这假定行上没有隐藏其他字符,如空格等。最好也检查 sscanf() 的返回。
    • @Ian:我完全同意你的看法。正如您在评论中提到的 OP 还可以检查 line 的字符串长度。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2018-01-08
    • 2021-12-05
    • 2021-03-11
    • 2019-05-17
    • 1970-01-01
    相关资源
    最近更新 更多