是否有可能实现一种现代的,便携式的“等待输入”实现?

时间:2019-05-28 13:18:40

标签: c++

我正在通过Visual Studio教授C ++,我想提供一种可移植,安全,现代的System("pause")类似功能。读How to simulate “Press any key to continue?”非常令人沮丧,因为没有一个答案可以提供一种便携式/现代的解决方案,有效


常见建议:std::cin.get();通常不这样做:

  • 如果之前使用过std::cin-已跳过。因此需要调用两次才能暂停一次。
  • 如果写入两次-并且之前没有输入-它将暂停两次
  • 如果先前输入无效,则所有呼叫都将被跳过std::cin.clear()之前无法解决。

std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

std::cin.get();更好,因为实际上调用std::cin.clear();确实可以解决输入已损坏(仍然引起中断)的情况。


考虑到std::cin.ignore(...);以不可预测的方式被跳过是一个问题。请注意,std::getline(std::cin, dummy);std::cin >> dummy;(当然还有std::cin.get();也是如此。


由于std::cin不提供检查是否已使用它的功能(如标志),因此我必须查看是否暂停语句被跳过。一种解决方案是使用std::getline()并查看生成的std::string是否为空。 问题:

  • 用户按下“ enter”(输入):字符串为空。

  • 语句被跳过:字符串为空。

所以这不起作用。在不要求用户输入除enter之外的其他内容的情况下,我看不到正确实现此方法的方法。


我考虑了很长时间,并提出了一个便携式但依赖硬件的解决方案:节省时间。 输入“输入”所花费的时间比被跳过的时间要多。我说如果经过的时间小于20微秒,我可以认为它已被跳过,并要求第二个std::cin.ignore(...)

在我的系统上,跳过的时间从未超过10微秒。人类的反应时间将永远不会超过此时间-但是,只要在调用该函数之前按“ Enter”键,就可以减少此延迟。在这种快速情况下,我得到的最低时间范围是100微秒。因此,这是此实现:

#include <iostream>
#include <limits>
#include <chrono>

void system_pause(unsigned max_keyboard_latency_hz = 50'000u) {
    std::cout << "press enter to continue . . . ";
    if (!std::cin.good()) {
        std::cin.clear();
    }
    auto t1 = std::chrono::high_resolution_clock::now();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    auto t2 = std::chrono::high_resolution_clock::now();

    double delta_t = std::chrono::duration_cast<std::chrono::nanoseconds>(t2 - t1).count() / 1e9;
    if (delta_t < 1.0 / max_keyboard_latency_hz) {
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
}

max_keyboard_latency_hz是第一个std::cin.ignore();被跳过的值(以赫兹为单位),如果执行得更快的话。在以下情况下,它的行为正确:输入,输入损坏和无输入。问题在于极端情况(立即按回车键),这取决于硬件(性能/输入等待时间),尽管灵活的max_keyboard_latency_hz对此却微不足道。


我只想知道是否有一种方法可以使类似System("pause");的实现方式适用于所有前面三种情况:输入,无输入和输入损坏。就我的研究而言,还没有这样的解决方案,所以我可能会选择实施(当然这不是让我们感到高兴的事情)。

0 个答案:

没有答案