繁体   English   中英

用于读取输入的动态缓冲区大小

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM