首页 > 解决方案 > 如何在 C++ 中解决 ncurses 和 std 输入/输出之间的冲突

问题描述

我正在开发一个多线程应用程序,其中有一个主线程和一个辅助线程。辅助线程必须接受用户的输入并将结果提供给主线程,问题是 std::cin 是一个阻塞函数,这意味着如果主线程停止执行辅助线程由于以下原因不能做同样的事情std::cin. 用户必须输入一些内容才能让程序结束,我想解决这个问题。所以基本上伪代码是这样的:

std::atomic<bool> interrupt(false);

std::string get_input(){

  std::cout << "Insert a new command: ";
  std::string cmd;
  std::cin >> cmd;
  return cmd;

  }

void kill_main_thread(){

  std::this_thread::sleep_for(std::chrono::milliseconds(5000));
  interrupt = true;

  }
int main() {

  std::thread new_thread (kill_main_thread);     // spawn new thread that calls foo()


  while(1) {

      if ( interrupt ) {
          return 0;
      }

      std::future<std::string> fut = std::async(get_input);
      if ( fut.wait_for(std::chrono::seconds(500)) == std::future_status::timeout ){

          std::string cmd = fut.get();

            
           if ( cmd == "close") {...}
            else if ( cmd == "open") {...}
            else {...}

      }

  }
return 0;
  
}

不幸的是,我无法更改程序的执行流程,因此基于之前的问题,我决定使用PDCurses库来getch()允许我创建一个输入非阻塞函数。

std::string input(){

    initscr();
    keypad(stdscr, TRUE);
    nodelay(stdscr, TRUE);
    char ch;
    std::string cmd = "";

    while(!interrupt) {
        if ((ch = getch()) != ERR)
            cmd = cmd + ch;

        if ( ch == '\n') break;
    }
    endwin();
    return cmd;
}

通过这种方式,通过用前面的例子替换这个input函数std::cin,通过将中断设置为 true,我可以停止辅助线程的执行。问题是 PDCurses 与我程序的所有 std::cout 发生冲突,终端不能与标准库正常工作。我找到了三种不同的解决方案来解决这个问题:

1.) 定义一个新终端,我在其中激活 PDCurses 和另一个必须与 std 一起工作的终端。尽管newterm应该创建一个新终端,但此功能不起作用:

    ....
    FILE *f = fopen("/dev/tty", "r+");
    SCREEN *screen = newterm(NULL, f, f);
    set_term(screen);
    refresh();
    ....

2.)getch()通过避免对 PDCurses 进行控制台操作,只使用函数。但我没有找到解决方案。

3.) 以另一种方式定义非阻塞输入函数。

标签: c++multithreadinginputblockingpdcurses

解决方案


推荐阅读