getch() и смешивание обычных клавиш с клавишами со стрелками

Я не могу отобразить текст на консоли, и он также не сохраняется должным образом. У меня работают клавиши со стрелками, Enter, Backspace и Escpe.

также еще одна / маленькая / ошибка, которую я действительно не получаю, - это когда я нажимаю esc, и она выходит из пустоты, которую я направляю на этот фрагмент кода

#endif  /* defined (_M_IX86) || defined (_M_X64) */
        __fastfail(FAST_FAIL_STACK_COOKIE_CHECK_FAILURE);

внутри gc_report.c, о котором я не нашел никакой информации (или, по крайней мере, связанной с моей проблемой).

#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
#define KEY_ENTER 13
#define KEY_BACKSPACE 8
#define KEY_ESCAPE 27

void texteditor(int x, int y,int kolommen,char textarr[20][20],int rijen=20)
{
    int index = 0, indey = 0, keuze,lol = 20;
    do{
        gotoxy(index + x, indey + y); 
        keuze = 0;
        keuze = _getch();
        if (keuze == 0 || keuze == 0xE0 || keuze == 224)
        {
            keuze = _getch();
            gotoxy(index + x, indey + y);
            switch (keuze)
            {
            case KEY_UP:indey--;
                break;
            case KEY_LEFT: index--;
                break;
            case KEY_DOWN:indey++;
                break;
            case KEY_RIGHT: index++;
                break;
            }
            indey = (indey <= 0) ? 0 : (indey > kolommen) ? kolommen : indey;
            index = (index <= 0) ? 0 : (index > rijen) ? rijen : index;
        }
            if (keuze == 32 || (keuze >= 46 && keuze <= 57) || (keuze <= 64 && keuze >= 126))
            {
                textarr[index][indey] = (char)keuze;
                std::cout << textarr[index][indey];
                index++;
                index = (index <= 0) ? 0 : (index > rijen) ? rijen : index;
            }
            if (keuze == KEY_BACKSPACE)
            {
                index = index--;
                gotoxy(index + x, indey + y);
                std::cout << " ";
                index = (index <= 0) ? 0 : (index > rijen) ? rijen : index;
            }
            if (keuze == KEY_ENTER)
            {
                index = 0;
                indey++;
                indey =(indey >= kolommen) ? kolommen : indey++;
            }       
    } while (keuze != KEY_ESCAPE);}

Я также немного поискал значения за клавишами со стрелками, в которых я нашел 37 (стрелка влево), 38 (стрелка вверх), 39 (стрелка вправо), 40 (стрелка вниз) как значение ASCII, тогда в чем разница с моим ?


person Semanresu    schedule 26.03.2015    source источник
comment
Это для какой системы? ДОС?   -  person Lundin    schedule 26.03.2015


Ответы (2)


Набор символов ASCII, как следует из названия, описывает набор символов, а не клавиши на клавиатуре. По этой причине в ASCII нет значений для клавиш со стрелками.

Вместо этого используемая вами функция _getch() возвращает либо 224 (E0h), либо 0, чтобы указать, что последующее является кодом сканирования ключа. Значения, которые вы используете для них, верны, и вы можете найти их здесь.

Другие значения, которые вы нашли (37-40), называются виртуальными ключами и встречаются гораздо чаще. например, они возвращаются в Javascript для event.keyCode, а также доступны в WinApi, но не применимы к вашему примеру _getch().

Теперь, когда с этим разобрались, давайте посмотрим на ваш пример:

  • Вы можете удалить E0, так как он равен 224.
  • Используемый вами массив textarr имеет размеры 20x20. Это означает, что запись за пределами textarr[19][19] является неопределенным поведением. Вы сравниваете индекс массива на предмет того, что он больше 20, прежде чем использовать rijen в качестве замещающего индекса. Вместо этого rijen должно быть 19. Таким образом, у вас нет внешнего доступа.
  • Я бы поставил kolommen рядом с rijen. Не имеет смысла располагать массив между ними + это мешает вам установить для него значение по умолчанию.
  • Вы также игнорируете множество печатных символов. Вы должны структурировать свой код так, чтобы в конце было условие else, где вы затем проверяете с помощью isprint(), можно ли его распечатать, а затем распечатываете его.
  • А теперь основная часть: if (... || (keuze <= 64 && keuze >= 126)). Ты видишь проблему? Я думаю, вы имели в виду (keuze >= 64 && keuze <= 126). То, как сейчас вы игнорируете все буквы ASCII.
  • Возможно, вы хотели бы очистить экран перед запуском texteditor(). system("cls") — это стандартный способ Windows сделать это.

Другое дело, что вложенность тернарных выражений некрасива. Ненужная скобка, которую вы использовали для условия, была бы намного лучше вокруг второго троичного выражения. Кроме того, консоль Windows по умолчанию имеет размер 80x25, который вы можете использовать вместо 20x20.

И, наконец, conio.h — это нестандартный заголовок, и вам лучше использовать вместо него функциональность, представленную в <windows.h>. Или вообще отказаться от неоптимальной обработки терминала в Windows и использовать библиотеку, например ncurses вместе с надлежащим Терминал.

person a3f    schedule 26.03.2015

Коды основаны на ansi.sys (для работы в современной Windows требуются некоторые надстройки). Вы не указали, какое дополнение вы используете. Возможно, вы ссылаетесь на какой-то источник как на статью Daniweb как обнаружить клавиши со стрелками??.

Вопросы, касающиеся клавиш со стрелками и getch (для практических целей аналогичны _getch -- см. Разницу между getch() и _getch()) ответили раньше :

  • getch и коды стрелок
  • Отн. ="nofollow noreferrer">Как сканировать клавиши со стрелками на клавиатуре?

Коды, используемые для слева/справа/вверх/вниз, основаны на конечном символе escape-последовательностей, распознаваемых ansi.sys, например, (согласно ncurses):

    kcub1=\0K,   
    kcud1=\0P,  
    kcuf1=\0M,   
    kcuu1=\0H,

Но \0 могут быть и другие символы, например \033[, \340, в зависимости от конфигурации. Последним может быть < em>Код расширенного префикса Windows, как указано в Коды сканирования на форуме CPlusPlus.

person Thomas Dickey    schedule 26.03.2015