如何在无需用户输入的情况下刷新标准输入?

时间:2019-01-21 23:53:21

标签: c stdin flush

我正在尝试模拟命令行外壳。用户输入他们想输入的shell命令,例如/bin/pwd,并且代码旨在执行它。

将缓冲区设置为读取固定数量的字符(例如,假设20个字符)。

如果用户输入的字符超过20个,则需要清除多余的字符,然后Shell才再次循环。

我一直在尝试这样做:

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

但是问题是getChar()要求您先输入一个字符。

是否有一种不需要用户输入任何内容的刷新标准输入的方法?

while (1) {

    // Prompt user for input
    ssize_t readIn = read(STDIN_FILENO, buffer, BUF_SIZE + 1);
    if (readIn < 0) {
        perror("read() failed");
        return 2;
    } 

    // Null-terminate and remove line return
    buffer[readIn - 1] = '\0'; 

    char program[strlen(buffer)];
    strcpy(program, buffer);
    printf("program is: %s\n", program);

    // Flush stdin
    int garbageCollector; 
    while ((garbageCollector = getchar()) != '\n' && garbageCollector != EOF);

    // Create child process
    child = fork();
    if (child < 0) {
        perror("fork() failed");
        return 3;
    }

    // Start alarm that is triggered after timeout exceeded
    // which then kills child process
    signal(SIGALRM, killChild);
    alarm(timeout); 

    if (child == 0) { // Child
        char* av[] = { program, NULL };
        execve(program, av, NULL);  

    } else {  // Parent
        wait(NULL);
        alarm(0);  // Reset alarm if program executed
    }

    memset(buffer, 0, BUF_SIZE); // Flush buffer
}

2 个答案:

答案 0 :(得分:2)

如果非POSIX可移植性不是问题(请注意,这不适用于Windows-但我看到您使用的fork()也不适用于Windows),则可以暂时将文件描述符设为重新尝试刷新非阻塞并从中读取所有输入:

<script type='text/javascript'>  
 //<![CDATA[  
 $(document).ready(function() {  
  $('img').each(function(){  
   var $img = $(this);  
   var filename = $img.attr('src')  
   $img.attr('title', filename.substring((filename.lastIndexOf('/'))+1, filename.lastIndexOf('.')));  
   $img.attr('alt', filename.substring((filename.lastIndexOf('/'))+1, filename.lastIndexOf('.')));  
  });  
 });  
 //]]>  
 </script>

然后您将呼叫int flush_in(FILE *file) { int ch; int flags; int fd; fd = fileno(file); flags = fcntl(fd, F_GETFL, 0); if (flags < 0) { return -1; } if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { return -1; } do { ch = fgetc(file); } while (ch != EOF); clearerr(file); if (fcntl(fd, F_SETFL, flags)) { return -1; } return 0; }

答案 1 :(得分:1)

有人在相关问题中提出了这样的建议:

fseek(stdin,0,SEEK_END);

似乎可以在Mac和Windows上运行,但不能在Linux上运行。对于Linux,Daniel的建议有效:

fflush(stdin);

因此,您可以在编译时解决此问题,并根据要编译的操作系统使用fflushfseek

#ifdef defined(_WIN32) || defined(__APPLE__)
  #define flush_stdin(stdin) fseek(stdin,0,SEEK_END)
#elif defined(__linux__) || defined(__unix__)
  #define flush_stdin(stdin) fflush(stdin)
#else
  #define flush_stdin(...) UNIMPLEMENTED