用于接收输入的No-Waiting命令

时间:2012-05-27 18:00:57

标签: c++ windows input

  

可能重复:
  C/C++: Capture characters from standard input without waiting for enter to be pressed

char ch;

我想要得到一个角色。我知道两种不同的方式。

1-在iostream头文件中使用cin命令。

cin >> ch;

它将等待用户输入内容,然后用户必须按Enter键将输入发送到ch变量。

conio.h头文件中的

2- getch()命令。

ch = _getch();

它将等待用户键入内容,只要键入一个字符,它就会保存在ch变量中,用户无需按Enter键。 BTW此代码将停止程序并等待输入。

现在我想编写一个不需要按Enter键的命令,它不会停止按下某个程序的程序。想象一下,我将程序延迟1秒钟,如果用户按下它会将其保存到ch变量中,如果不是什么,程序将继续,并且它不会停止按下某些东西。它就像一个选择器命令,如果它有什么东西可以拾取它,如果没有它会继续。

希望我很清楚。那怎么办呢?

2 个答案:

答案 0 :(得分:2)

在Windows上,您可以这样做:

  1. CreateFile使用文件名"CONIN$",它将为您提供控制台的Win32句柄。
  2. WaitForSingleObject,传递控制台句柄并暂停。
  3. 如果等待成功,请使用ReadConsoleInput确定发生了什么。
  4. 如果等待失败,则发生超时。
  5. 如果您只是在循环中轮询执行其他操作,那么您可以使用PeekConsoleInput,它会检查输入队列中是否有任何事件,并且始终立即返回。


    在Unix上,类似的方法也可以。请注意:

    1. 没有必要打开文件,因为stdin始终是文件描述符0
    2. 使用selectpoll在超时时测试输入活动。
    3. 最终差异:在Windows上,鼠标活动以相同的方式捕获。在Unix上,你通常会从tty读取键盘输入,鼠标的东西是完全独立的。

答案 1 :(得分:1)

首先我们需要一个函数来打开和关闭非阻塞输入:

void nonblock(const bool state){

    struct termios ttystate;

    //get the terminal state
    tcgetattr(STDIN_FILENO, &ttystate);

    if (state){
        //turn off canonical mode
        ttystate.c_lflag &= ~ICANON;
        //minimum of number input read.
        ttystate.c_cc[VMIN] = 1;
    }
    else{
        //turn on canonical mode
        ttystate.c_lflag |= ICANON;
    }

    //set the terminal attributes.
    tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
}

现在我们需要一个函数来测试并查看是否按下了某个键:

int keypress(void){
    struct timeval tv;
    fd_set fds;
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    FD_ZERO(&fds);
    FD_SET(STDIN_FILENO, &fds);
    select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
    return FD_ISSET(STDIN_FILENO, &fds);
}

我们要同时检查两件事。用户是否按了一个键,或者时间用完了? 这是一个在指定的秒数后更改布尔值的函数:

void SleepForNumberOfSeconds(const int & numberofSeconds,bool & timesUp){

    timespec delay = {numberofSeconds,0};
    timespec delayrem;

    nanosleep(&delay, &delayrem);
    timesUp = true;

    return;
}

以下是您可以致电的主要功能:

void WaitForTimeoutOrInterrupt(int const& numberofSeconds){

    bool timesUp = false;

    std::thread t(SleepForNumberOfSeconds, numberofSeconds, std::ref(timesUp));
    nonblock(1);
    while (!timesUp && !keypress()){

    }

    if (t.joinable()){
        t.detach();
    }
    nonblock(0);

    return;
}

这是要测试的code 编译:

  

g ++ -std = c ++ 0x -o rand rand.cpp -lpthread

on:

  

gcc(Ubuntu / Linaro 4.6.1-9ubuntu3)4.6.1

这只是一种解决方案,它可能对您不起作用 考虑一下ncurses。