简体   繁体   English

从C中的文件读取基元

[英]reading primitives from file in C

I am new to C, and want to read some data from a file. 我是C语言的新手,想从文件中读取一些数据。

Actually, I find many reading functions, fgetc, fgets, etc.. But I don't know which one/combination is the best to read a file with the following format: 实际上,我发现了许多读取功能,例如fgetc,fgets等。但是我不知道哪种格式最适合读取以下格式的文件:

0 1500 100.50
1 200     9
2 150     10

I just need to save each row above into a struct with three data members. 我只需要将上面的每一行保存到具有三个数据成员的结构中。

I just need to know the best practice to do that, hence I am new to C programming. 我只需要知道执行此操作的最佳实践,因此对于C编程我还是陌生的。

Thanks. 谢谢。

Try reading each line using fgets . 尝试使用fgets阅读每一行。 With each line, you can then use sscanf . 每行都可以使用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);
}

This may have errors, but it's just meant to give you an example of how you might use the functions. 这可能会有错误,但这只是为了给您一个示例,说明如何使用这些函数。 Be sure to validate what sscanf returns you. 确保验证sscanf返回了什么。

#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;
}

Some notes on the code: 有关代码的一些说明:

  • The fscanf function is quite difficult to use. fscanf函数很难使用。 I had to experiment a while until I got it right. 我不得不尝试一段时间,直到正确为止。 The space characters between the %d and %lg are necessary so that any white-space between the numbers is skipped. 必须使用%d%lg之间的空格字符,以便跳过数字之间的任何空格。 This is especially important at the end of the line, where the newline character must be read. 这在必须读取换行符的行尾特别重要。
  • Most of the code is concerned with checking errors thoroughly. 大多数代码都与彻底检查错误有关。 Almost every return value of a function call is checked whether it succeeded or not. 检查函数调用的几乎每个返回值是否成功。 In addition, the number of fields and the number of characters that have been read are compared to the expected values. 另外,将字段数和已读取的字符数与期望值进行比较。
  • The format strings for fscanf and fprintf differ in subtle details. fscanffprintf的格式字符串在细节上有所不同。 Be sure to read the documentation for them. 请务必阅读它们的文档。
  • I used the combination of fgets to read one line at a time and sscanf to parse the fields. 我使用fgets的组合一次读取一行,并使用sscanf解析字段。 I did this because it seemed impossible to me to match a single \\n using fscanf . 我这样做是因为使用fscanf匹配单个\\n似乎是不可能的。
  • I used the GNU C Compiler with the standard warning flags -Wall -Wextra . 我将GNU C编译器与标准警告标志-Wall -Wextra This helped to avoid some easy mistakes. 这有助于避免一些简单的错误。

Update: I forgot to check that each invocation of fgets reads exactly one line. 更新:我忘了检查一下fgets每次调用是否都准确地读取了一行。 There might be lines that are too long to fit into the buffer. 可能有些行太长而无法放入缓冲区。 One should check that the line always ends with \\n . 应该检查该行始终以\\n结尾。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM