#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
初始化为 NULL
。 getline
还返回实际读取的字符数,省去了需要在fgets
后调用strlen
以确定相同的字符数。
如果您有其他问题,请告诉我。
考虑2个想法:
-
分配内存的上限是合理的。 任务的性质应该对最大行长度有所了解,无论是 80、1024 还是 1 MB。
使用 智能操作系统,分配的内存的实际使用可能不会发生,直到需要时才发生。 请参阅为什么 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);