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

2024-01-01

一个线程将值无限地打印到控制台,另一个主线程从控制台获取用户输入,但输入值与该线程的输出混合。

C++:cin 同时 cout https://stackoverflow.com/questions/27650706/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;
}

edit 1:

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

输入端子(目前)

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: 我发布的答案有数据处理,其中并发操作在给定的命令上停止。


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

#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;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在控制台中同时输入和输出 的相关文章

  • 为什么opencv videowriter这么慢?

    你好 stackoverflow 社区 我有一个棘手的问题 我需要你的帮助来了解这里发生了什么 我的程序从视频采集卡 Blackmagic 捕获帧 到目前为止 它工作得很好 同时我用 opencv cv imshow 显示捕获的图像 它也工
  • Android NDK C++“wstring”支持

    我有用 C 编写的源代码 lib 现在我想在 Android NDK 项目 NDK 6 中编译并使用相同的源代码 lib 我能够编译大多数 C 文件 除了基于 std wstring 的功能 在 Application mk 中 当我指定时
  • 使用不带参数的 Split() 时,默认分隔符是什么?

    所以我看了看String Split 今天 C 中的方法 我意识到你也可以向它传递零参数 这是我从未考虑过的 使用时默认的分隔符是什么Split 没有任何参数 如果没有值 则为空白 来源自here https msdn microsoft
  • Java:使用 Java.util.concurrent 线程访问读取线程串行端口

    我正在尝试编写一个 Java 串行设备驱动程序并想使用 对我来说是新的 java util concurrent包裹 我有一种发送数据包然后等待 ACK 的方法 我打算有炭 接收在不同的线程中运行 如果接收线程收到 ACK 它应该使用发送数
  • 返回 int& 的函数[重复]

    这个问题在这里已经有答案了 我在网上查了一下发现一篇试图解释的文章std move和右值 http thbecker net articles rvalue references section 01 html并发现了一些我实在无法掌握的东
  • 如何使用汇编获取BIOS时间?

    我正在从头开始实现一个小型操作系统 用于教育目的 现在 我想使用汇编来获取 BIOS 时间 我对此进行了很多搜索 但找不到任何代码示例来执行此操作 如果有人可以提供任何参考或代码示例或与此相关的任何内容 我将非常感激 See 时钟中断 1a
  • 如何将字节块读入结构体

    我有一个需要处理的资源文件 它包含一组文件 首先 资源文件列出了其中包含的所有文件 以及一些其他数据 例如在此结构中 struct FileEntry byte Value1 char Filename 12 byte Value2 byt
  • 特定设备的不同字体大小

    我目前正在开发通用应用程序 我需要分别处理移动设备和桌面的文本框字体大小 我找到了一些方法 但都不能解决问题 使用 VisualStateManager 和 StateTrigger 为例
  • Microsoft.Graph - 如何从具有不同用户名的共享邮箱发送?

    我目前正在将使用 SMTP 的服务代码移植到 Office 365 通过 SMTP 我可以使用 发件人 字段在来自共享收件箱的邮件上设置不同的用户名 同时保留共享电子邮箱地址 这似乎无法通过 Office 365 运行 其工艺流程为 客户填
  • 使用scanf()时如何区分整数和字符

    我只是使用该功能scanf 代码如下 scanf d a printf d a 当我输入1时 它会像我想要的那样打印1 但即使我输入 1a 它也会像以前一样打印 1 当用户输入非整数时 例如 2 3 12ab 1 a 我想向用户显示 输入整
  • 不要声明只读可变引用类型 - 为什么不呢?

    我一直在阅读这个问题 https stackoverflow com questions 2274412 immutable readonly reference types fxcop violation do not declare r
  • C# 中处理 SQL 死锁的模式?

    我正在用 C 编写一个访问 SQL Server 2005 数据库的应用程序 该应用程序是数据库密集型的 即使我尝试优化所有访问 设置适当的索引等 我预计迟早会遇到死锁 我知道为什么会发生数据库死锁 但我怀疑我能否在某个时候发布不发生死锁的
  • 如何不在类中实现接口的功能?

    面试时面试官问了我以下问题 但我不知道这个问题的答案是什么 请帮忙 如果我不想 我必须做什么 在我的类中实现一个函数 在接口中声明为 由我班实施 Edited 我正在使用 NET 和 C 如果有人可以提供 C 示例代码示例 那就太好了 Th
  • 是什么原因导致 Linq 错误:此方法无法转换为存储表达式?

    我有一堆具有相同 select 语句的 Linq to Entity 方法 所以我想我会很聪明 并将其分离到它自己的方法中以减少冗余 但是当我尝试运行代码时 我得到了以下内容错误 该方法不能转化为 商店表达式 这是我创建的方法 public
  • 如何查找哪个 Yocto 项目配方填充图像根文件系统上的特定文件

    我经常与 Yocto 项目合作 一个常见的挑战是确定文件为何 或来自什么配方 包含在 rootfs 中 这有望从构建系统的环境 日志和元数据中得出 理想情况下 一组命令将允许将文件链接回源 即配方 我通常的策略是对元数据执行搜索 例如gre
  • 有没有更好的方法来获取每个项目与谓词匹配的子序列?

    假设我有一个 IEnumerable 例如 2 1 42 0 9 6 5 3 8 我需要获得与谓词匹配的项目的 运行 例如 如果我的谓词是 bool isSmallerThanSix int number 我想得到以下输出 2 1 0 5
  • 微软语音识别速度

    我正在使用微软的语音识别器开发一个小型练习应用程序 对于我正在做的事情来说 我似乎无法让它足够快地识别单个单词 我希望能够正常说话 系统将从我所说的内容中抓取 关键字 并生成一个字符串 目前我正在使用 5 个单词的自定义语法 红 蓝 黄 绿
  • 在 SQL Server 上执行分页的最佳方式是什么?

    我有一个数据库超过200万记录 我需要执行分页以在我的 Web 应用程序上显示 该应用程序每页必须有 10 条记录DataGrid 我已经尝试使用ROW NUMBER 但是这种方式会选择所有 200 万条记录 然后只得到 10 条记录 我也
  • 如何强制执行特定的 UserControl 设计

    我正在编写一个基本用户控件 它将由一堆其他用户控件继承 我需要对所有这些后代控件强制执行某种设计 例如 顶部必须有几个按钮以及一个或两个标签 后代用户控件区域的其余部分可以自由放置任何内容 最初 我认为我可以将一个面板放到 Base Use
  • 如何从函数返回矩阵(二维数组)? (C)

    我创建了一个生成宾果板的函数 我想返回宾果板 正如我没想到的那样 它不起作用 这是函数 int generateBoard int board N M i j fillNum Boolean exists True initilize se

随机推荐