在控制台中同时输入和输出

时间:2019-03-29 09:27:43

标签: c++ linux multithreading

一个线程,它在控制台上无限打印值,而一个主线程正在从控制台上获取用户输入,但是输入值与该线程的输出混合在一起。

C++ : cin while cout

没有给我提示如何进一步发展,但是我无法提出自己的解决方案(因为我是c ++的新手)。

using namespace std;

mutex mtx;

void foo()
{
    while (1)
    {
        usleep(1000000);
        cout << "Cake\n";
    }
}

int main()
{
    mtx.lock();
    thread t1(foo);
    string x;
    while (true)
    {
        cin >> x;
        edit//fflush(stdin);
        cout << x << "\n";
    }
    t1.join();
    mtx.unlock();
    return 0;
}

编辑1:

好吧,确切地说,我真正想要的是

IN端子(当前

output:cake (which prints every second)
output:cake 
output:cake 
output:cake 
input:hi
output:hicake (still yet to give the enter it echo's the input to console)
output:cake 

我在终端中真正想要的是输入独立于输出

output:cake 
output:cake 
output:cake 
input:hi
output:cake 
output:cake 
input:hi(waiting still for enter)

//and when enter is pressed it should print to the console
output:hi
output:cake

注意:禁用回声没有帮助。

编辑2: 我发布的答案具有数据处理功能,其中并发操作在给定命令上停止。

2 个答案:

答案 0 :(得分:1)

我能够使用所有给定的输入提出解决方案,希望这对某人有帮助。

#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <cstring>
#include <mutex>
#include <string>
#include <chrono>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <thread>
/// reads a character from console without echo.
int getChar()
{
    struct termios oldattr;
    tcgetattr(STDIN_FILENO, &oldattr);
    struct termios newattr = oldattr;
    newattr.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &newattr);
    const int ch = getchar();
    tcsetattr(STDIN_FILENO, TCSANOW, &oldattr);
    return ch;
}

class Console
{
  private:
    // mutex for console I/O
    std::mutex _mtx;
    // current input
    std::string _input;
    // prompt output
    std::string _prompt;

  public:
    Console() {}

    Console(const Console &) = delete;
    Console &operator=(const Console &) = delete;

    std::string read();

    void write(const char *text, size_t size);
    void write(const char *text) { write(text, strlen(text)); }
    void write(const std::string &text) { write(text.c_str(), text.size()); }
};

std::string Console::read()
{
    { // activate prompt
        std::lock_guard<std::mutex> lock(_mtx);
        _prompt = "> ";
        _input.clear();
        std::cout << _prompt << std::flush;
    }
    enum
    {
        Enter = '\n',
        BackSpc = 127
    };
    for (;;)
    {
        switch (int c = getChar())
        {
        case Enter:
        {
            std::lock_guard<std::mutex> lock(_mtx);
            std::string input = _input;
            _prompt.clear();
            _input.clear();
            std::cout << std::endl;
            return input;
        } // unreachable: break;
        case BackSpc:
        {
            std::lock_guard<std::mutex> lock(_mtx);
            if (_input.empty())
                break;
            _input.pop_back();
            std::cout << "\b \b" << std::flush;
        }
        break;
        default:
        {
            if (c < ' ' || c >= '\x7f')
                break;
            std::lock_guard<std::mutex> lock(_mtx);
            _input += c;
            std::cout << (char)c << std::flush;
        }
        break;
        }
    }
}

void Console::write(const char *text, size_t len)
{
    if (!len)
        return;
    bool eol = text[len - 1] == '\n';
    std::lock_guard<std::mutex> lock(_mtx);
    // remove current input echo
    if (size_t size = _prompt.size() + _input.size())
    {
        std::cout
            << std::setfill('\b') << std::setw(size) << ""
            << std::setfill(' ') << std::setw(size) << ""
            << std::setfill('\b') << std::setw(size) << "";
    }
    // print text
    std::cout << text;
    if (!eol)
        std::cout << std::endl;
    // print current input echo
    std::cout << _prompt << _input << std::flush;
}

struct Flags //this flag is shared between both the threads
{
    // flag: true then exit communication thread and main loop
    bool exit;
    // flag: true then start data processing
    bool start;
    // the mini console
    Console console;

    // constructor.
    Flags() : exit(false), start(true) {}
};

void dataProc(Flags &shared)
{
    int i = 0;
    while (!shared.exit)
    {
        while (!shared.start)
        {
            if (shared.exit)
                return;
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
        shared.console.write("Starting data processing.");
        for (;;)
        {
            if (!shared.start || shared.exit)
            {

                shared.console.write("Data processing stopped.");
                while (!shared.start || shared.exit)
                {
                    if (shared.exit)
                        return;
                    std::this_thread::sleep_for(std::chrono::milliseconds(100));
                }
                shared.console.write("Data processing restarted.");
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(250));
            {
                std::ostringstream fmt;
                fmt << "Cake " << ++i;
                shared.console.write(fmt.str());
            }
        }
        shared.console.write("Data processing done.");
        shared.start = false;
    }
}

void processInput(const std::string &input, Flags &shared)
{

    if (strcasecmp(input.c_str(),"start")==0)
        shared.start = true;
    else if (strcasecmp(input.c_str(),"stop")==0)
        shared.start = false;
    else if (strcasecmp(input.c_str(),"exit")==0)
        shared.exit = true;
    else if (input.size())
        shared.console.write("Wrong command!");
}




int main()
{
    Flags shared;
    std::thread threadProc(&dataProc, std::ref(shared));

    while (!shared.exit)
    {
        shared.console.write("Commands accepted: start stop exit");
        std::string input = shared.console.read();
        processInput(input, shared);
    }
    threadProc.join();
    return 0;
}

答案 1 :(得分:0)

我建议锁定mtxcout的{​​{1}}。

cin