Как я могу получить одно нажатие клавиши на языке программирования D + Tango?

Я прочитал эту статью и пытаюсь сделать упражнение на языке программирования D, но столкнулись с проблемой в первом упражнении.

(1) Отображение серии чисел (1,2,3,4, 5....и т.д.) в бесконечном цикле. Программа должна выйти, если кто-то нажмет определенную клавишу (скажем, клавишу ESCAPE).

Конечно, бесконечный цикл не является большой проблемой, но все остальное. Как я мог получить ключевой удар в D/Tango? В FAQ по танго говорится, что используйте функцию C kbhit() или get(), но, насколько я знаю, их нет в стандартной библиотеке C и нет в glibc, который поставляется с моей машиной Linux, которую я использую для программирования.

Я знаю, что могу использовать стороннюю библиотеку, например ncurses, но у нее такая же проблема, как и у kbhit() или get(), это не стандартная библиотека на C или D и не предустановленная в Windows. Я надеюсь, что смогу выполнить это упражнение, используя только D/Tango, и смогу запустить его как на Linux, так и на Windows.

Как я мог это сделать?


person Brian Hsu    schedule 19.09.2008    source источник


Ответы (5)


Вот как вы это делаете на языке программирования 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
person Walter Bright    schedule 04.11.2008

kbhit действительно не является частью каких-либо стандартных интерфейсов C, но его можно найти в conio.h.

Тем не менее, вы должны иметь возможность использовать getc/getchar из tango.stdc.stdio - я изменил FAQ, который вы упомянули, чтобы отразить это.

person larsivi    schedule 19.09.2008

D обычно имеет все доступные стандартные библиотеки C (Tango или Phobos), поэтому ответы на этот вопрос для GNU C должны работать и в D.

Если у танго нет нужной функции, легко сгенерировать привязки. (Взгляните на CPP, чтобы избавиться от любого макромусора.)

person BCS    schedule 19.09.2008

Спасибо за оба ваших ответа.

К сожалению, моя основная среда разработки — это 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;
}
person Brian Hsu    schedule 19.09.2008

Как указал Ларс, вы можете использовать _kbhit и _getch, определенные в conio.h и реализованные (я полагаю) в msvcrt для Windows. Вот статья с кодом C++ для использования _kbhit и _getch.

person DK.    schedule 01.04.2009