Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.6k views
in Technique[技术] by (71.8m points)

c - How to test the source code for my own kbhit() alternative?

I came across this code which was supposed to create an alternative POSIX function (new_kbhit()) for a DOS function 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:
");

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

    printf("
Done.
");

    return 0;
}

Using POSIX standard I somehow deciphered what this code does (comments). But to me it does exactly the same if I comment out almost everything inside the function new_kbdhit() which then looks like this:

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

So I can't confirm that this code does anything at all. How could I test it to see it's true potential? I have hard time understanding it's value at all.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...