【问题标题】:Reading integers from txt file in C从C中的txt文件中读取整数
【发布时间】:2017-08-23 11:48:22
【问题描述】:

我正在制作一个文件阅读器,它可以从文件中逐行读取整数。问题是它不起作用。我认为我以错误的方式使用 fscanf 。有人可以帮我吗?

我已经在其他问题中寻找答案,但我找不到任何解释我的代码为什么不起作用的东西。

int read_from_txt(){
    FILE *file;
    file = fopen("random_numbers.txt", "r");
    //Counting line numbers to allocate exact memory
    int i;
    unsigned int lines = 0;
    unsigned int *num;
    char ch;
    while(!feof(file)){
        ch = fgetc(file);
        if (ch == '\n'){
            lines++;
        }
    }
    //array size will be lines+1
    num = malloc(sizeof(int)*(lines+1));
    //storing random_numbers in num vector
    for(i=0;i<=lines;i++){
        fscanf(file, "%d", &num[i]);
        printf("%d", num[i]);
    }
    fclose(file);
}

txt文件是这样的:

12 
15
32
68
46
...

但是这段代码的输出一直给出“0000000000000000000...”

【问题讨论】:

  • fgetc 循环之后,文件指针位于文件末尾。您需要rewind 再次阅读该文件。
  • @Lashane file 以文本模式打开。对应于编译器对文本文件的 C 库理解的文本文件会将\n\r\n\r 转换为'\n'if (ch == '\n') 就足够了。如果需要处理其他文本文件,则会出现许多其他问题,超出了本文的范围。
  • 提示:任何时候代码没有按预期运行并且代码正在执行 I/O,添加代码以检查 I/O 函数的返回值,例如 fscanf(file, "%d", &amp;num[i]);,这会显示一个问题 - 这个节省您的时间。
  • while(!feof(file))is always wrongfgetc返回 int 而不是 char

标签: c file


【解决方案1】:

您忘记“倒回”文件:

fseek(file, 0, SEEK_SET);

您的读取过程会遍历文件两次 - 一次用于计算行数,另一次用于读取数据。在第二遍之前,您需要回到文件的开头。

请注意,您可以通过使用realloc 在单遍中执行此操作:将循环中的数字读取到临时int 中,并且对于每次成功读取,通过调用@ 将num 数组扩展一个987654325@。这将根据需要扩展缓冲区,您无需倒带。

在重新分配给num之前,请仔细检查realloc的结果,以避免内存泄漏。

【讨论】:

    【解决方案2】:

    您可以尝试使用标准 IO 中的 getline 函数,并仅使用一个循环将解析后的数字添加到数组中。请参阅下面的代码。请查看https://linux.die.net/man/3/getline

    此外,您可以使用atoistrtoul 函数将读取的行转换为整数。随时查看https://linux.die.net/man/3/atoihttps://linux.die.net/man/3/strtoul

    下面的代码评估一个包含数字列表的文件并将这些数字添加到一个 C 整数指针

    #include <stdlib.h>
    #include <stdio.h>
    
    int main(int argc, char ** argv) {
        FILE * file;
    
        file = fopen("./file.txt", "r");
    
        size_t read;
        char * line = NULL;
        size_t line_len = 0;
    
        size_t buffer_size = 10;
        int * buffer = (int *)malloc(sizeof(int) * buffer_size);
    
        int seek = 0;
        while((read = getline(&line, &line_len, file)) != -1) {
            buffer[seek++] = atoi(line);
    
            if (seek % 10 == 0) {
                buffer_size += 10;
                buffer = (int *)realloc(buffer, sizeof(int) * buffer_size);
            }
        }
    
        for (int i = 0; i < seek; i++) {
            printf("%d\n", buffer[i]);
        }
    
        free(buffer);
        fclose(file);
    }
    

    如果您不确定应该使用哪种转换函数。您可以在What is the difference between sscanf or atoi to convert a string to an integer? 上查看atoisscanf 之间的区别

    【讨论】:

    • 请注意,atoi 提供了绝对 no 错误检查,任何依赖于 buffer[X] 的后续代码都包含该范围内的 unsigned0 - INT_MAX 无法验证 buffer[X] 是否包含有效值。 (最好使用strtoul 进行错误检查)。接下来,将realloc 的返回值分配给指针本身(而不是tmp 指针)可能会因丢失对原始内存块的引用而造成内存泄漏。 (更好void *tmp = realloc(buffer, sizeof *buffer * buffer_size); if (tmp) buffer = tmp;。(也不需要投射)
    • @DavidC.Rankin 是对的,您可以使用sscanfstrtoul 检查转换的完整性。此外,您应该检查指针完整性以避免可能的泄漏或内存问题。谢谢大卫 C。
    猜你喜欢
    • 1970-01-01
    • 2020-10-09
    • 1970-01-01
    • 2018-07-22
    • 1970-01-01
    • 1970-01-01
    • 2014-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多