我正在尝试创建一个程序,它将从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(缓冲区),但我不知道如何让fgetc读取正确的相关行。
有没有聪明的方法来解决这个问题?
答案 0 :(得分:2)
但我依赖
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;
}
答案 1 :(得分:0)
功能:getline()
可以满足您的需求。语法:
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
该函数在stdio.h
头文件中公开,通常需要:#define _POSIX_C_SOURCE 200809L
或#define _GNU_SOURCE
作为调用getline()
的文件中的第一行
强烈建议阅读/理解MAN页面的“getline()”以获取所有肮脏的细节。