首页 > 解决方案 > 如何在不需要用户输入的情况下刷新标准输入?

问题描述

我正在尝试模拟命令行外壳。用户输入他们想要输入的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
}

标签: cstdinflush

解决方案


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

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;
}

然后你会打电话给flush_in(stdin).


推荐阅读