#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char buffer[10];
char *input = 0;
size_t cur_len = 0;
while (fgets(buffer, sizeof(buffer), stdin) != 0)
{
size_t buf_len = strlen(buffer);
char *extra = realloc(input, buf_len + cur_len + 1);
if (extra == 0)
break;
input = extra;
strcpy(input + cur_len, buffer);
cur_len += buf_len;
}
printf("%s [%d]", input, (int)strlen(input));
free(input);
return 0;
}
这是关于最小更改集,以便您获得完整的输入行。每次增加空间多达9个字节;虽然这不是最好的方法,但使用更好的方式需要额外的记录(分配空间的加倍和记录已分配空间与已使用空间之间的差异)。请注意,cur_len记录了指向input所指向的字符串长度,不包括终止的null字符。此外,请注意使用extra可以避免内存泄漏。
strcpy()操作可以被memmove(input + cur_len, buffer, buf_len + 1)合法地替换(在这种情况下,可以使用memcpy()代替memmove(),但它并不总是有效,而memmove()始终有效,因此使用memmove()更可靠)。
使用长度加倍时,cur_max变量记录分配了多少空间,而cur_len记录了使用了多少空间。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char buffer[10];
char *input = 0;
size_t cur_len = 0;
size_t cur_max = 0;
while (fgets(buffer, sizeof(buffer), stdin) != 0)
{
size_t buf_len = strlen(buffer);
if (cur_len + buf_len + 1 > cur_max)
{
size_t new_len = cur_max * 2 + 1;
if (buf_len + 1 > new_len)
new_len = buf_len + 1;
char *extra = realloc(input, new_len);
if (extra == 0)
break;
input = extra;
cur_max = new_len;
}
strcpy(input + cur_len, buffer);
cur_len += buf_len;
}
printf("%s [%d]", input, (int)strlen(input));
free(input);
return 0;
}
realloc
。考虑每次将分配加倍的策略,以及直接读入缓冲区。顺便说一下:size_t
的printf格式是%zu
。 - Deduplicatorgetline
而不是fgets
。 - 5gon12edermalloc()
中存在一个经典的 off-by-one 错误。使用strlen(str)
函数几乎总是错误的;它几乎总是应该是strlen(str)+1
。此外,你的循环也会严重泄漏内存;在每次迭代中,你都会覆盖存储在input
中的前一个指针。 - Jonathan Leffler