C: fgets 用于逐行读取文件 -> 提供更少的内存?

标签 c

我尝试用 C 语言逐行读取文件(但由于某些原因,我希望这些行在末尾连接成一个字符串!)。

int max_line_length, finish_length, current_length;
max_line_length = finish_length = 50000;
current_length = 0;
line = malloc(sizeof(char) * max_line_length);
finished_line = malloc(sizeof(char) * finish_length);

while (fgets(line, max_line_length, file) != NULL) {

  if (line[strlen(line)-1] == '\n') {
    int len = strlen(line);
    char new_part[len];
    strncpy(new_part, line, len - 1);
    new_part[len - 1] = '\0';

    if ((current_length + (len - 1)) > finish_length) {
      while ((current_length + (len - 1)) > finish_length) finish_length*=2;
      finish_line = realloc(sizeof(char)*finish_length);
    }
    current_length+= strlen(new_part);
    strncat(finish_line, new_part, strlen(new_part));
    line[0] = '\0';
  } else {
    max_line_length *= 2;
    line = realloc(sizeof(char) * max_line_length);
  }
}

所以我检查是否读取了换行符,如果没有,这应该意味着行中没有足够的内存,所以我重新分配它,然后它会再次读取,对吧?

我不明白我想念什么,但 valgrind 提示如下:

4,096 bytes in 1 blocks are definitely lost in loss record 111 of 114  
at 0x47F1: malloc (vg_replace_malloc.c:302)  
==901==    by 0x180915: fgets (in /usr/lib/system/libsystem_c.dylib) 

在我调用 fgets 的那一行!

但是我在方法结束时释放了 line 和 finish_line 。有人看到我在这里想念什么吗???

最佳答案

查看 realloc 的定义:

void *realloc(void *ptr, size_t size);

就您而言,您在调用 realloc 时没有提供任何 ptr 参数。对我来说,这甚至无法编译:

error: too few arguments to function ‘realloc’

Realloc 返回指向新分配的内存的指针。您应该将旧指针传递给 realloc 并使其返回新指针,例如:

char* new_finished_line = NULL;
new_finished_line = realloc(finished_line, sizeof(char)*finish_length);
/* if realloc was successful, it already freed finished_line pointer
 * and it returned to new_finished_line */
if (new_finished_line != NULL) {
    finished_line = new_finished_line;
}
/* if new_finished_line is NULL, then finished line is still allocated */
else {
    free(finished_line);
    printf("realloc error\n");
    exit(1);
}

但是,经过一些语法修复后,我的机器上的您的版本并没有造成内存泄漏。也许考虑重新设计你的算法?您可以尝试使用下面的代码,其中逐字符读取文件,如果读取换行符,则将空格写入缓冲区。有许多不同的方法可以实现这一目标。

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

char* read_my_file(char* name) {
    char* store;
    char* new_store = NULL;
    int SIZE = 10;
    int x;
    int i = 0;
    store = malloc(SIZE);
    FILE* fp = fopen(name, "r");
    while (( x = fgetc(fp) ) != EOF) {
        if (x == '\n') {
            store[i] = ' ';
        }
        else {
            store[i] = x;
        }
        if (i > SIZE - 2) {
            SIZE *= 2;
            new_store = realloc(store, SIZE);
            if (new_store != NULL) {
                store = new_store;
            }
            else {
                fprintf(stderr, "realloc error");
                free(store);
                exit(1);
            }
        }
        i++;
    }
    store[i] = '\0';
    fclose(fp);
    return store;
}

int main(void)
{
    char* container = read_my_file("YOUR_FILE_TO_READ.txt");
    printf("%s\n",container);
    free(container);
    return 0;
}

我的算法可能不是最好的算法,我只是想表明有很多方法可以做到这一点。

关于C: fgets 用于逐行读取文件 -> 提供更少的内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25449655/

相关文章:

c - 添加或删除顺序最后的方法会导致 C 程序无用

c - 小写<-->大写函数未按计划运行

c - 如何 "multithread"C代码

c++ - 嵌套循环 OpenMP 并行化、私有(private)索引还是公共(public)索引?

c - 在 TCP 服务器套接字上用 C 接收数据

c - 结构C中 ":"是什么意思

c - 如何将管道与一个 execve 结合起来

c - 为什么忽略 SIGCONT 仍会使进程继续?

c - 字符串比较有问题吗? C

c - C 结构体中的反向输出顺序