如何在按下键盘时“安全”终止运行中的C++程序?

6
我试图编写一个模拟程序,直到我按下某个键(比如'q'表示退出)才停止运行。然后在我按下该键后,我希望程序继续写入当前正在写入的数据,关闭文件,然后优雅地退出(而不是强制按下ctrl+c来停止程序)。在C++中有没有办法实现这一点?
谢谢

肯定有方法可以做到这一点。你需要想办法跳出模拟循环,但是检测按键将是关键。这个程序将在哪个操作系统上运行? - djdanlib
3
似乎是一个比较广泛的问题。1)如何异步读取密钥?2)如何通知程序关闭?3)如何确保在最终关闭前所有数据都被写入? - Almo
你需要找到操作系统库来执行这个函数。它不是标准的。 - Puppy
这将在Linux或Mac上运行。最好是非操作系统相关的,但如果这是唯一的选择,那么需要Unix兼容的。基本上,我希望有一种方法可以“监听”按键,以便在模拟的每次迭代结束时,它会检查该键是否已被按下,然后调用关闭函数。 - Eddy
@pst:问题没有说明这是针对Linux、Windows还是Mac OS。因此,一般来说根本无法完成。C++标准没有提供任何方法来实现它,但操作系统可以提供更多的设施。在每个系统上实现这个功能的方式都不同。 - LiKao
显示剩余4条评论
1个回答

5

让用户按下CTRL-C,但安装一个信号处理程序来处理它。在信号处理程序中,设置一个全局布尔变量,例如user_wants_to_quit。然后您的模拟循环可以如下所示:

while ( work_to_be_done && !user_wants_to_quit) {
 …
}
// Loop exited, clean up my data

一个完整的POSIX程序(抱歉,如果你期望的是微软Windows系统),包括设置和恢复SIGINT (CTRL-C)处理程序:

#include <iostream>
#include <signal.h>

namespace {
  sig_atomic_t user_wants_to_quit = 0;

  void signal_handler(int) {
    user_wants_to_quit = 1;
  }
}

int main () {

  // Install signal handler
  struct sigaction act;
  struct sigaction oldact;
  act.sa_handler = signal_handler;
  sigemptyset(&act.sa_mask);
  act.sa_flags = 0;
  sigaction(SIGINT, &act, &oldact);


  // Run the sim loop
  int sim_loop_counter = 3;
  while( (sim_loop_counter--) && !user_wants_to_quit) {
    std::cout << "Running sim step " << sim_loop_counter << std::endl;

    // Sim logic goes here. I'll substitute a sleep() for the actual
    // sim logic
    sleep(1);

    std::cout << "Step #" << sim_loop_counter << " is now complete." << std::endl;
  }

  // Restore old signal handler [optional]
  sigaction(SIGINT, &oldact, 0);

  if( user_wants_to_quit ) {
    std::cout << "SIM aborted\n"; 
  } else {
    std::cout << "SIM complete\n";
  }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接