【问题标题】:Stopping an infinite loop in C++ when key is pressed [duplicate]按下键时停止C++中的无限循环[重复]
【发布时间】:2014-02-11 17:16:03
【问题描述】:

我有一个程序如下:

#include<iostream>
using namespace std;
int main()
{
    while(true)
    {
        //do some task
        if(Any_key_pressed)
            break;
    }
return 0;
}

如果按下任何键,如何退出循环。

C++ Compiler: GCC 4.2 and higher
OS: Linux-Mint

谢谢

【问题讨论】:

  • 这将在什么操作系统上运行? 这就是重要的平台特定 API
  • 你需要一个库来处理键盘输入。我个人喜欢OIS。或者你可以使用操作系统提供的任何东西。
  • 使用中断,或者fork一个进程并读取stdin
  • comp.lang.c FAQ 第 19 节讨论了这一点。

标签: c++ linux loops infinite-loop


【解决方案1】:

标准 C++ 不提供执行此操作的方法。您将需要一个特定于平台的 API,它可以告诉您是否按下了某个键(或者可能在标准输入上输入可用)而不会阻塞。这意味着您需要告诉我们您使用的是哪个平台。

【讨论】:

  • Linux系统有什么办法吗?
  • 平台是指操作系统,而不是工具链
【解决方案2】:

试试这个:

#include <iostream>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>

using namespace std;

int kbhit(void)
{
  struct termios oldt, newt;
  int ch;
  int oldf;

  tcgetattr(STDIN_FILENO, &oldt);
  newt = oldt;
  newt.c_lflag &= ~(ICANON | ECHO);
  tcsetattr(STDIN_FILENO, TCSANOW, &newt);
  oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
  fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

  ch = getchar();

  tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
  fcntl(STDIN_FILENO, F_SETFL, oldf);

  if(ch != EOF)
  {
    ungetc(ch, stdin);
    return 1;
  }

  return 0;
}

int main(void)
{

  while(!kbhit());

  cout<<"You pressed "<<(char)getchar();

  return 0;
}

【讨论】:

    【解决方案3】:

    您可以使用 SDL,它(大部分)独立于平台。

    #include<SDL/SDL.h>
    ...
    #include<iostream>
    using namespace std;
    int main()
    {
        while(true)
        {
            //do some task
            SDL_Event event
            while(SDL_PollEvent(&event))
            {
                if(event.type==SDL_KEYDOWN)
                {
                    break;
                }
            }
        }
    return 0;
    }
    

    上述代码适用于 Windows、Linux、MacOS 以及许多其他操作系统。 至于如何设置SDL,有tutorial

    【讨论】:

      【解决方案4】:

      你可以使用ncurses

      #include <iostream>
      #include <ncurses.h>
      
      int main ()
      {
          initscr();              // initialize ncurses
          noecho();               // don't print character pressed to end the loop
          curs_set(0);            // don't display cursor
          cbreak();               // don't wait for user to press ENTER after pressing a key
          nodelay(stdscr, TRUE);  // The nodelay option causes getch to be a non-blocking call. If no input is ready, getch returns ERR. If disabled (bf is FALSE), getch waits until a key is pressed.
      
          int ch;
      
          printw("Let's play a game! Press any key to quit.\n\n");
      
          while (1) {                       // infinite loop
              if ((ch = getch()) == ERR) {  // check to see if no key has been pressed
                  printw(".");              // if no key has been pressed do this stuff
                  usleep(1000);
                  refresh();
              } else {                      // if a key is pressed... 
                  nodelay(stdscr, false);   // reset nodelay()
                  clear();                  // clear the screen
                  break;                    // exit loop
              }
          }
      
          mvprintw(LINES/2, COLS/2-9, "Game Over");
          refresh();
          getch();  // wait for character, just so the program doesn't finish and exit before we read "Game Over" 
          endwin(); // terminate ncurses
          return 0;
      }
      

      【讨论】:

      • ncurses 的问题在于它占据了整个屏幕,这对于只想轮询键盘输入的程序来说太过分了。顺便说一句,这个程序不需要#include &lt;iostream&gt;——但它确实需要#include &lt;unistd.h&gt;(对于usleep)。
      猜你喜欢
      • 2017-05-23
      • 1970-01-01
      • 2023-03-13
      • 2015-02-04
      • 2013-07-27
      • 2017-07-30
      • 1970-01-01
      • 1970-01-01
      • 2012-01-10
      相关资源
      最近更新 更多