从C中的文件中读取一行,动态地

时间:2015-04-07 20:14:31

标签: c file-io dynamic malloc

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

int main()
{
    FILE *input_f;

    input_f = fopen("Input.txt", "r"); //Opens the file in read mode.
    if (input_f != NULL)
    {
        char line[2048];

        while( fgets(line, sizeof line, input_f) != NULL )
        {
            //do something
        }
        fclose(input_f); //Close the input file.
    }
    else
    {
        perror("File couldn't opened"); //Will print that file couldn't opened and why.
    }
    return 0;
}

您好。我知道我可以用C中的这段代码逐行阅读,但我不想限制行大小,比如2048这段代码。

我考虑过使用malloc,但在我阅读之前我不知道该行的大小,所以IMO无法完成。

有没有办法不限制线条尺寸?

这个问题只是为了我的好奇心,谢谢。

2 个答案:

答案 0 :(得分:1)

当您动态分配内存时,您需要更改:

char line[2048];

#define MAXL 2048           /* the use of a define will become apparent when you  */
size_t maxl = MAXL;         /* need to check to determine if a realloc is needed  */
char *line = malloc (maxl * sizeof *line);
if (!line)                  /* always check to insure allocation succeeded */
    ...error.. memory allocation failed

您阅读了最新的{maxl -1)字符或newline(如果使用fgetc等)或阅读该行,然后检查line [strlen (line) - 1] == '\n'是否确定您是否阅读整行(如果使用fgets)。 (POSIX要求所有行以newline终止)如果您阅读maxl个字符(fgetc)或未读取换行符(fgets),那么它就是简短阅读,还有更多字符。您的选择是realloc(通常是大小加倍)并再试一次。重新分配:

char *tmp = realloc (line, 2 * maxl)
if (tmp) {
    line = tmp;
    maxl *= 2;
}

注意:从不使用原始指针重新分配(例如line = realloc (line, 2 * maxl),因为如果realloc失败,则释放内存并将指针设置为NULL并且您将丢失line中存在的所有数据。另请注意maxl每次realloc时通常会加倍。但是,您可以自由选择您喜欢的任何大小增加方案。(如果您关注归零所有分配的新内存,你可以使用memset将新分配的空间初始化为零/ null。在你想要保证line总是null-terminated)的某些情况下有用

这是基本的动态分配/重新分配方案。请注意,在阅读完整行之前,您正在阅读,因此您需要重新构建循环测试。最后,由于您分配了内存,因此您负责在完成内存后释放内存。一个你不能没有的工具是valgrind(或类似的内存检查器)来确认你没有泄漏内存。

提示如果您正在阅读并希望确保您的字符串始终为null-terminated,那么在分配您的内存块后,所有字符为零(0)。如前所述,memset可用,但如果您选择calloc而不是malloc,则会将内存归零。但是,在realloc上,新空间不会为零,因此无论最初分配该块的函数是什么,都需要调用memset

提示2 查看POSIX getline。只要getline初始化为lineNULL就会处理所需的分配/重新分配。 getline还会返回实际读取的字符数,但需要在strlen之后调用fgets以确定相同内容。

如果您还有其他问题,请与我们联系。

答案 1 :(得分:0)

考虑两个想法:

  1. 分配内存的上限是合理的。任务的性质应该一些最大行长度的想法,无论是80,1024还是1 MB。

  2. 使用聪明的操作系统,在需要之前可能不会实际使用已分配的内存。请参阅Why is malloc not "using up" the memory on my computer?

  3. 因此,让代码分配1个大缓冲区来限制病态情况,让底层内存管理(重新)根据需要分配实内存。

    #define N (1000000)
    char *buf = malloc(N);
    ...
    while (fgets(buf, N, stdin) != NULL)) {
      size_t len = strlen(buf);
      if (len == N-1) {
        perror("Excessive Long Line");
        exit(EXIT_FAILURE);
      }
    }
    free(buf);