从stdin读取任意大小的字符串?

时间:2012-03-17 14:53:31

标签: c

我想从控制台读取一个字符串。

然而,使用scanf或fgets,在我看来,只能读取固定最大大小的字符串。更糟糕的是,似乎无法检查在用户输入太多的情况下输入了多少字符(在这种情况下,我可以简单地重新分配数组以使字符串适合数组)。

我读到我应该在this question的答案中一次读取一个字符,但是我不知道如何在每个字符之后没有用户按Enter键的情况下一次读取一个字符

我该怎么做?

5 个答案:

答案 0 :(得分:4)

GCC文档says

  

标准C具有执行此操作的功能,但它们不是非常安全:空字符甚至(对于gets)长行可能会混淆它们。因此GNU库提供了非标准getline函数,可以轻松可靠地读取行。

那个

  

[getline]是一个GNU扩展,但它是从流中读取行的推荐方法。替代标准功能不可靠。

因此,如果你正在使用GCC,我会说你应该使用getline。如果您不使用GCC,您应该看看您的编译器是否提供了类似的功能。如果没有 - 或者你真的更喜欢使用标准的东西 - 那么你需要一次读一个字符。

  

我不知道如何在不让用户在每个角色后按Enter键的情况下一次阅读一个角色。

是的,你这样做。用户输入一系列字符,然后按Enter键。您的第一个fgetc来电将会阻止,直到用户按下Enter键,但之后,后续的fgetc来电将立即返回,直到您阅读换行符为止。 (然后它将再次阻止,直到用户再次按Enter键。)读取“一次一个字符”并不意味着您必须在用户键入下一个字符之前读取每个字符;它只是意味着,一旦用户输入一行,你就可以一次读取该行一行。

答案 1 :(得分:1)

char c = NULL;
while (c != 0x0D)
{
    scanf("%c", &c);
    // do stuffs with c
}

答案 2 :(得分:1)

尝试运行此.. ..

#include <stdio.h>

int main(){
    char next;
    while((next=getchar())!=EOF)
        printf("%c\n",next);

}

然后查看getchar()的手册页,看看手边有什么。

答案 3 :(得分:1)

如果最后一个字符不是fgets()

,您可以在循环中使用\n并重新分配
/* UNTESTED: MAY HAVE OFF-BY-ONE ERRORS */
char *buffer;
size_t bufsiz = 100;
size_t buflen = 100;
size_t bufcur = 0;
buffer = malloc(bufsiz);
for (;;) {
    fgets(buffer + bufcur, bufsiz, stdin);
    buflen = bufcur + strlen(buffer + bufcur);
    if (buffer[buflen - 1] == '\n') break;
    tmp = realloc(buffer, bufsiz * 2);
    if (tmp == NULL) /* deal with error */;
    buffer = tmp;
    bufcur = buflen - 1;
    bufsiz *= 2;
}
/* use buffer (and bufsiz and buflen) */
free(buffer);

答案 4 :(得分:1)

接受的答案应该注意getchar()返回一个int。 char数据类型不足以容纳EOF。

我们可以读取预定数量的文本,然后丢弃其余的输入。这种做法不仅仅是其批评者的一部分(我们怎么敢设想知道要丢弃什么)。另一种选择是使用getline或编写自定义函数。我以为我会尝试后者。

这不会阻止用户使用cat large_file填充内存。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#define MAX 50
#define JUSTDO(a) if (!(a)) {perror(#a);exit(1);}
/** char *get_line  FILE *f
 * reads an arbitrarily long line of text or until EOF
 * caller must free the pointer returned after use
 */
char *get_line (FILE *f) {
    int len=MAX;
    char buf[MAX],*e=NULL,*ret;JUSTDO (ret=calloc(MAX,1));
    while (fgets (buf,MAX,f)) {
        if (len-strlen(ret)<MAX) JUSTDO (ret=realloc(ret,len*=2));
        strcat (ret,buf) ;if ((e=strrchr (ret,'\n'))) break;
    } if (e) *e='\0';
    return ret;
}
/* main */
int main (void) {
    char *s;
    printf ("enter a line of text:\n");
    printf ("line was '%s'\n",s=get_line(stdin)) ;free (s);
    return 0;
}