портативная альтернатива kbhit() и getch() и system(cls)

Мне нужен переносной способ использования функций kbhit и getch. В настоящее время я разрабатываю простую ascii-игру, и мне нужно определить, нажата ли клавиша. Если это так, мне нужно прочитать его, а если нет, мне нужно продолжить, не дожидаясь ввода. Я бы предпочел не повторять это, но я не буду придираться к этому. Я думаю, что kbhit и getch были бы хороши для этого, НО мне разрешено использовать только полностью переносимый код (ну, по крайней мере, код для Linux, Mac и ПК, хотя не так много других ОС приходит на ум). Насколько я понимаю, библиотеки termios, curses и conio не полностью реализованы на всех трех нужных мне ОС. Я в растерянности. Каждое решение, которое я нашел, использует непереносимый код. Могу ли я как-нибудь написать для этого переносимые функции? В настоящее время я включаю stdio.h, stdlib.h и time.h. Мне также нужен портативный способ очистки экрана, так как в настоящее время я использую систему («cls») и систему («очистить»), которые также необходимо менять каждый раз, когда я меняю ОС, или это способ, которым я мог бы сделать if-else и определите ОС, на которой работает код, чтобы переключаться между этими двумя операторами. Вот фрагмент кода, в котором есть эти функции:

    char key = ' ';
    while(1)
    {
        system("cls");
        if (_kbhit())
        {
            key =_getch();
            printf("output: %c", key);
        }    
        else
            printf("output:");
    }

По сути, это та функциональность, которая мне нужна в моем коде, но я не могу придумать переносимый способ сделать это, и мой учитель требует, чтобы код работал на Linux, Mac и ПК с использованием стандартного C и стандартных библиотек. Пожалуйста помоги! И никакого C++, пожалуйста, мы используем c.

РЕДАКТИРОВАТЬ: я не думаю, что ncurses был не совсем тем, что я искал. Кто-то порекомендовал мне использовать #ifdef для их реализации во время компиляции. Мне нравится это решение, но мне нужна помощь, чтобы понять, как это сделать на Linux и Mac, поскольку я могу протестировать только Windows с моей текущей настройкой. надеюсь, что скоро Linux будет работать на моей другой машине для тестирования, но OSX имеет большую цену, поэтому я был бы признателен за помощь. Вот текущий код:

 //libraries
#include <stdio.h>      //used for i/o
#include <stdlib.h>     //used for clearing the screen
#include <time.h>       //used to get time for random number generator

//check OS and include necessary libraries
#ifdef _WIN32
    //code for Windows (32-bit and 64-bit, this part is common)
    #include <conio.h>
    #define CLEARSCREEN system("cls")
    #define CHECKKEY _kbhit()
    #define NBGETCHAR getch()

#elif __APPLE__
    //code for mac
    #define CLEARSCREEN system("clear")
    #define CHECKKEY 
    #define NBGETCHAR 

#elif __linux__
    //code for linux
    #define CLEARSCREEN system("clear")
    #define CHECKKEY 
    #define NBGETCHAR 

#else
#   error "Unknown compiler"
#endif

int main()
{
    char key = ' ';
    while(1)
    {
        CLEARSCREEN;
        if (CHECKKEY)
        {
            key=NBGETCHAR;
            printf("output: %c", key);
        }    
        else
            printf("output:");
    }
}

person The Villain In Glasses    schedule 10.12.2015    source источник
comment
Одним из решений является использование #ifdef для выбора (во время компиляции) правильного кода для ОС. Переносимый код не означает, что его можно скомпилировать один раз и использовать везде. Это означает компиляцию на каждой ОС с таким количеством зависимостей от ОС, которое необходимо.   -  person user3386109    schedule 10.12.2015
comment
Нет портативного способа сделать это. Самое близкое, что вы можете сделать, это какая-то сторонняя библиотека, которая решает проблемы переносимости за вас. Проклятия, вероятно, подходят ближе всего к этому. В противном случае вам придется написать свои собственные функции clear(), kbhit() и getch() с отдельными версиями каждой для каждой операционной системы.   -  person Ross Ridge    schedule 10.12.2015
comment
ПОЧЕМУ нет портативного способа сделать это?   -  person Dmitry    schedule 12.04.2016
comment
Потому что unix-подобные операционные системы (Mac OS X, GNU/Linux и т. д.) и Microsoft Windows NT совершенно разные. В Windows есть API, чтобы делать забавные вещи с окном консоли, в то время как в Unix используются curses для чтения и записи магических последовательностей байтов, которые были введены физическими терминалами, такими как VT100 и до сих пор используются эмуляторами терминала. / История заключается в том, почему нет портативного способа сделать это.   -  person Oskar Skog    schedule 15.10.2016


Ответы (1)


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

person Jon Purdy    schedule 10.12.2015
comment
Это не решение. ncurses захватывает ваш экран и не совместим с существующими консольными программами. После того, как вы перейдете к проклятиям, вы должны преобразовать всю свою программу в проклятия, чтобы быть последовательными. ncurses также очищает ваш экран, что обычно пугает пользователя, привыкшего просто запускать программы, которые только прокручивают. - person Dmitry; 12.04.2016