我想在OS X上的命令行应用程序中执行以下操作:
while (true) {
    // do some task
    if (user_has_pressed('x')) {
        // break out of the loop and do something different
    }
}为了清楚起见,我不希望程序阻塞等待用户输入。我正在运行一个需要运行几个小时的数值模拟,我想按一个键来打印其进度的详细统计数据,或者中断它并更改参数等。
有一些现有的similar questions,但答案要么建议使用仅支持windows的getch功能,要么将终端切换到不同的输入模式。我不想这样做,因为我需要保留使用ctrl-c中断的能力,而不会弄乱终端。
我不想构建Cocoa应用程序,也不关心跨平台。我只是在寻找在命令行应用程序中做这件事的最简单、最快、最脏的方法,这个应用程序只能在我自己的机器上运行。
我想一种选择是使用ncurses。从简单的阅读来看,这似乎是一个比我想要的更重的选择--但如果有人能发布一个简单的最小示例来完成上面的任务,那将是非常有帮助的。
发布于 2016-12-08 13:46:09
您是否正在寻找以下行为?
   #include <pthread.h>
   #include <iostream>
   static volatile bool keep_running = true;
   static void* userInput_thread(void*)
   {
       while(keep_running) {
           if (std::cin.get() == 'q')
           {
               //! desired user input 'q' received
               keep_running = false;
           }
       }
   }
   int main()
   {
      pthread_t tId;
      (void) pthread_create(&tId, 0, userInput_thread, 0);
      while ( keep_running )
      {
         //! this will run until you press 'q'
      }
      (void) pthread_join(tId, NULL);
      return 0;
   }发布于 2016-12-08 18:36:31
基本思想是使用轮询,但终端通常会在将按键发送到stdin之前等待enter键。因此,我们需要首先禁用规范模式。
#include <poll.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <string.h>
#include <termios.h>
#include <iostream>
void disable_canonical(){
    struct termios old = {0};
    if (tcgetattr(0, &old) < 0)
        perror("tcsetattr()");
    old.c_lflag &= ~ICANON;
    old.c_lflag &= ~ECHO;
    old.c_cc[VMIN] = 1;
    old.c_cc[VTIME] = 0;
    if (tcsetattr(0, TCSANOW, &old) < 0)
        perror("tcsetattr ICANON");
}
void enable_canonical(){
    struct termios old = {0};
    if (tcgetattr(0, &old) < 0)
        perror("tcsetattr()");
    old.c_lflag |= ICANON;
    old.c_lflag |= ECHO;
    old.c_cc[VMIN] = 1;
    old.c_cc[VTIME] = 0;
    if (tcsetattr(0, TCSANOW, &old) < 0)
        perror("tcsetattr ICANON");
}
bool key_pressed(char c){
    struct pollfd fds[1];
    fds[0].fd = 0;
    fds[0].events = POLLIN;
    fds[0].revents = 0;
    int r = poll(fds, 1, 1);
    if(r > 0){
        if(fds[0].revents & POLLIN || fds[0].revents & POLLRDBAND || fds[0].revents & POLLRDNORM){
            char buffer[1024];
            memset(buffer, 0, sizeof(buffer));
            int n = read(0, buffer, sizeof(buffer) -1);
            for(int i = 0; i < n; ++i){
                if(buffer[i] == c){
                    return true;
                }
            }
        }
    }
    return false;
}
int main(){
    disable_canonical();
    while(true){
        if(key_pressed('x')){
            break;
        }
        usleep(500);
        //std::cout << "looping...\n";
    }
    enable_canonical();
}附注: tcsetattr代码是从https://stackoverflow.com/a/912796/573789借用的
发布于 2016-12-08 23:54:54
我相信你正在寻找的是如何在保持程序运行的情况下跳出循环。
您的问题的解决方案之一是使用goto C++关键字。请看下面的代码:
while(true)
{
   char pressKeyToQuit = 'q';
   cin >> pressKeyToQuit;
   if(pressKeyToQuit == 'q')
   {
       goto getOffTheLoop; //to do something different
   }
   getOffTheLoop:
 //do something different
  cout << "Processing!\n";
}希望我能帮上忙!
https://stackoverflow.com/questions/40903215
复制相似问题