C++ 中断或取消 getch();

标签 c++ c++11 interrupt getch

我有一个简单的计时器。它在一个与主线程分开的线程中运行的函数中。使用 std::future,该函数返回一个简单的 bool 值,表示计时器是否达到特定数字。

我正在使用 getch(); 查看用户是否按下了字母键。

如果计时器返回真,即它命中了指定的数字,我需要取消getch();并转到代码中的下一步。进入下一步很容易。

已经 2 周了,我找不到解决问题的方法。

问题: 我究竟该如何中断或取消对 getch(); 的调用?这可能吗?

我正在使用 getch(); 来识别按下了哪些字母键。

C++11 Visual Studio。

最佳答案

操作系统必须提供对键盘的访问。因此,例如在 Windows 上,最好的方法可能是按照操作系统的术语处理输入,如 here 所述。 .

使用标准的 c++ 库函数,可以从 std::cin 流中读取字符。问题在于,这些字符仅在用户按下 Enter(同时添加换行符 \n 字符)后才从操作系统传递。

如果您可以忍受在键入一个字符后按回车键的需要,那么下面的代码就可以工作了。该程序执行 get()在一个单独的线程中,这样如果没有按下任何键或者如果 Enter 没有被按下并且只使用标准的 c++11,它就不会阻塞程序。但是,除非用户键入 qsends the EOF,否则该程序不会完成(即加入线程) .

#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>

std::condition_variable cv{};
std::mutex mtx;
std::queue<char> char_queue{};
bool quit{false};

void add_chars_to_queue()
{
    char c{};
    for(;;) {
        c = static_cast<char>(std::cin.get());
        if(!std::cin) {
            std::unique_lock<std::mutex> lck{mtx};
            quit = true;
            cv.notify_all();
            return;
        }
        if(c == 'q' || c == 'Q') {
            std::unique_lock<std::mutex> lck{mtx};
            quit = true;
            char_queue.push(c);
            cv.notify_all();
            return;
        }
        if(c == '\n')
            continue;
        std::unique_lock<std::mutex> lck{mtx};
        char_queue.push(c);
        cv.notify_all();
    }
}


std::string get_key_or_wait(std::chrono::system_clock::duration d)
{
    std::unique_lock<std::mutex> lck{mtx};
    for(int i{10}; i > 0; --i) {
        cv.wait_for(lck, d / 10., []() {return quit || !char_queue.empty(); });
        if(!char_queue.empty())
            break;
        if(quit)
            return{"Quitting.\n"};
        std::cout << "Countdown at " << i << '\n';
    }
    std::string return_string{};
    if(!char_queue.empty()) {
        return_string += "Obtained a character from the stream before the timer ran out. Character was: ";
        return_string += char_queue.front();
        char_queue.pop();
    }
    else {
        return_string = "Timer ran out.";
    }

    return return_string;
}

int main()
{
    std::thread get_chars{[]() {add_chars_to_queue(); }};

    std::cout << "Type q to exit.\n";
    for(int i{}; i < 3; ++i) {
        {
            std::lock_guard<std::mutex> lck{mtx};
            if(quit)
                break;
        }
        std::cout << "Waiting for key press followed by <enter>.\n"; 
        std::cout << get_key_or_wait(std::chrono::seconds(10)) << '\n';
    }

    get_chars.join();
    return 0;
}

输出:

Type q to exit.
Waiting for key press followed by <enter>.
Countdown at 10
Countdown at 9
Countdown at 8
a
Obtained a character from the stream before the timer ran out. Character was: a
Waiting for key press followed by <enter>.
Countdown at 10
Countdown at 9
Countdown at 8
Countdown at 7
Countdown at 6
Countdown at 5
Countdown at 4
Countdown at 3
Countdown at 2
Countdown at 1
Timer ran out.
Waiting for key press followed by <enter>.
Countdown at 10
Countdown at 9
Countdown at 8
bCountdown at 7
Countdown at 6
Countdown at 5

Obtained a character from the stream before the timer ran out. Character was: b
q

关于C++ 中断或取消 getch();,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41368759/

相关文章:

linux - 设置中断标志 (sti) 使 linux 内核崩溃

c# - 检测新创建的文件,刚刚编辑的文件

c++ - 保护 QML 源代码免遭抄袭

c++ - 嵌入式Linux应用程序中的周期 "lags"

c++ - 通过跳过可选参数来填充参数包

c++ - 当我在子类中调用函数时,它会调用父类函数

operating-system - 电源故障中断究竟发生了什么?

c++ - 根据线性顺序使用最接近的值将数字裁剪为其他类型的数字限制

c++ - gcc vs clang 在具有可变参数和相同类型的额外参数的部分特化上的行为

c++11 - Clang 提示 "cannot override a deleted function"而没有删除任何功能