对于我正在处理的项目,我需要程序能够接收来自用户的输入,但是当他们输入内容时,程序可以继续循环。
例如:while (true)
{
if (userInput == true)
{
cin >> input
}
//DO SOMETHING
}
这意味着每个循环都会发生//DO SOMETHING
,而用户不会按百万次输入。
kbhit()
和getch()
创建自己的输入,但是这非常混乱,我不喜欢使用conio.h以便于携带等。此外,它不需要特别使用cin
,因为很有可能它不能使用它,所以任何好的解决方案都不需要我使用'不太好'的库来自己输入,将不胜感激。
答案 0 :(得分:2)
免责声明:以下似乎与Linux上的gcc一起使用,但由于某些原因,它无法在Windows上与VC ++一起使用。规范似乎为这里的实现提供了很大的余地,VC ++肯定会利用它......
任何std::basic_istream
或其基础std::basic_streambuf
都有多种功能。
为了了解是否有任何字符可供输入,您可以在std::basic_streambuf
上致电in_avail
:
if (std::cin.rdbuf() and std::cin.rdbuf()->in_avail() >= 0) {
}
in_avail
为您提供无阻塞的可用字符数,如果没有此类字符,则返回-1
。之后,您可以使用常规"格式化"读取std::cin >> input
等操作。
否则,对于未格式化的读取,您可以使用std::basic_istream
中的readsome
,其中最多可返回N个字符而不会阻止:
size_t const BufferSize = 512;
char buffer[BufferSize];
if (std::cin.readsome(buffer, BufferSize) >= 1) {
}
然而,值得注意的是,这种方法的实现变化很大,因此对于便携式程序来说,它可能没那么有用。
注意:如评论中所述,in_avail
方法可能不稳定。我confirm it can work,但是你首先必须使用C ++ IO流的一个不起眼的特性:std::ios_base::sync_with_stdio(false)
它允许C ++流缓冲输入(从而从C&#stdio缓冲区中窃取它)。
答案 1 :(得分:2)
为此可能值得研究多线程。我通常犹豫不决,因为多线程会引发许多可能最终难以调试的潜在问题,但在这种情况下,它们可以相当容易地被隔离。我设想这样的事情:
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
int main() {
std::atomic<bool> interrupted;
int x;
int i = 0;
do {
interrupted.store(false);
// create a new thread that does stuff in the background
std::thread th([&]() {
while(!interrupted) {
// do stuff. Just as an example:
std::cout << i << std::flush;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
});
std::cin >> x;
// when input is complete, interrupt thread and wait for it to finish
interrupted.store(true);
th.join();
// apply x, then loop to make new thread to do stuff
i = x;
} while(x != -1); // or some other exit condition
}
乍一看,这看起来有点浪费,因为它会产生并抛弃线程,但是用户输入在计算方面需要永恒,因此开销不应过高。更重要的是,它确实具有避免任何数据竞争建议的优势,因为主(输入)循环和后台线程之间唯一的通信方式是原子中断标志,以及x
对共享的应用当没有运行的线程可能会使主循环竞争时会发生数据。
答案 2 :(得分:1)
令人遗憾的是,如果按键被击中,则没有简单的可移植方式来异步检查。但我想标准委员会已经仔细评估了利弊。
如果您不想依赖第三方事件管理库,并且如果多线程会过度,那么可以选择拥有自己的kbhit()
版本,并为您想要的环境进行条件编译支持:
这不是最具学术性的答案,但它是务实的。
答案 3 :(得分:0)
也许,你可以试试:
while (true)
{
if (userInput == true)
{
if(cin >> input){
}else{
std::cout << "Invalid input!" << std::endl;
cin.clear();
}
}
//DO SOMETHING
}