【问题标题】:C++ cin keypress eventC++ cin 按键事件
【发布时间】:2012-08-12 20:02:45
【问题描述】:

我相信这是一个非常简单的问题,但我找不到简单的答案。我有一个无限循环,例如while(1)for(;;),我需要在按键时打破循环。最简单的方法是什么?

P.S.:我不能使用 getchcin.ignorecin.get,因为它会停止循环。

【问题讨论】:

  • 如果你告诉我们更多的上下文,我很确定我们可以想出一些东西。否则,您将需要使用一些特定于操作系统的东西。
  • 服务器上的一些 linux。我不知道,哪个发行版。 std中没有跨平台的解决方案吗?

标签: c++ keypress infinite-loop break onkeypress


【解决方案1】:

嗯,你想要的是异步输入。 cin提供的所有方法等待进入。为此,您必须使用系统特定的功能,或者使用可以为您完成此操作的库。

您需要做的不仅是在 while 循环中处理您的逻辑,还要从您的操作系统的消息管道中侦听。如果你想了解更多关于那个的信息,请发表评论。

编辑:还有另一种方法,但我不推荐它,因为我相信它可能是不可移植的。以下代码在VS2012RC下编译运行。

#include<iostream>
#include<conio.h>

using namespace std;

int main()
{
   cout << "Enter a character";
   getch();
}

【讨论】:

  • 哇,我认为像按键这样简单的东西将在所有平台上以相同的方式实现。我知道 cin 只是一些流,但我仍然认为会有一个跨平台的解决方案。我将在有一些 linux 的服务器上运行它,但我不知道哪个发行版。我还记得,很久以前我在学校里用 Pascal 做某事时,只有一个事件“keypressed”,所以我简单地写了“repeat until keypressed;”。所以在 C++ 中 while(?) {}?
  • 嗯,Linux 上的消息处理相当简单,我相信。您只需运行一到两次操作系统调用来轮询消息,然后在您不想执行任何操作时运行默认操作。本质区别在于,使用流时,您会得到char 输入的字符,而使用操作系统调用时,您会得到 Key Up/Down 事件,您可以将修饰键用作“普通键”(shift、ctrl 等)
  • 关于“帕斯卡”的问题,看conio.h/getch()函数。我可以根据您使用的编译器对它进行不同的命名,但实际上它通常是提供的。 (可以是getchgetchar 或其他)
  • 我什至不能在编译器中使用 conio.h。
  • 不是老头吗?顺便说一句,我使用几乎最新的 G++ 编译器。
【解决方案2】:

以下是使用kbhit() 并具有无限循环的Windows 控制台代码。 但是如果键盘被击中,它会打破循环并退出。 如果你有 &lt;conio.h&gt; ,试试这个:

#include <iostream> 
#include <conio.h>

using namespace std;


int main()
{


   while (1)
   { 
     if (kbhit()) break;

   }

  return 0;
}

【讨论】:

  • 所以我可以在循环结束时使用:"if(kbhit()) break;"?
  • 在while循环中,添加if(kbhit()) break;
  • 编译器找不到 conio.h 或只是 conio。
【解决方案3】:

C++ 中没有“键盘”。您只有一个不透明的输入数据流,您的终端偶尔会使用自己的键盘输入填充该数据流。这几乎总是一个缓冲的、可编辑的逐行输入,因此您无法知道何时按下了任何给定的键。

您需要一种特定于平台的方法来直接与较低级别的终端通信。 ncurses 是一个这样的库,相当广泛和可移植的(存在兼容的 Windows 变体)。 SDL 和 Allegro 等便携式图形应用程序框架也提供原始键盘处理。

【讨论】:

  • 天啊,std 中一定有一个简单的解决方案。例如,在循环的每次迭代中,从该输入数据流(cin?)中获取数据并检查它是否为空,但我不知道该怎么做......
  • 不,流不允许这样做。看看我的回答下面的评论。
  • @LukasSalich:这样看:如果您的 C++ 应用程序会收到每个按键事件,那么它就是负责的。例如,您的 C++ 程序必须处理行编辑,这反过来又需要对终端 API 有深入的了解,以便您可以例如按退格键删除一个字符。为了保护这种负担的平均 C++ 应用程序/运行时,这不是标准的一部分。但是,有许多库可以做到这一点,例如 conio、ncurses 等;这意味着您可以选择适合您需求的任何库最佳。 C/C++ 的一大优点。
【解决方案4】:

这会检查“左箭头”是否被按下:

GetKeyState(VK_LEFT)

这也不等待任何东西。只需检查一些标志。

winuser.h 中定义的其他一些键:

#define VK_NUMPAD0        0x60
#define VK_NUMPAD1        0x61
#define VK_NUMPAD2        0x62
#define VK_NUMPAD3        0x63
#define VK_NUMPAD4        0x64
#define VK_NUMPAD5        0x65
#define VK_NUMPAD6        0x66
#define VK_NUMPAD7        0x67
#define VK_NUMPAD8        0x68
#define VK_NUMPAD9        0x69

#define VK_CLEAR          0x0C
#define VK_RETURN         0x0D

#define VK_SHIFT          0x10
#define VK_CONTROL        0x11
#define VK_MENU           0x12
#define VK_PAUSE          0x13
#define VK_CAPITAL        0x14

#define VK_KANA           0x15
#define VK_HANGEUL        0x15  /* old name - should be here for compatibility */
#define VK_HANGUL         0x15
#define VK_JUNJA          0x17
#define VK_FINAL          0x18
#define VK_HANJA          0x19
#define VK_KANJI          0x19

#define VK_ESCAPE         0x1B

#define VK_CONVERT        0x1C
#define VK_NONCONVERT     0x1D
#define VK_ACCEPT         0x1E
#define VK_MODECHANGE     0x1F

#define VK_SPACE          0x20
#define VK_PRIOR          0x21
#define VK_NEXT           0x22
#define VK_END            0x23
#define VK_HOME           0x24
#define VK_LEFT           0x25
#define VK_UP             0x26
#define VK_RIGHT          0x27
#define VK_DOWN           0x28
#define VK_SELECT         0x29
#define VK_PRINT          0x2A
#define VK_EXECUTE        0x2B
#define VK_SNAPSHOT       0x2C
#define VK_INSERT         0x2D
#define VK_DELETE         0x2E
#define VK_HELP           0x2F

winuser.h 必须包含在 windows.h 中

【讨论】:

  • 这仅适用于 Windows。它不是跨平台的(它没有写在问题中,但是阅读 cmets,您会明白,问题是针对标准的。
  • 对不起,我在构建答案时没有阅读 cmets ^^
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多