C++ 从标准输入中捕获字符,无需等待按下 Enter 键
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/421860/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Capture characters from standard input without waiting for enter to be pressed
提问by Adam
I can never remember how I do this because it comes up so infrequently for me. But in C or C++, what is the best way to read a character from standard input without waiting for a newline (press enter).
我永远不记得我是如何做到这一点的,因为它对我来说很少出现。但是在 C 或 C++ 中,从标准输入读取字符而不等待换行符的最佳方法是什么(按 Enter)。
Also ideally it wouldn't echo the input character to the screen. I just want to capture keystrokes with out effecting the console screen.
理想情况下,它不会将输入字符回显到屏幕上。我只想在不影响控制台屏幕的情况下捕获击键。
采纳答案by Johannes Schaub - litb
That's not possible in a portable manner in pure C++, because it depends too much on the terminal used that may be connected with stdin
(they are usually line buffered). You can, however use a library for that:
这在纯 C++ 中以可移植的方式是不可能的,因为它太依赖于可能与之连接的所使用的终端stdin
(它们通常是行缓冲的)。但是,您可以为此使用库:
conio available with Windows compilers. Use the
_getch()
function to give you a character without waiting for the Enter key. I'm not a frequent Windows developer, but I've seen my classmates just include<conio.h>
and use it. Seeconio.h
at Wikipedia. It listsgetch()
, which is declared deprecated in Visual C++.curses available for Linux. Compatible curses implementations are available for Windows too. It has also a
getch()
function. (tryman getch
to view its manpage). See Cursesat Wikipedia.
conio 可用于 Windows 编译器。使用该
_getch()
功能可以为您提供一个字符,而无需等待 Enter 键。我不是经常使用 Windows 开发人员,但我看到我的同学只是包含<conio.h>
并使用它。参见conio.h
维基百科。它列出了getch()
在 Visual C++ 中声明已弃用的 。可用于 Linux 的诅咒。兼容的 curses 实现也可用于 Windows。它还有一个
getch()
功能。(尝试man getch
查看其联机帮助页)。参见维基百科的诅咒。
I would recommend you to use curses if you aim for cross platform compatibility. That said, I'm sure there are functions that you can use to switch off line buffering (I believe that's called "raw mode", as opposed to "cooked mode" - look into man stty
). Curses would handle that for you in a portable manner, if I'm not mistaken.
如果您的目标是跨平台兼容性,我会建议您使用curses。也就是说,我确定您可以使用某些功能来关闭离线缓冲(我相信这称为“原始模式”,而不是“熟模式” - 查看man stty
)。如果我没记错的话,Curses 会以一种便携的方式为你处理这个问题。
回答by Johannes Schaub - litb
On Linux (and other unix-like systems) this can be done in following way:
在 Linux(和其他类 Unix 系统)上,这可以通过以下方式完成:
#include <unistd.h>
#include <termios.h>
char getch() {
char buf = 0;
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");
if (read(0, &buf, 1) < 0)
perror ("read()");
old.c_lflag |= ICANON;
old.c_lflag |= ECHO;
if (tcsetattr(0, TCSADRAIN, &old) < 0)
perror ("tcsetattr ~ICANON");
return (buf);
}
Basically you have to turn off canonical mode (and echo mode to suppress echoing).
基本上你必须关闭规范模式(和回声模式来抑制回声)。
回答by cwhiii
I found this on another forum while looking to solve the same problem. I've modified it a bit from what I found. It works great. I'm running OS X, so if you're running Microsoft, you'll need to find the correct system() command to switch to raw and cooked modes.
我在另一个论坛上找到了这个,同时希望解决同样的问题。我已经根据我发现的内容对其进行了一些修改。它工作得很好。我运行的是 OS X,所以如果你运行的是 Microsoft,你需要找到正确的 system() 命令来切换到原始模式和熟模式。
#include <iostream>
#include <stdio.h>
using namespace std;
int main() {
// Output prompt
cout << "Press any key to continue..." << endl;
// Set terminal to raw mode
system("stty raw");
// Wait for single character
char input = getchar();
// Echo input:
cout << "--" << input << "--";
// Reset terminal to normal "cooked" mode
system("stty cooked");
// And we're out of here
return 0;
}
回答by cwhiii
CONIO.H
CONIO.H
the functions you need are:
您需要的功能是:
int getch();
Prototype
int _getch(void);
Description
_getch obtains a character from stdin. Input is unbuffered, and this
routine will return as soon as a character is available without
waiting for a carriage return. The character is not echoed to stdout.
_getch bypasses the normal buffering done by getchar and getc. ungetc
cannot be used with _getch.
Synonym
Function: getch
int kbhit();
Description
Checks if a keyboard key has been pressed but not yet read.
Return Value
Returns a non-zero value if a key was pressed. Otherwise, returns 0.
libconio http://sourceforge.net/projects/libconio
libconio http://sourceforge.net/projects/libconio
or
或者
Linux c++ implementation of conio.h http://sourceforge.net/projects/linux-conioh
conio.h 的 Linux c++ 实现 http://sourceforge.net/projects/linux-conioh
回答by hasen
If you are on windows, you can use PeekConsoleInputto detect if there's any input,
如果你在 windows 上,你可以使用PeekConsoleInput来检测是否有任何输入,
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
DWORD events;
INPUT_RECORD buffer;
PeekConsoleInput( handle, &buffer, 1, &events );
then use ReadConsoleInput to "consume" the input character ..
然后使用 ReadConsoleInput 来“使用”输入字符 ..
PeekConsoleInput(handle, &buffer, 1, &events);
if(events > 0)
{
ReadConsoleInput(handle, &buffer, 1, &events);
return buffer.Event.KeyEvent.wVirtualKeyCode;
}
else return 0
to be honest this is from some old code I have, so you have to fiddle a bit with it.
老实说,这是来自我拥有的一些旧代码,因此您必须对其进行一些处理。
The cool thing though is that it reads input without prompting for anything, so the characters are not displayed at all.
很酷的事情是它在不提示任何内容的情况下读取输入,因此根本不显示字符。
回答by Joseph Dykstra
#include <conio.h>
if (kbhit() != 0) {
cout << getch() << endl;
}
This uses kbhit()
to check if the keyboard is being pressed and uses getch()
to get the character that is being pressed.
这用于kbhit()
检查键盘是否被按下并用于getch()
获取被按下的字符。
回答by Tritium
Assuming Windows, take a look at the ReadConsoleInputfunction.
假设是 Windows,看看ReadConsoleInput函数。
回答by David Thornley
C and C++ take a very abstract view of I/O, and there is no standard way of doing what you want. There are standard ways to get characters from the standard input stream, if there are any to get, and nothing else is defined by either language. Any answer will therefore have to be platform-specific, perhaps depending not only on the operating system but also the software framework.
C 和 C++ 对 I/O 采取了非常抽象的观点,并且没有标准的方法来做你想做的事。有从标准输入流中获取字符的标准方法,如果有的话,任何一种语言都没有定义其他任何东西。因此,任何答案都必须是特定于平台的,可能不仅取决于操作系统,还取决于软件框架。
There's some reasonable guesses here, but there's no way to answer your question without knowing what your target environment is.
这里有一些合理的猜测,但如果不知道您的目标环境是什么,就无法回答您的问题。
回答by Norman Ramsey
回答by ssinfod
I use kbhit() to see if a char is present and then getchar() to read the data. On windows, you can use "conio.h". On linux, you will have to implement your own kbhit().
我使用 kbhit() 查看是否存在字符,然后使用 getchar() 读取数据。在 Windows 上,您可以使用“conio.h”。在 linux 上,您必须实现自己的 kbhit()。
See code below:
见下面的代码:
// kbhit
#include <stdio.h>
#include <sys/ioctl.h> // For FIONREAD
#include <termios.h>
#include <stdbool.h>
int kbhit(void) {
static bool initflag = false;
static const int STDIN = 0;
if (!initflag) {
// Use termios to turn off line buffering
struct termios term;
tcgetattr(STDIN, &term);
term.c_lflag &= ~ICANON;
tcsetattr(STDIN, TCSANOW, &term);
setbuf(stdin, NULL);
initflag = true;
}
int nbbytes;
ioctl(STDIN, FIONREAD, &nbbytes); // 0 is STDIN
return nbbytes;
}
// main
#include <unistd.h>
int main(int argc, char** argv) {
char c;
//setbuf(stdout, NULL); // Optional: No buffering.
//setbuf(stdin, NULL); // Optional: No buffering.
printf("Press key");
while (!kbhit()) {
printf(".");
fflush(stdout);
sleep(1);
}
c = getchar();
printf("\nChar received:%c\n", c);
printf("Done.\n");
return 0;
}