【问题标题】:reading primitives from file in C从 C 文件中读取原语
【发布时间】:2011-03-12 12:29:24
【问题描述】:

我是 C 新手,想从文件中读取一些数据。

其实我发现很多阅读函数,fgetc,fgets等。 但我不知道哪种/组合最适合读取以下格式的文件:

0 1500 100.50
1 200     9
2 150     10

我只需要将上面的每一行保存到一个包含三个数据成员的结构中。

我只需要知道这样做的最佳实践,因此我是 C 编程新手。

谢谢。

【问题讨论】:

    标签: c file-io stream iostream


    【解决方案1】:

    尝试使用fgets 读取每一行。对于每一行,您可以使用sscanf

    FILE* f = fopen("filename.txt", "r");
    if (f) { 
        char linebuff[1024];
        char* line = fgets(linebuff, 1024, f);
        while (line != NULL) {
            int first, second;
            float third;
            if (sscanf(line, "%d %d %g", &first, &second, &third) == 3) {
                // do something with them.. 
            } else {
                // handle the case where it was not matched.
            }
            line = fgets(linebuff, 1024, f);
        }
        fclose(f);
    }
    

    这可能有错误,但它只是为了给你一个例子来说明你如何使用这些函数。请务必验证 sscanf 返回的内容。

    【讨论】:

    • 那么,为什么不直接使用 fscanf 呢?
    • @Mohammed:因为 fscanf 中的数字格式(如 %g)会跳过包括换行符在内的空格。这将阻止您检查文件是否每行包含三个值。
    • 我也打算建议使用fscanf,但我更喜欢这个建议。
    • 它可以,但是当我将float替换为double时,它在最后一列返回了垃圾数据,你知道为什么吗?
    • 您可能需要提供格式 %lf(小写 L f)而不是 %g。你用的是什么格式化程序?
    【解决方案2】:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    static void
    read_file(const char *fname)
    {
        FILE *f;
        char line[1024];
        int lineno, int1, int2, nbytes;
        double dbl;
    
    
        if ((f = fopen(fname, "r")) == NULL) {
            perror("fopen");
            exit(EXIT_FAILURE);
        }
    
        for (lineno = 1; fgets(line, sizeof line, f) != NULL; lineno++) {
    
            int fields = sscanf(line, " %d %d %lg %n", &int1, &int2, &dbl, &nbytes);
            if (fields != 3 || (size_t) nbytes != strlen(line)) {
                fprintf(stderr, "E: %s:%d: badly formatted data\n", fname, lineno);
                exit(EXIT_FAILURE);
            }
    
            /* do something with the numbers */
            fprintf(stdout, "number one is %d, number two is %d, number three is %f\n", int1, int2, dbl);
        }
    
        if (fclose(f) == EOF) {
            perror("fclose");
            exit(EXIT_FAILURE);
        }
    }
    
    int main(void)
    {
            read_file("filename.txt");
            return 0;
    }
    

    关于代码的一些注释:

    • fscanf 函数很难使用。我不得不试验一段时间,直到我做对了。 %d%lg 之间的空格字符是必需的,以便跳过数字之间的任何空格。这在行尾尤其重要,必须读取换行符。
    • 大部分代码都与彻底检查错误有关。几乎每个函数调用的返回值都会检查它是否成功。此外,还会将已读取的字段数和字符数与预期值进行比较。
    • fscanffprintf 的格式字符串在细微的细节上有所不同。请务必阅读他们的文档。
    • 我使用fgets 一次读取一行和sscanf 的组合来解析字段。我这样做是因为我似乎无法使用 fscanf 匹配单个 \n
    • 我使用带有标准警告标志-Wall -Wextra 的GNU C 编译器。这有助于避免一些简单的错误。

    更新:我忘记检查fgets 的每次调用是否准确读取一行。可能有行太长而无法放入缓冲区。应检查该行是否始终以 \n 结尾。

    【讨论】:

      猜你喜欢
      • 2011-08-10
      • 2011-12-08
      • 1970-01-01
      • 2013-07-16
      • 1970-01-01
      • 2014-04-02
      • 2012-05-15
      • 2016-06-18
      • 2016-08-02
      相关资源
      最近更新 更多