Как сделать цикл в C++, который запускает счетчик времени и позволяет вводить данные одновременно (неблокирующий ввод пользователя)
Итак, что я пытаюсь сделать, это создать функцию в C++, которая позволяет пользователю вводить что-либо и все в строку в течение заданного промежутка времени (скажем, десять минут (или даже одну)) (и СОХРАНИТЬ все, что они Введено, между прочим. Я пытаюсь разработать игру, чтобы помочь участникам или авторам NaNoWriMo в целом подтолкнуть их к написанию, поэтому необходимо сохранить все необходимое), а затем не допускать добавления ввода. Поначалу это звучало легко, но пять часов поиска в Google показали обратное.
Во-первых, я решил, что могу просто добавлять несколько раз, пока не закончится время или что-то в этом роде. Заметим:
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;
}
Но потом я понял, что цикл не будет проверять условие снова, пока пользователь не нажмет ввод. Надоедливый. То же самое с моим умным представлением о характере. Мне был нужен цикл, который обновлялся с каждым набранным символом (или с каждым вторым разом), независимо от того, сколько времени требуется пользователю для ввода другого.
Итак, тогда я подумала: "Ну, останавливаться на каждом месте и обновлять время должно работать достаточно хорошо, да?"
Именно тогда я начал обнаруживать, что C++ не очень хорошо работает с разбором строк или чтением ввода по мере его поступления. Я думал о добавлении каждого символа, так как с ним довольно легко найти пробел, но он все еще ждет пользователя.
Разочарованный, я задался вопросом, есть ли способ запустить программу одновременно при получении пользовательского ввода, чтобы один раз истекло (используя время (ноль), проходы времени , время (ноль) и вычитая две переменные, чтобы получить прошедшие секунды),
Оказывается, есть! (Я знал, что должно быть, учитывая все компьютерные программы и игры, использующие этот принцип, но я довольно плохо знаком с программированием (я изучил функции в прошлую среду, чтобы дать вам представление), поэтому я не знал, что.)
Первыми функциями, на которые я наткнулся, были проклятия и ncurses, но я быстро обнаружил, что это действительно не было жизнеспособным вариантом для того, что я хочу делать (так как я слышал, что делать довольно забавные вещи для cout).
Затем я наткнулся на kbhit, который распознает, когда клавиши нажимаются на клавиатуре. Этот блог кажется многообещающим, и, вероятно, что я хочу сделать, но я не уверен, на каком языке он написан.,, все, что я знаю, это то, что он не очень хорошо работает с моей C++ IDE. Я понятия не имею, как заставить это играть хорошо с C++.
Итак, повторение того, что я хотел бы:
Цикл, который содержит одновременное выполнение счетчика времени и пользовательского ввода (в строку), но завершается (перестает позволять вводить пользователем дальше в строку), когда время истекает. (Все, не делая смешных вещей с остальной частью моей программы, как ncurses.)
Дополнительно: я использую Windows 8 (проклятие моего существования) и использую Code::Blocks в качестве своей IDE.
Или, если у вас есть, где-то на этот вопрос уже был дан ответ. Это было бы здорово. Мне было бы глупо чувствовать, что я не могу его найти.
(Вот несколько мест, на которые я посмотрел по пути:
Пользовательский ввод во время работы программы
Как читать ввод со стандартного ввода, пока не нажата пробел или табуляция?
Захватывать символы со стандартного ввода, не дожидаясь нажатия клавиши ввода)
(Игра, которую я пытаюсь создать, (которая совсем не очень далеко; я начал играть прошлой ночью), на случай, если вам будет интересно: https://github.com/Rowan-Law/Dungeon-Crawl/blob/master/Source%20Code)
2 ответа
Возможно, вы захотите создать поток для времени, а затем просто обновлять строку до тех пор, пока поток не вернется
Многопоточность - это решение. На базовом уровне консольные приложения C++, использующие std::cin
только обновление при входе (как я и Кристиан Хакл указали), так что без потоков то, что я хотел сделать, невозможно.
Я знаю, что этот вопрос довольно старый, но я надеюсь, что этот ответ сэкономит другим новичкам кучу времени в поисках ответа, которого не существует!
Вот как вы можете получить довольно близкое приближение к тому, что вы хотите в 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;
}