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

#include  #include  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 ),则它是一个简短的读取,并且剩余更多字符。 您的选择是重新分配(通常将大小加倍)并再试一次。 重新分配:

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

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

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

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

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

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

考虑两个想法:

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

  2. 使用智能操作系统,在需要之前可能不会实际使用已分配的内存。 请参阅为什么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);