循环获得CIN输入

Loop getting cin input

本文关键字:输入 CIN 循环      更新时间:2023-10-16

可以创建一个while循环:

bool stop_input = false;
while (!stop_input) {
    // Keep getting inputed string
    // Maybe like std::getline(std::cin, str_input);
}

在哪里可以继续循环并将用户输入到控制台的情况下,而无需停止(冻结),例如执行std::cinstd::getline()

我对此有兴趣拥有一个单独的线程,该线程将在等待用户输入某些内容并按ENTER时会做其他事情,然后stop_input将进行真实,并且用户输入将被禁用。

这可能吗?如何?

编辑:

例如,如果我这样做:

void test()
{
    std::string str;
    while (!stop_input) {
        std::getline(std::cin, str);
    }
}

如果我创建了一个像上面的函数,将其编译并启动了调试器,则在std :: getline()第二次被调用时,调试器(程序)将停止。我不想发生这种情况,我希望这个循环能够不断地启动,直到设置stop_input = true;

停止停止

edit2:

主线程:

void someFunction()
{
    string read_input;
    thread get_input = thread(readInput, &read_input);
    while(1) {
        if (buttonPressed(ENTER) {
            stop_input = true;
            get_input.join();
            // Do something with 'read_input' string.
        } else if (buttonPressed(ESC) {
           stop_input = true;
           get_input.join()
           // Discard 'read_input' string and return from this function.
           break;
        }
    }
}

阅读线程:

void readInput(string* input)
{
    while (!stop_input) {
        //Get input
    }
}

P.S。当然,主线程也将在后面做一些工作,与输入阅读无关。

我不确定我是否正确解决了您的问题,但是如果您只想在线程中运行某些内容并允许输入,直到线程中的任务完成,这就是我的方式会这样做:

std::vector< int > v;
std::atomic< bool > stop_input( false );
std::thread t( [ &v, &stop_input ]() 
{
  for( int i = 0; 1'000'000'000 > i; ++i ) v.push_back( i );
  stop_input = true;
} );
std::string m;
while( !stop_input )
{
  std::cin >> m;
  std::cout << "Your message: " << m << std::endl;
}
t.join();

但是,这只会在用户输入终止任务之后终止。它不会"中断" std::cin

这个问题似乎与线程同步有关。

假设stop_input本身已正确同步,例如由于它是ATOMIC_BOOL,当STOP_INPUT设置为true时,这仍然不会阻止您的线程在while loop的身体内部执行此操作。

您想实现什么目标?知道这一点,我们可能能够帮助您找到针对特定问题的适当的线程安全和线程感知的解决方案:)

您是说您有两个线程,一个等待用户输入以唤醒另一个线程?

您创建一个将要照顾循环的线程,然后您的其他线程将使用用户输入并设置BOOL。循环线程不断调用另一个线程以查看是否有用户输入。

这样:

#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
string s;
bool b = false;
void doStuff()
{
    int i = 0;
    while (!b)
    {
        cout << i << ' ';
        ++i;
        this_thread::yield();
        //this_thread::sleep_for(chrono::seconds(1));
    }
    cout << "you wrote: " << s << endl;
}
int main()
{
    thread t(doStuff);
    char c;
    while ((c = cin.get()) != 'n')
        s += c;
    b = true;
    t.join();
}

睡眠和屈服自动阻止线程,并调用另一个可用的线程。get()也会自动阻止其线程。如果您想要非阻滞的东西,那可能是OS依赖的...

编辑:

您可以分离线程,使其独立执行,然后在访问它们之前锁定共享资源。

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
mutex m;
string s;
bool stopInput = false;
char c = 0;
void readInput()
{
    while (!stopInput)
    {
        m.lock();
        c = cin.get();
        s += c;
        m.unlock();
    }
}
int main()
{
    thread t(readInput);
    t.detach();
    while (true)
    {
        m.lock();
        if (isEnter(c))
        {
            stopInput = true;
            cout << "Input: " << s << endl;
            break;
        }
        else if (isEscape(c))
        {
            stopInput = true;
            break;
        }
        m.unlock();
    }
}

可以让 getline(或 cin.getcin.peek等)在单独的线程中与" exit" - 可变性(如" stop_input")一起运行(请参见下面的示例)。

请注意,设置stop_input=true显然不会中断getline(或cin.getcin.peek,...)。进一步注意,在像while (!stop_input) { std::getline(std::cin, str); ... }这样的循环中,主线程不太可能在重新输入循环之前设置stop_input=true。因此,在用户输入值后,主线程可能无法立即停止输入。在循环可以对stop_input的任何更改做出反应之前,将再次输入getline

也应该进一步注意其他线程也不使用getline,因为 - 至少据我所知 - 它不是线程的安全。

#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
bool stop_input = false;
std::queue<std::string> commandQueue;
std::mutex commandQueueMutex;
void getLineUntilInputStopped()
{
    std::string str;
    while (!stop_input) {
        std::getline(std::cin, str);
        if (str == "stopinput")
            stop_input = true;
        commandQueueMutex.lock();
        commandQueue.push(str);
        commandQueueMutex.unlock();
    }
    std::cout << "Listening on input stopped.";
}

int main(int argc, const char * argv[]) {
    std::thread t(getLineUntilInputStopped);
    t.detach();
    bool exit = false;
    while (!exit)
    {
        std::string command = "";
        commandQueueMutex.lock();
        if (commandQueue.size() > 0)
        {
            command = commandQueue.front();
            commandQueue.pop();
        }
        commandQueueMutex.unlock();
        if (command.size() > 0)
        {
            if (command == "exit")
            {
                exit = true;
                std::cout << "exit program.";
            }
            else
            {
                std::cout << "command '" << command << "' entered.";
            }
        }
        else
        {
            std::cout << "in the meanwhile do something elsen";
            std::this_thread::sleep_for (std::chrono::seconds(3));
        }
    }
    return 0;
}