无需暂停代码的用户输入(c 控制台应用程序)

新手上路,请多包涵

如何在不导致代码停止执行的情况下输入输入?在过去的 20 分钟里,我一直在寻找答案,但没有结果。

cin >> string; 暂停代码AFAIK。

我需要使用多线程,还是有更好的方法? (我什至不知道多线程是否可行。)

我最近开始学习 c++,至少可以说我是初学者,所以请彻底解释并包括我可能需要的任何库,谢谢。

原文由 Mandera 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
2 个回答

有两种算法可以在不阻塞(暂停)的情况下获取输入。第一个是轮询,第二个是按事件(中断)。

轮询输入

轮询涉及定期检查输入。使用键盘,这可能是读取键盘以进行按键操作。对于串行端口,这可能意味着检查接收寄存器的状态。

在某些系统上阻塞或等待输入将包括永远轮询,直到接收到输入。

输入事件

在某些平台上,当检测到输入时会发送一个事件。例如,Windows 操作系统接收到一个按键被按下的事件,并将消息发送到焦点任务。在嵌入式系统上,硬件可以取消引用中断向量处的函数指针。

在基于事件的系统上阻塞输入意味着休眠直到接收到事件。

概括

标准 C++ 语言不提供用于无阻塞地检索输入的标准函数。 C++ 输入函数的实现依赖于平台,可能会阻塞也可能不会阻塞。例如,平台可以等到收到换行符后再返回单个字符。

许多平台或操作系统都有功能,您可以在其中测试端口的输入(轮询)或在输入发生时收到通知(事件驱动)。由于您没有指定您使用的是哪个平台,所以详细信息到此为止。

原文由 Thomas Matthews 发布,翻译遵循 CC BY-SA 3.0 许可协议

这是一个示例,说明如何使用 >> 与另一个使用多线程的调用并行地从标准输入流中读取令牌。

 #include <iostream>
#include <thread>
#include <future>

int main() {
    // Enable standard literals as 2s and ""s.
    using namespace std::literals;

    // Execute lambda asyncronously.
    auto f = std::async(std::launch::async, [] {
        auto s = ""s;
        if (std::cin >> s) return s;
    });

    // Continue execution in main thread.
    while(f.wait_for(2s) != std::future_status::ready) {
        std::cout << "still waiting..." << std::endl;
    }

    std::cout << "Input was: " << f.get() << std::endl;
}

这里使用启动参数 std::launch::async 调用 std::async 在不同的线程上异步运行任务。 std::async 返回并行运行的任务的句柄,称为 future 。这个未来可用于检查任务是否完成。也可以使用成员函数 std::future::getstd::future 对象返回任务的结果。

我传递给 std::async 的任务是一个简单的 lambda 表达式,它创建一个字符串,从流中读取一个令牌并返回它( ""s 是引入的标准文字在 C++14 中返回一个空的 std::string 对象)。

调用 std::async 后主线程继续执行语句(与异步运行任务并行)。在我的示例中,执行了一个 while 循环,它只是等待异步任务完成。请注意使用 std::future::wait_for 每次迭代仅阻塞 2 秒。 std::future::wait_for 返回一个可以比较的 状态 来检查任务是否完成。

最后调用 std::future::get 会返回异步运行任务的结果。如果我们没有等待任务完成,调用将阻塞,直到结果准备好。

注意不要从主线程中的标准输入(并行)读取,因为读取调用 不是 原子事务并且数据可能会出现乱码。

原文由 Felix Glas 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题