Получение необработанного ввода из консоли с использованием C или C ++ - PullRequest
3 голосов
/ 14 июля 2011
/* Initialize new terminal i/o settings */
static struct termios old, new1;
void initTermios(int echo) {
    tcgetattr(0, &old); /* grab old terminal i/o settings */
    new1 = old; /* make new settings same as old settings */
    new1.c_lflag &= ~ICANON; /* disable buffered i/o */
    new1.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */
    tcsetattr(0, TCSANOW, &new1); /* use these new terminal i/o settings now */
}

/* Restore old terminal i/o settings */
void resetTermios(void) {
    tcsetattr(0, TCSANOW, &old);
}

Как я могу получить клавишу со стрелкой в ​​качестве ввода (возможно, в виде одного символа), текущий код работает хорошо для всех других вещей, которые мне нужны ... Пожалуйста, нет решения с ncurses

Ответы [ 4 ]

5 голосов
/ 14 июля 2011

Вы не можете сделать это в стандартном C ++ / C, вам нужен нестандартный файл conio.h и расширение getch (). Затем вы можете дважды вызвать getch (), чтобы получить код клавиши для стрелок

#include <conio.h>
using namespace std;

int main() 
{
    cout << "press up arrow;" << endl;
    int control = getch(); //gets the escape character
    int keycode = getch(); //gets the code
    cout << control << endl; 
    cout << keycode << endl;
}
3 голосов
/ 14 июля 2011

Вы пробовали функцию read?

Это работает для меня с Cygwin G ++, у меня нет linux, удобного для тестирования:

#include <unistd.h>
#include <termios.h>
#include <stdio.h>

/* Initialize new terminal i/o settings */
static struct termios old, new1;
void initTermios(int echo) {
    tcgetattr(0, &old); /* grab old terminal i/o settings */
    new1 = old; /* make new settings same as old settings */
    new1.c_lflag &= ~ICANON; /* disable buffered i/o */
    new1.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */
    tcsetattr(0, TCSANOW, &new1); /* use these new terminal i/o settings now */
}

/* Restore old terminal i/o settings */
void resetTermios(void) {
    tcsetattr(0, TCSANOW, &old);
}

int main(void)
{
    char c;
    initTermios(0);
    while (1) { read(0, &c, 1); printf("%d\n", c); }
}

Как заметил @Fiktik, настройка эха не работает, но я использую код в вопросе без изменений.

1 голос
/ 26 июня 2018

Существует большое руководство по написанию текстовых редакторов для терминалов Unix с необработанным вводом, окраской синтаксиса и т. Д., В котором используются только стандартная библиотека C и стандартные заголовки, доступные в Unix-подобных системах:

https://viewsourcecode.org/snaptoken/kilo/02.enteringRawMode.html

В этой главе руководства объясняется, как переключить вход терминала в необработанный режим и обработать его стандартными функциями ввода-вывода из C (read() и прочее). Затем вы можете обрабатывать такие вещи, как перемещение курсора, прокрутка, цвета и т. Д., Записывая в выход определенные последовательности переключения терминала VT100. Вы можете найти больше в этом руководстве, включая ссылки на все необходимые документы и примеры исходных кодов. Есть также репозиторий GitHub со всеми образцами из учебника, а также конечный продукт, основанный на Kilo editor , написанном antirez .

Что касается чтения специальных клавиш, таких как клавиши со стрелками, Home, End, PgUp, PgDown и т. Д., Попробуйте вывести необработанные символы, которые вы получаете от ввода, и просто нажмите клавиши, которые вы хотите увидеть, на какие коды они отображаются. Например, для клавиш со стрелками они обычно отображаются на escape-последовательности <ESC>[A - <ESC>[D, где <ESC> - это специальный управляющий символ с ASCII-кодом 27 десятичный или 0x1B шестнадцатеричный. Это коды выхода терминала VT100, которые инструктируют терминал перемещать курсор на один символ в одном из этих четырех направлений. Подробнее об обработке этих нажатий клавиш в следующей главе вышеупомянутого руководства:

https://viewsourcecode.org/snaptoken/kilo/03.rawInputAndOutput.html

1 голос
/ 14 июля 2011

В качестве одного символа это невозможно (ввод представляет собой последовательность символов).То, что вы можете сделать, это сделать его похожим на один символ, реализовав собственную функцию ввода.Что-то вроде:

struct key_data {
   enum key_type kt; /* ARROW, FUNCTION, REGULAR, etc */
   unsigned char key; /* depends on kt */
};

int get_key_press (struct key_data * kd) {
   int c = getc(stdin);
   switch (c) {
      /*
        If c is a control character, process further characters to see what needs to happen
       */
   }
   return 0;
}

/* later, in main */
   struct key_data kd;
   get_key_press (&kd);
   if (kd.kt == ARROW_KEY) {
      switch (kd.key) {
         case ARROW_RIGHT: 
            printf("Right Arrow Pressed\n");
            break;
         /* and so on */

Итак, после реализации вы можете использовать get_key_press, чтобы действовать так, как будто вы получаете один символ.

Хотя эта работа уже сделана для вас в другом месте;почему отвращение к ncurses?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...