清除缓冲区未按预期工作?

Clearing the buffer not working as expected?

提问人:yad0 提问时间:1/13/2023 最后编辑:yad0 更新时间:1/13/2023 访问量:66

问:

我有以下代码。

           int x1, x2;
           char check[3];
           do{
                //input should be (x1,x2)
                successfully_inputed = scanf("(%d,%d%2s", &x1, &x2, check);
                if(successfully_inputed == EOF)
                        break;
                if(check[1] || successfully_inputed != 3 || check[0] != ')'){
                        fprintf(stderr, "Invalid line");
                        
                        char ch;
                        while((ch = getchar()) != EOF && ch != '\n');

                        continue;
                }
                getchar(); // remove the new line character from buffer
          }while(1);

它确实适用于我给出的每个输入,而不是一个特定的输入。当我给出任何东西,然后后面跟着 ,例如“asdEOF”,然后它消耗“asd”,当它到达时,它要求我输入,不是 而是 .为什么会发生这种情况,我该如何解决?EOFEOFscanf()getchar()

c scanf 缓冲区 eof getchar

评论

3赞 dbush 1/13/2023
getchar返回一个 .int
0赞 yad0 1/13/2023
更改为并不能解决@dbushchint
0赞 pmacfarlane 1/13/2023
这看起来像某种伪代码。你能给我们一些可以自己编译和运行的真实代码吗?
0赞 yad0 1/13/2023
编辑了它。如果你想要更多的代码,我可以提供更多,我只是想保持它干净和简单。@pmacfarlane
0赞 pmacfarlane 1/13/2023
类似的问题在这里。您可能应该在您的 .(一旦我编译了您的代码,这为我解决了您的问题。if (feof(stdin)) break;scanf()

答:

1赞 Allan Wind 1/13/2023 #1

当输入为“asd<ctr-d>”时失败,因此您需要交换条件的顺序,以便您先检查它:scanf()

        if(successfully_inputed != 3 || check[1] || check[0] != ')'){

无论哪种情况,我们都会正确地获得“无效行”。然后我们尝试刷新输入流(确保 ch 为 int):

int ch;
while((ch = getchar()) != EOF && ch != '\n');

这导致 getchar() 读取 'a' 和 's' 和 'd' 然后挂起等待输入。这是因为,在 Linux 上,ctrl-d 只会导致终端缓冲区被刷新,并且您需要在空流上使用第二个 ctrl-d 来关闭它。然后,这将触发 getchar() 返回的 EOF。

即使您切换到读取输入,它也不会返回,直到您在非空输入缓冲区上按两次 ctrl-d :fgets()

#include <stdio.h>
#define LINE_LEN 100
#define CHECK_LEN 3

int main() {
    for(;;) {
        char line[LINE_LEN];
        if(!fgets(line, LINE_LEN, stdin)) {
            if(feof(stdin)) break;
            // handle error
            return 1;
        }
        int x1;
        int x2;
        char check[CHECK_LEN];
        int rv = sscanf(line, "(%d,%d%2s", &x1, &x2, check);
        if(rv != 3 || check[1] || check[0] != ')') {
            fprintf(stderr, "\nInvalid line\n");
        }
    }
}

和示例会话:

$ ./a.out
asd<ctrl-d><ctrl-d>
Invalid line
$
$ ./a.out
<ctrl-d>
$