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


#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 无法完成。

有没有办法不限制行大小?

这个问题只是出于我的好奇心,谢谢。

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

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 中存在的任何数据。另请注意,每次realloc 时,maxl通常会翻倍。但是,您可以自由选择您喜欢的任何尺寸增加方案。(如果您担心将所有分配的新内存清零,则可以使用 memset 将新分配的空间初始化为零/空。在某些情况下很有用,您希望确保您的line始终null-terminated

这就是基本的动态分配/重新分配方案。请注意,您正在阅读直到阅读完整行,因此您需要重组循环测试。最后,由于您分配了内存,因此您有责任在完成内存后释放内存。您离不开的工具是valgrind(或类似的内存检查器(来确认您没有泄漏内存。

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

提示2 查看 POSIX getline . getline将处理所需的分配/重新分配,只要line初始化为 NULLgetline还返回实际读取的字符数,省去了需要在fgets后调用strlen以确定相同的字符数。

如果您有其他问题,请告诉我。

考虑2个想法:

  1. 分配内存的上限是合理的。 任务的性质应该对最大行长度有所了解,无论是 80、1024 还是 1 MB。

  2. 使用
  3. 智能操作系统,分配的内存的实际使用可能不会发生,直到需要时才发生。 请参阅为什么 malloc 没有"耗尽"我计算机上的内存?

因此,让

代码分配 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);

相关内容

  • 没有找到相关文章