如何通过stdin停止输入溢出

问题描述

我的程序应该通过stdin接受输入,并将字符串存储到大小为SIZE的数组中。

当我输入7个或更多值时,会出现我的问题;当程序循环运行时,超出缓冲区大小的值仍会被使用,同时用标准输入中剩余的内容buf不断填充(至少,我认为它是这样工作的)。

#define SIZE 8

char *readLine(char *buf,size_t size) {
    printf("$ ");
    fgets(buf,size,stdin);
    return buf;
}

int main() {
    char *buf = malloc(SIZE * sizeof(char));
    
    for (;;) {
        readLine(buf,SIZE);
        printf("> %s",buf);
    }   
}

我得到的输出分别测试了6、7和8的输入大小:

$ abcdef
> abcdef
$ abcdefg
> abcdefg$ > 
$ abcdefgh
> abcdefg$ > h

我不了解的事情:

  • 为什么第7个值会使程序的输出看起来很奇怪?我以为第7个字符加上空字符会正常工作?
  • 为什么buf所填充的值超出了SIZE的大小(在这种情况下为8)?

由此,我可以进行简单的更改/添加来实现自己想要的功能吗?

解决方法

为什么第7个值会使程序的输出看起来很奇怪?我以为第7个字符加上空字符可以正常工作?

fgets不会读取过多的输入(超出了您提供的缓冲区大小,但为空字节排除了一个字节空间)。因此,字符h留在输入流中,然后在下一次调用fgets时被占用-读取为h和换行符\n。读取换行符后,fgets终止读取其他输入。

为什么buf会填充超出SIZE大小(在这种情况下为8)的值?

不是。如前所述,剩余的输入将被读取,因此它具有这种外观。

由此,我可以进行简单的更改/添加来实现自己想要的功能吗?

您可以检查fgets读取的缓冲区是否具有换行符char;如果没有,请读取并忽略输入流中的剩余字节。

您可以这样做:

void discard(const char *buf)
{
    if(strchr(buf,'\n') == NULL) {
        /* No newline found,so read & discard everything.
        while(getchar() != '\n');
    }
}

char *readLine(char *buf,size_t size) {
    printf("$ ");
    if (fgets(buf,size,stdin) != NULL) {
        discard(buf);
    }
    return buf;
}