如果我们用std::getline
或者简单的std::cin >>
获取用户输入,有一个问题是,它会阻塞掉整个程序,用户必须有输入后才能继续执行。如果这个输入是单独的线程,它还会阻止整个程序的退出。
这个时候可以用下面这个函数,非阻塞式的用户输入,会检查用户是否在输入,没有的话就直接返回空:
#include <iostream>
#include <optional>
std::optional<std::string> noblock_input(std::istream& in = std::cin)
{
// 下面这个很关键
in.sync_with_stdio(false);
if (in.rdbuf()->in_avail() > 0) {
char buffer[1024];
in.getline(buffer, sizeof(buffer));
return buffer;
}
return {};
}
注意,该实现在用户已有输入字符的情况下,会等到用户输入到按下回车为止,在这期间是也是阻塞的。
也有人提到:
The only C++ function that comes close to what you're asking is std::cin.rdbuf()->in_avail(): http://www.cplusplus.com/reference/streambuf/streambuf/in_avail/
But it won't help you to do what you're describing: std::cin's buffer is not updated when the user presses a key. It is only updated when you, the programmer, attempt to make a read from std::cin and its buffer happens to be empty, so it has to ask the OS for input.
If you're trying to build a keyboard-interactive game, use a gaming library that provides such functionality, or the underlying OS API. (for POSIX OS, the API is select()/poll(), combined with appropriate tty driver settings)
所以上述实现有可能依赖于特定的编译器和命令行客户端。该实现在 ubuntu 20.04 / GCC 9.4 / windows terminal 下测试有效。
Q. E. D.