如何获取D编程语言+ Tango中的单个按键?

时间:2020-03-06 14:24:39  来源:igfitidea点击:

我阅读了本文,并尝试使用D编程语言进行练习,但是在第一个练习中遇到了问题。

(1) Display series of numbers
  (1,2,3,4, 5....etc) in an infinite
  loop. The program should quit if
  someone hits a specific key (Say
  ESCAPE key).

当然,无限循环不是一个大问题,但其余的是。我怎样才能抓住D / Tango的关键点?在探戈常见问题中,它说使用C函数kbhit()或者get(),但是据我所知,它们不在C标准库中,也不存在于我用于编程的Linux机器随附的glibc中。

我知道我可以使用某些第三方库,例如ncurses,但是它也具有与kbhit()或者get()类似的问题,它不是C或者D中的标准库,也没有预安装在Windows上。我希望我可以仅使用D / Tango来完成此练习,并且可以在Linux和Windows机器上运行它。

我该怎么办?

解决方案

D通常具有所有可用的C stdlib(Tango或者Phobos),因此针对GNU C的此问题的答案也应适用于D。

如果探戈没有所需的功能,则生成绑定很容易。 (看看CPP可以消除任何宏垃圾。)

kbhit确实不是任何标准C接口的一部分,但可以在conio.h中找到。

但是,我们应该可以使用tango.stdc.stdio中的getc / getchar。我更改了我们提到的FAQ来反映这一点。

多谢回覆。

不幸的是,我的主要开发环境是Linux + GDC + Tango,所以我没有conio.h,因为我没有使用DMC作为我的C编译器。

而且我还发现在我的开发环境中,getc()和getchar()都是行缓冲的,因此它无法实现我希望做的事情。

最后,我通过使用GNU ncurses库完成了此练习。由于D可以直接与C库接口,因此不需要太多的工作。我只是声明我在程序中使用的函数原型,调用这些函数并将程序直接与ncurses库链接。

它可以在我的Linux机器上完美运行,但是我仍然不知道如果没有任何第三方库就如何做到这一点,并且还可以在Linux和Windows上运行。

import tango.io.Stdout;
import tango.core.Thread;

// Prototype for used ncurses library function.
extern(C)
{
    void * initscr();
    int cbreak ();
    int getch();
    int endwin();
    int noecho();
}

// A keyboard handler to quit the program when user hit ESC key.
void keyboardHandler ()
{
    initscr();
    cbreak();
    noecho();
    while (getch() != 27) {
    }
    endwin();
}

// Main Program
void main ()
{
    Thread handler = new Thread (&keyboardHandler);
    handler.start();

    for (int i = 0; ; i++) {
        Stdout.format ("{}\r\n", i).flush;

        // If keyboardHandler is not ruuning, it means user hits
        // ESC key, so we break the infinite loop.
        if (handler.isRunning == false) {
            break;
        }
    }

    return 0;
}

使用D编程语言的方法如下:

import std.c.stdio;
    import std.c.linux.termios;

    termios  ostate;                 /* saved tty state */
    termios  nstate;                 /* values for editor mode */

    // Open stdin in raw mode
    /* Adjust output channel        */
    tcgetattr(1, &ostate);                       /* save old state */
    tcgetattr(1, &nstate);                       /* get base of new state */
    cfmakeraw(&nstate);
    tcsetattr(1, TCSADRAIN, &nstate);      /* set mode */

   // Read characters in raw mode
    c = fgetc(stdin);

    // Close
    tcsetattr(1, TCSADRAIN, &ostate);       // return to original mode

正如Lars指出的那样,我们可以使用conio.h中定义的_kbhit和_getch并在Windows的(我相信)msvcrt中实现。这是一篇使用C ++代码使用_kbhit和_getch的文章。