我正在通过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");
的实现方式适用于所有前面三种情况:输入,无输入和输入损坏。就我的研究而言,还没有这样的解决方案,所以我可能会选择实施(当然这不是让我们感到高兴的事情)。