首页 > 解决方案 > 如何测试我自己的 kbhit() 替代方案的源代码?

问题描述

我遇到了这段代码,它应该new_kbhit()为 DOS 函数创建一个替代 POSIX 函数 () kbhit()

// Standard C  headers
#include <stdio.h>
#include <stdbool.h>

// POSIX system headers
#include <sys/select.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <stropts.h>

/////////////////////////////////////////////////////////////
// FUNCTION:    kbhit_new()
//
// It returns 0. But if a key is pressed it returns number
// of pending bytes.
/////////////////////////////////////////////////////////////
int new_kbhit() {

    // Stdin's file descriptor (fd) is always 0, stdout's is 1 and stderr's is 2.
    static const int stdin_fd = 0;

    // This is static because we only want to disable buffering when this function is 1st called.
    static bool initialized = false;

    // Define the terminal structure named term.
    struct termios term;

    // Define an integer that will store the number of pending bytes.
    int bytes_waiting;

    if (! initialized) {
        // Get parameter STDIN of the terminal and store it inside termios structure (term).
        tcgetattr(stdin_fd, &term);
        // A: Remove termios structure's (term) flag ICANON inside the local modes i.e. c_lflag.
        // B: Removing flag ICANON will dissable canonnical processing.
        // C: When there is no canonical processing
        term.c_lflag &= ~ICANON;
        // Set terminal's attributes immediately (TCSANOW). Attributes are applied from termios (term).
        tcsetattr(stdin_fd, TCSANOW, &term);
        // Assign a buffer NULL to stream stdin. This disables buffering on stdin so pressed key is shown.
        setbuf(stdin, NULL);
        initialized = true;
    }

    // A:  ioctl operates on the "streams devices" but it needs it's file descriptors (fd)..
    // B:  Linux is not 100% POSIX compliant. It supports more than POSIX defines.
    // C:  Linux supports "streams device" FIONREAD (https://www.kernel.org/doc/html/latest/)
    // C:  FIONREAD device stores an integer i.e. "pending number of bytes" in last argument of ioctl.
    ioctl(stdin_fd, FIONREAD, &bytes_waiting);
    return bytes_waiting;
}

/////////////////////////////////////////////////////////////
// EXAMPLE:
/////////////////////////////////////////////////////////////
#include <unistd.h>

int main(int argc, char** argv) {

    printf("Press any key to terminate:\n");

    while (! new_kbhit()) {
        putchar('.');
        fflush(stdout);
        usleep(1000000);
    }

    printf("\nDone.\n");

    return 0;
}

使用 POSIX 标准,我以某种方式破译了这段代码的作用(评论)。但对我来说,如果我注释掉函数内的几乎所有内容,它的作用完全一样new_kbdhit(),看起来像这样:

int new_kbhit() {
    int bytes_waiting;
    ioctl(stdin_fd, FIONREAD, &bytes_waiting);
    return bytes_waiting;
}

所以我无法确认这段代码有什么作用。我如何测试它以了解它的真正潜力?我很难理解它的价值。

标签: cposix

解决方案


推荐阅读