Как сделать цикл в 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;
}
Другие вопросы по тегам