[英]dynamic buffer size for reading input
我正在尝试创建一个程序,该程序将从stdin逐行读取,在该行中搜索给定单词的开头和结尾,并输出所有匹配的单词。 这是代码:
int main()
{
char buffer[100];
char **words = NULL;
int word_count = 0;
while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
int length = strlen(buffer);
if (buffer[length - 1] == '\n') {
word_count = count_words(buffer, FIRSTCHAR);
if (word_count > 0) {
words = get_words(buffer, FIRSTCHAR, LASTCHAR);
for (int i = 0; i < word_count; ++i) {
printf("%s\n", words[i]);
free(words[i]);
}
free(words);
}
}
}
return 0;
}
我可以使用基本功能,但是我依赖具有固定缓冲区大小的fgets()。 我想要动态分配一个内存缓冲区,其大小基于每行的长度。
我只能看到一种解决它的方法,该方法是使用fgetc遍历输入并递增一个计数器直到行尾,然后使用该计数器代替sizeof(buffer) ,但是我不知道该怎么做。 fgetc读取正确的相关行。
有解决这个问题的聪明方法吗?
但我依赖具有固定缓冲区大小的
fgets()
。 我想动态分配一个内存缓冲区,其大小基于每行的长度
我确实为另一个SO答案写了一个fgets
版本,该答案读取了整行并返回了包含整行内容的malloc
分配指针。 这是代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *fgets_long(FILE *fp)
{
size_t size = 0, currlen = 0;
char line[1024];
char *ret = NULL, *tmp;
while(fgets(line, sizeof line, fp))
{
int wholeline = 0;
size_t len = strlen(line);
if(line[len - 1] == '\n')
{
line[len-- - 1] = 0;
wholeline = 1;
}
if(currlen + len >= size)
{
// we need more space in the buffer
size += (sizeof line) - (size ? 1 : 0);
tmp = realloc(ret, size);
if(tmp == NULL)
break; // return all we've got so far
ret = tmp;
}
memcpy(ret + currlen, line, len + 1);
currlen += len;
if(wholeline)
break;
}
if(ret)
{
tmp = realloc(ret, currlen + 1);
if(tmp)
ret = tmp;
}
return ret;
}
诀窍是检查是否已读取换行符。 如果已读取,则可以返回缓冲区,否则它将使用sizeof line
重新分配缓冲区更多字节,并将其追加到缓冲区。 您可以根据需要使用此功能。
另一种选择是,如果您使用的是POSIX系统和/或正在使用GNU GCC进行编译,则也可以使用getline
。
void foo(FILE *fp)
{
char *line = NULL;
size_t len = 0;
if(getline(&line, &len, fp) < 0)
{
free(line); // man page says even on failure you should free
fprintf(stderr, "could not read whole line\n");
return;
}
printf("The whole line is: '%s'\n", line);
free(line);
return;
}
函数: getline()
您的需求。 语法:
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
该函数在stdio.h
头文件中公开,通常需要类似以下内容: #define _POSIX_C_SOURCE 200809L
或#define _GNU_SOURCE
作为调用getline()
的文件的第一行
强烈建议您阅读/理解`getline()的MAN页面,以获取所有肮脏的细节。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.