Как мне отменить пользовательский ввод, доставленный во время функции сна?

#c #input #stdin

#c #ввод #стандартный

Вопрос:

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

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

 void countdown(void){
  printf("5n");
  sleep(1);
  printf("4n");
  sleep(1);
  printf("3n");
  sleep(1);
  printf("2n");
  sleep(1);
  printf("1n");
  sleep(1);
  clearScreen(0); //clears terminal
}
  

Комментарии:

1. Посмотрите на ncurses .

2. если вы находитесь в Windows: learn.microsoft.com/en-us/cpp/c-runtime-library/reference /…

3. Windows также реализует нестандартные fflush(stdin) и rewind(stdin) , оба из которых очищают буфер ввода, но не являются переносимыми.

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

5. @bsheps только если это задокументировано таким образом, но теперь кажется, что ОС — это Linux, поэтому: нет.

Ответ №1:

Вы в принципе не можете; Понятие «отбрасывание пользовательского ввода в течение определенного периода времени» на самом деле не имеет никакого смысла для стандартного вывода и ввода, учитывайте тот факт, что ваш ввод может поступать, например, из файла (проблема здесь в том, что «время» на самом деле не является понятием, которое каким-либо образом существует в стандартных процедурах ввода / вывода).

Для этого вам понадобится терминальный API, а в стандартной библиотеке C ничего подобного нет, хотя есть библиотеки, которые предоставляют подобные возможности (но вы уже сказали, что не хотите использовать внешние библиотеки).

Комментарии:

1. Это имеет смысл, но есть ли способ отменить его непосредственно перед выходом из функции?

2. Как насчет использования tcflush?

3. @bsheps Это часть API терминала Linux, а не стандартный C.

4. @Cubic В своих комментариях под вопросом говорит, что использует Linux mint, и программа должна запускаться на CentOS. Разве обе эти среды (Linux) не будут иметь доступ к этой библиотеке по умолчанию? (к вашему сведению — я все еще новичок в C)

5. @bsheps это скорее «ответ на вопрос, который был задан», а не ответ типа «решить основную проблему, с которой сталкивается OP»

Ответ №2:

Поскольку вы используете среду Linux, вы можете попробовать использовать tcflush()

Ссылка на документацию tcflush

Вот измененный пример вашего кода с использованием tcflush. Вы можете раскомментировать нижнюю часть и увидеть, что все, введенное во время обратного отсчета, удалено из буфера stdio.

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

void main(){
        char str[100];
        printf("5n");
        sleep(1);
        printf("4n");
        sleep(1);
        printf("3n");
        sleep(1);
        printf("2n");
        sleep(1);
        printf("1n");
        sleep(1);

        // arguments for tcflush: 
        // 0 is for stdin 
        // TCIFLUSH is to flush data received but not read
        tcflush(0,TCIFLUSH);

        // prove it works by uncommenting this code
//      printf("fgets is waiting");
//      fgets(str, sizeof(str), stdin);
//      printf("%s", str);

//      clearScreen(0); //clears terminal
}
  

Комментарии:

1. Обратите внимание, что int main() требуется ISO C, а не void. Но да, это работает, даже очищая буфер редактирования строки (текст, который вы ввели, но еще не нажали return on).

Ответ №3:

Одним из способов было бы использовать поток для обратного отсчета.

Основной код запускает поток обратного отсчета, затем выполняет цикл для получения ввода.

Если функция ввода возвращается до завершения потока или был введен неправильный ответ, игнорируйте ввод и повторите цикл.

Комментарии:

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

2. @Cubic но разве это не потребовало бы от пользователя ввода в любом случае?