Nick_is_asking Ответов: 2

Как я могу использовать ввод, не дожидаясь, пока пользователь что-то даст (используя C) ?


- Привет!!
Я использую язык Си и хочу использовать ввод ,не дожидаясь ввода пользователя или нажатия клавиши enter.(в python я могу это сделать)-я думаю, здесь тоже.
Например,я хочу напечатать "hello\n" в консоли внутри цикла while ,и когда пользователь дает ввод, я хочу напечатать данный ввод, не останавливая печать сообщения "hello".

Что я уже пробовал:

#include <stdio.h>
#include <stdlib.h>
#include <curses.h>

int main(void)
{
initscr();
noecho();
cbreak(); // don't interrupt for user input
timeout(500); // wait 500ms for key press
char c;
int a = 1;
while(a == 1)
{
  c = getch();
  printf("hello\n");
  printf("%c key pressed...\n",c);
}
  endwin();
  nocbreak();
}



но я получил эту ошибку:

/tmp/ccNmVWH7.o: в функции `main':
input_no_wait.c:(.text+0x9): неопределенная ссылка на `initscr'
input_no_wait.c:(.text+0xe): неопределенная ссылка на `noecho'
input_no_wait.c:(.text+0x13): неопределенная ссылка на `cbreak'
input_no_wait.c:(.text+0x1a): неопределенная ссылка на `stdscr'
input_no_wait.c:(.text+0x27): неопределенная ссылка на `wtimeout'
input_no_wait.c:(.text+0x2e): неопределенная ссылка на `stdscr'
input_no_wait.c:(.text+0x36): неопределенная ссылка на `wgetch'
input_no_wait.c:(.text+0x54): неопределенная ссылка на `endwin'
input_no_wait.c:(.text+0x59): неопределенная ссылка на `nocbreak'
collect2: ошибка: ld вернул 1 статус выхода


--------------------------------------------------------------
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0



Мне нужна твоя помощь.

Заранее спасибо!!!

2 Ответов

Рейтинг:
1

CHill60

У меня был бы основной процесс, работающий в одном потоке, и "ожидание ввода пользователя" в другом. Взгляните на это Использование Рабочих Потоков[^] для получения дополнительной информации (извините, что он использует C++, но посмотрите на принципы)
Другой - на этот раз в C#, но принципы остаются теми же Краткий обзор потоков[^]
Внешняя (для Codeproject) статья о потоковой передаче в C-это та самая статья из Корнельского университета[^]


Nick_is_asking

Есть ли что-нибудь еще,потому что я не понимаю??

CHill60

Ну вы могли бы посмотреть на проклятия (библиотека программирования) - Википедия[^]
Однако на каком то этапе я советую вам хорошенько подумать о резьбе

Nick_is_asking

Я попробовал этот код:

#включить <stdio.h>
#include <stdlib.h>
#включить <curses.h>

тап_п(недействительными)
{
initscr();
noecho();
cbreak(); // не прерывайте ввод данных пользователем
тайм-аут(500); // подождите 500 мс для нажатия клавиши

int c = getch();
printf("%c\n",c);
endwin();
nocbreak();
возвращает 0;
}


но я получил эту ошибку:

/tmp/ccNmVWH7.o: в функции `main':
input_no_wait.c:(.text+0x9): неопределенная ссылка на `initscr'
input_no_wait.c:(.text+0xe): неопределенная ссылка на `noecho'
input_no_wait.c:(.text+0x13): неопределенная ссылка на `cbreak'
input_no_wait.c:(.text+0x1a): неопределенная ссылка на `stdscr'
input_no_wait.c:(.text+0x27): неопределенная ссылка на `wtimeout'
input_no_wait.c:(.text+0x2e): неопределенная ссылка на `stdscr'
input_no_wait.c:(.text+0x36): неопределенная ссылка на `wgetch'
input_no_wait.c:(.text+0x54): неопределенная ссылка на `endwin'
input_no_wait.c:(.text+0x59): неопределенная ссылка на `nocbreak'
collect2: ошибка: ld вернул 1 статус выхода

CHill60

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

Nick_is_asking

Я компилирую так: gcc name.c name и запускаю так ./name
Я просто хочу получить ввод, не дожидаясь ввода пользователя и не нажимая кнопку [ENTER].

CHill60

Там должен быть файл конфигурации или настроек или что - то подобное-или, возможно, Вам это нужно.
Могу ли я предложить вам поднять новый вопрос об этом - опубликовать свой код и детали ошибки, как вы это сделали в своем комментарии. Также укажите, как вы компилируете/связываете свой код - укажите также имя компилятора, который вы используете.
Надеюсь, кто-то, кто более хорошо разбирается в компиляторах C на Ubuntu, сможет предложить лучшую помощь

Рейтинг:
1

Nick_is_asking

Я нашел решение ,но мне нужно нажать клавишу, которую я хочу, дважды, а не один раз.
Вот код, и я думаю, что проблема заключается в getch().
Можете ли вы помочь мне решить эту проблему(я хочу нажать кнопку один раз, а не два).
Код:

#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/select.h>


int kbhit(void);
int getch(void);

int kbhit(void)
{
  struct timeval tv;
  fd_set read_fd;

  /* Do not wait at all, not even a microsecond */
  tv.tv_sec=0;
  tv.tv_usec=0;

  /* Must be done first to initialize read_fd */
  FD_ZERO(&read_fd);

  /* Makes select() ask if input is ready:
   * 0 is the file descriptor for stdin    */
  FD_SET(0,&read_fd);

  /* The first parameter is the number of the
   * largest file descriptor to check + 1. */
  if(select(1, &read_fd,NULL, /*No writes*/NULL, /*No exceptions*/&tv) == -1)
    return 0;  /* An error occured */

  /*  read_fd now holds a bit map of files that are
   * readable. We test the entry for the standard
   * input (file 0). */
  
if(FD_ISSET(0,&read_fd))
    /* Character pending on stdin */
    return 1;

  /* no characters were pending */
  return 0;
}




int  getch(void) {
    struct termios oldattr, newattr;
    int ch;
    tcgetattr( STDIN_FILENO, &oldattr );
    newattr = oldattr;
    newattr.c_lflag &= ~( ICANON | ECHO );
    tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
    ch = getchar();
    tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
    return ch;
}



int main(){
        int a = 1;
   while(a == 1){
      if(kbhit() == 0){
         getch();
                 printf("%c is pressed\n",getch());
         
      }  
   }
  return 0;
}



Например, если я нажимаю "а", а затем снова "а", то я получаю -> а нажимается.
Но я хочу нажать " а " только один раз, чтобы получить -> а нажата.
Мне нужна твоя помощь.

Заранее спасибо...


Richard MacCutchan

Какую именно проблему вы пытаетесь решить? Использование консольного приложения таким образом очень старомодно.

Nick_is_asking

Я хочу построить змеиную игру в терминале С помощью C, и я не знаю, какой вход использовать для перемещения змеи.Столь простой.