清除缓冲区标准输入

时间:2015-09-09 15:33:25

标签: c

Hello Stackoverflow社区,我对此代码有疑问:

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

#define MAX_SIZE 50


int main()
{
    char *s = malloc(sizeof(char)*MAX_SIZE);
    do{
        int r = read(STDIN_FILENO, s, MAX_SIZE);
        if(r==-1) printf("error");
        else{
            write(STDERR_FILENO, s, MAX_SIZE);
        }
        while(getchar()!='\n');
    } while(strcmp(s,"end\n")!=0);
    free(s);
    return 0;
}

问题在于它产生了错误的输出,stdin在'do while'的每次迭代中都不会产生“干净”。我知道在Windows上我必须使用fflush(stdin)但在互联网上观看我看到这个功能不适用于Linux。我使用linux,并且总是在互联网上观看我看到许多人说解决方案是while(getchar()!='\n);而不是fflush(stdin),但问题没有得到解决......你能解释一下为什么吗?

1 个答案:

答案 0 :(得分:1)

我看到的问题:

  1. 您将错误的参数传递给write。而不是

    write(STDERR_FILENO, s, MAX_SIZE); 
    

    应该是

    write(STDERR_FILENO, s, r); // Write the number of characters that were read
                                // not MAX_SIZE
    
  2. 没有仔细考虑跳到行尾的策略。你有:

    int r = read(STDIN_FILENO, s, MAX_SIZE);
    if(r==-1) printf("error");
    else{
        write(STDERR_FILENO, s, MAX_SIZE);
    }
    while(getchar()!='\n');
    

    首先,read在遇到换行符时不会停止阅读。它最多可读取MAX_SIZE个字符。它会在这个过程中吞噬尽可能多的换行符。您需要做的是改为使用fgets()

    char* cp = fgets(s, MAX_SIZE, stdin);
    if ( cp == NULL )
    {
       // If fgets fails, you probably reached the end of the file.
       break;
    }
    
    fprintf(stderr, "%s", s);
    
  3. 该行

    while(strcmp(s,"end\n")!=0);
    
    如果使用read从文件中读取数据,

    将导致未定义的行为,因为read不会自动将终止空字符添加到s。使用fgets可以避免这个问题。

  4. 此外,由于您在编译时知道数组的大小,因此可以使用:

    char s[MAX_SIZE];
    

    而不是使用malloc在运行时分配内存。