如何在 C++ 中创建一个运行时间计数器并允许用户同时输入的循环(非阻塞用户输入)
How to make a loop in C++ that runs a time counter and allows for user input simultaneously (non-blocking user input)
所以,我想做的是 在 C++ 中创建一个函数,允许用户在一定时间内将任何内容输入字符串 (例如,十分钟(甚至一分钟))(并保留他们输入的所有内容, 顺便说一句。我正在尝试设计一款游戏来帮助 NaNoWriMo 参与者或一般作者推动他们写作,因此保留所有内容是必不可少的)然后不允许再附加输入。 起初这听起来很容易,但五个小时的谷歌搜索证明并非如此。
首先,我认为我可以重复追加直到时间 运行 结束或其他什么。观察:
int main() //testing
{
string str;
string app = " ";
getline(cin, app);
for (int i = 0; i <= 3; i++)
{
Sleep(5000);
cout << i << endl;
str = " ";
getline(cin, str);
app.append(str);
}
cout << app;
}
但后来我意识到,duh, 在用户按下 enter 之前,循环不会再次检查条件。麻烦。与我对角色的巧妙构想相同。我需要一个循环,它随着每个输入的字符(或过去的每一秒)而更新,无论用户输入另一个字符需要多长时间。
所以,然后我就想,"Well, stopping at every space and updating the time should work well enough, yeah?"
这是我开始发现 C++ 在解析字符串或读取输入时表现不佳的时候。我考虑过附加每个 字符, 因为这很容易找到 space,但它 仍然 等待用户。
很沮丧,我想知道是否有一种方法可以让程序 运行 在获取用户输入的同时同时进行,这样一旦时间 运行 结束(使用 time(null), time passes, time(null) 并减去两个变量以获得经过的秒数)。
原来有! (考虑到所有使用此原理的计算机程序和游戏,我知道 必须 ,但我对编程还很陌生(我学习了 函数 上周三,给你一个想法),所以我不知道 什么 。)
我偶然发现的第一个函数是 curses 和 ncurses,但我很快发现这对于我想做的事情来说真的不是一个可行的选择(因为我听说它做的事情很有趣)。
然后 我偶然发现了 kbhit,它可以识别何时按下键盘上的键。 This blog 看起来很有前途,大概是我想做的,但是我不确定它是用什么语言写的。 . .我所知道的是它不能很好地与我的 C++ IDE 配合使用。我不知道如何让它与 C++ 兼容。
所以,重申一下我想要的:
一个包含同时执行时间计数器和用户输入(到字符串)的循环,但是当时间 运行 出来了。(所有这些都没有像 ncurses 那样对我的程序的其余部分做任何有趣的事情。)
此外:我 运行 Windows 8(我存在的祸根)并且我使用 Code::Blocks 作为我的 IDE。
或者,如果你知道了,这个问题已经在某个地方得到了回答。那实际上会很棒。如果我找不到它只会让我觉得很傻。
(以下是我一路上看过的一些地方:
User input while program still running
How do I read input from standard input until a space or a tab is pressed?
Capture characters from standard input without waiting for enter to be pressed)
(我正在尝试创建的游戏,(完全还不是很远;我昨晚开始了),以防你好奇:https://github.com/Rowan-Law/Dungeon-Crawl/blob/master/Source%20Code)
您可能想为时间创建一个线程,然后继续更新字符串直到时间线程返回
多线程是解决方案。在基本级别,使用 std::cin
的 C++ 控制台应用程序仅在输入时更新(正如我和 Christian Hackl 所指出的),因此如果没有线程,我想做的事情是不可能的。
我知道这个问题已经很老了,但我希望这个答案能为其他新手节省大量时间在网上搜索不存在的答案!
以下是您如何使用线程在 C++17 中获得您想要的非常接近的近似值。唯一的小问题是用户在时间限制后仍然可以输入,只是不会被保存。
#include <atomic>
#include <chrono>
#include <iostream>
#include <istream>
#include <mutex>
#include <ostream>
#include <string>
#include <thread>
std::atomic_bool done = false;
std::mutex cout_mutex{};
void Timing(std::chrono::seconds length) {
auto start = std::chrono::steady_clock::now();
auto end = start + length;
auto now = std::chrono::steady_clock::now();
while(now < end) {
now = std::chrono::steady_clock::now();
done = false;
}
done = true;
{
std::scoped_lock<std::mutex> lock(cout_mutex);
std::cout << "\nTime's up! Any unsaved input will be lost." << std::endl;
}
}
int main() {
std::string str{};
std::string app{};
using namespace std::literals::chrono_literals;
//This can be any duration you want.
std::thread t = std::thread(Timing, 30s);
t.detach();
while(!done) {
std::getline(std::cin, str);
if(!done) {
app.append(str + '\n');
}
}
std::cout << app;
}
所以,我想做的是 在 C++ 中创建一个函数,允许用户在一定时间内将任何内容输入字符串 (例如,十分钟(甚至一分钟))(并保留他们输入的所有内容, 顺便说一句。我正在尝试设计一款游戏来帮助 NaNoWriMo 参与者或一般作者推动他们写作,因此保留所有内容是必不可少的)然后不允许再附加输入。 起初这听起来很容易,但五个小时的谷歌搜索证明并非如此。
首先,我认为我可以重复追加直到时间 运行 结束或其他什么。观察:
int main() //testing
{
string str;
string app = " ";
getline(cin, app);
for (int i = 0; i <= 3; i++)
{
Sleep(5000);
cout << i << endl;
str = " ";
getline(cin, str);
app.append(str);
}
cout << app;
}
但后来我意识到,duh, 在用户按下 enter 之前,循环不会再次检查条件。麻烦。与我对角色的巧妙构想相同。我需要一个循环,它随着每个输入的字符(或过去的每一秒)而更新,无论用户输入另一个字符需要多长时间。
所以,然后我就想,"Well, stopping at every space and updating the time should work well enough, yeah?"
这是我开始发现 C++ 在解析字符串或读取输入时表现不佳的时候。我考虑过附加每个 字符, 因为这很容易找到 space,但它 仍然 等待用户。
很沮丧,我想知道是否有一种方法可以让程序 运行 在获取用户输入的同时同时进行,这样一旦时间 运行 结束(使用 time(null), time passes, time(null) 并减去两个变量以获得经过的秒数)。
原来有! (考虑到所有使用此原理的计算机程序和游戏,我知道 必须 ,但我对编程还很陌生(我学习了 函数 上周三,给你一个想法),所以我不知道 什么 。)
我偶然发现的第一个函数是 curses 和 ncurses,但我很快发现这对于我想做的事情来说真的不是一个可行的选择(因为我听说它做的事情很有趣)。
然后 我偶然发现了 kbhit,它可以识别何时按下键盘上的键。 This blog 看起来很有前途,大概是我想做的,但是我不确定它是用什么语言写的。 . .我所知道的是它不能很好地与我的 C++ IDE 配合使用。我不知道如何让它与 C++ 兼容。
所以,重申一下我想要的:
一个包含同时执行时间计数器和用户输入(到字符串)的循环,但是当时间 运行 出来了。(所有这些都没有像 ncurses 那样对我的程序的其余部分做任何有趣的事情。)
此外:我 运行 Windows 8(我存在的祸根)并且我使用 Code::Blocks 作为我的 IDE。
或者,如果你知道了,这个问题已经在某个地方得到了回答。那实际上会很棒。如果我找不到它只会让我觉得很傻。
(以下是我一路上看过的一些地方:
User input while program still running
How do I read input from standard input until a space or a tab is pressed?
Capture characters from standard input without waiting for enter to be pressed)
(我正在尝试创建的游戏,(完全还不是很远;我昨晚开始了),以防你好奇:https://github.com/Rowan-Law/Dungeon-Crawl/blob/master/Source%20Code)
您可能想为时间创建一个线程,然后继续更新字符串直到时间线程返回
多线程是解决方案。在基本级别,使用 std::cin
的 C++ 控制台应用程序仅在输入时更新(正如我和 Christian Hackl 所指出的),因此如果没有线程,我想做的事情是不可能的。
我知道这个问题已经很老了,但我希望这个答案能为其他新手节省大量时间在网上搜索不存在的答案!
以下是您如何使用线程在 C++17 中获得您想要的非常接近的近似值。唯一的小问题是用户在时间限制后仍然可以输入,只是不会被保存。
#include <atomic>
#include <chrono>
#include <iostream>
#include <istream>
#include <mutex>
#include <ostream>
#include <string>
#include <thread>
std::atomic_bool done = false;
std::mutex cout_mutex{};
void Timing(std::chrono::seconds length) {
auto start = std::chrono::steady_clock::now();
auto end = start + length;
auto now = std::chrono::steady_clock::now();
while(now < end) {
now = std::chrono::steady_clock::now();
done = false;
}
done = true;
{
std::scoped_lock<std::mutex> lock(cout_mutex);
std::cout << "\nTime's up! Any unsaved input will be lost." << std::endl;
}
}
int main() {
std::string str{};
std::string app{};
using namespace std::literals::chrono_literals;
//This can be any duration you want.
std::thread t = std::thread(Timing, 30s);
t.detach();
while(!done) {
std::getline(std::cin, str);
if(!done) {
app.append(str + '\n');
}
}
std::cout << app;
}