#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无法完成。
有没有办法不限制线条尺寸?
这个问题只是为了我的好奇心,谢谢。
答案 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
初始化为line
,NULL
就会处理所需的分配/重新分配。 getline
还会返回实际读取的字符数,但需要在strlen
之后调用fgets
以确定相同内容。
如果您还有其他问题,请与我们联系。
答案 1 :(得分:0)
考虑两个想法:
分配内存的上限是合理的。任务的性质应该一些最大行长度的想法,无论是80,1024还是1 MB。
使用聪明的操作系统,在需要之前可能不会实际使用已分配的内存。请参阅Why is malloc not "using up" the memory on my computer?
因此,让代码分配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);