如何使用fgets读取未知长度的输入

时间:2014-12-06 00:27:57

标签: c string input string-length

我应该如何使用fgets()阅读长输入,我不太明白。

我写了这个

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char buffer[10];
    char *input;
    while (fgets(buffer,10,stdin)){
        input = malloc(strlen(buffer)*sizeof(char));
        strcpy(input,buffer);
    }
    printf("%s [%d]",input, (int)strlen(input));
    free(input);
    return 0;
}

2 个答案:

答案 0 :(得分:5)

#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;
}

答案 1 :(得分:3)

更好的方法是使用为您分配的输入机制,例如getline(或甚至scanf)。 (注意: scanf未在所有编译器中分配。它在gcc/Linux中进行,但不在Windows/Codeblocks/gcc中进行。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char *input;
    scanf ("%m[^\n]%*c", &input);
    printf("\n %s [%d]\n\n",input, (int)strlen(input));
    free(input);
    return 0;
}

<强>输出:

$ ./bin/scanfinput
This is my longer string.

 This is my longer string. [25]

getline示例

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char *input = NULL;     /* input buffer, NULL forces getline to allocate */
    size_t n = 0;           /* maximum characters to read (0 - no limit      */
    ssize_t nchr = 0;       /* number of characters actually read            */

    if ((nchr = getline (&input, &n, stdin)) != -1)
        input[--nchr] = 0;  /* strip newline */

    printf ("\n %s [%zd]\n\n", input, nchr);
    free(input);

    return 0;
}