使用fgets从c中的stdin读取未知长度行

lob*_*3rd 3 c

我试图使用C语言从stdin读取未知长度行.

我在网上看到了这个:

char** str;
gets(&str);
Run Code Online (Sandbox Code Playgroud)

但它似乎给我带来了一些问题,我真的不明白如何以这种方式做到这一点.

你能解释一下为什么这个例子工作/不工作以及实现它的正确方法(用malloc吗?)

Dav*_*eri 6

你不希望指针指向char,使用chars 数组

char str[128];
Run Code Online (Sandbox Code Playgroud)

或指向 char

char *str;
Run Code Online (Sandbox Code Playgroud)

如果选择指针,则需要使用保留空间 malloc

str = malloc(128);
Run Code Online (Sandbox Code Playgroud)

然后你可以使用 fgets

fgets(str, 128, stdin);
Run Code Online (Sandbox Code Playgroud)

并删除trailling换行符

char *ptr = strchr(str, '\n');
if (ptr != NULL) *ptr = '\0';
Run Code Online (Sandbox Code Playgroud)

要读取任意长行,可以使用getline(添加到libc的GNU版本的函数):

#define _GNU_SOURCE
#include <stdio.h>

char *foo(FILE * f)
{
    int n = 0, result;
    char *buf;

    result = getline(&buf, &n, f);
    if (result < 0) return NULL;
    return buf;
}
Run Code Online (Sandbox Code Playgroud)

或使用fgets和您自己的实现realloc:

char *getline(FILE * f)
{
    size_t size = 0;
    size_t len  = 0;
    size_t last = 0;
    char *buf = NULL;

    do {
        size += BUFSIZ; /* BUFSIZ is defined as "the optimal read size for this platform" */
        buf = realloc(buf, size); /* realloc(NULL,n) is the same as malloc(n) */            
        /* Actually do the read. Note that fgets puts a terminal '\0' on the
           end of the string, so we make sure we overwrite this */
        if (buf == NULL) return NULL;
        fgets(buf + last, size, f);
        len = strlen(buf);
        last = len - 1;
    } while (!feof(f) && buf[last] != '\n');
    return buf;
}
Run Code Online (Sandbox Code Playgroud)

用它来称呼它

char *str = getline(stdin);

if (str == NULL) {
    perror("getline");
    exit(EXIT_FAILURE);
}
...
free(str);
Run Code Online (Sandbox Code Playgroud)

更多信息

  • @Alter Mann - realloc()可能会失败.您的代码现在能够处理任意长度,但假设realloc()始终成功.除了那个小狡辩,现在好多了. (2认同)
  • 我相信“fgets(buf + last, size, f);” 应该是“fgets(buf + last, BUFSIZ, f);” 否则“realloc”可能会失败。 (2认同)