【问题标题】:No-Waiting Command for receiving input [duplicate]用于接收输入的无等待命令 [重复]
【发布时间】:2012-06-02 07:34:32
【问题描述】:

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

char ch;

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

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

cin >> ch;

它会等待用户输入一些东西,然后用户必须按回车将输入发送到 ch 变量。

2- conio.h 头文件中的 getch() 命令。

ch = _getch();

它会等待用户输入一些东西,只要输入一个字符,它就会保存在 ch 变量中,用户不需要按 enter。顺便说一句,此代码将停止程序并等待输入。

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

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

【问题讨论】:

  • 您前段时间发布了一个类似的问题。您查看我建议的链接了吗?
  • 所以如果用户按键,您想等待一定的时间还是提前继续?
  • 这个问题的答案是特定于操作系统的,你还没有提到操作系统。
  • @BenVoigt,从_getch() 来看,我认为是 Windows。我不知道任何其他_getch()
  • @chris:我同意,但我希望陌生人继续填写详细信息,而不是根据假设回答。

标签: c++ windows input


【解决方案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

上:

gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1

这只是一种解决方案,它可能不适合您。
也可以考虑研究 ncurses。

【讨论】:

    【解决方案2】:

    在 Windows 上,您可以这样做:

    1. CreateFile 使用文件名"CONIN$",这将为您提供控制台的 Win32 句柄。
    2. WaitForSingleObject,传递控制台句柄和超时。
    3. 如果等待成功,请使用ReadConsoleInput 确定发生了什么。
    4. 如果等待失败,则发生超时。

    如果您只是在循环中轮询执行其他操作,那么您可以使用PeekConsoleInput,它会检查输入队列中是否有任何事件,并始终立即返回。


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

    1. 不必打开文件,因为stdin 始终是文件描述符0
    2. 使用selectpoll 测试输入活动是否存在超时。

    最终区别:在 Windows 上,鼠标活动的捕获方式相同。在 Unix 上,您通常会从 tty 读取键盘输入,而鼠标则是完全独立的。

    【讨论】:

    • 以前从未见过这种方法。需要研究的东西:)
    猜你喜欢
    • 2013-02-25
    • 1970-01-01
    • 2015-11-24
    • 1970-01-01
    • 2013-04-03
    • 1970-01-01
    • 2013-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多