我永远不会记得我是如何做到这一点的,因为它对我来说很少出现。但在C或C++中,从标准输入中读取字符而不等待换行(按Enter)的最佳方式是什么。从标准输入捕获字符而不等待输入被按下
理想情况下,它不会将输入字符回显到屏幕。我只想捕获击出控制台屏幕的击键。
我永远不会记得我是如何做到这一点的,因为它对我来说很少出现。但在C或C++中,从标准输入中读取字符而不等待换行(按Enter)的最佳方式是什么。从标准输入捕获字符而不等待输入被按下
理想情况下,它不会将输入字符回显到屏幕。我只想捕获击出控制台屏幕的击键。
这在纯C++中是不可能移植的,因为它太依赖于可能与stdin连接的终端(它们通常是线路缓冲)。但是,您可以使用以下库:
_getch()
为您提供一个角色,而无需等待输入密钥。我不是一个频繁的Windows开发人员,但我看到我的同学只包括conio.h
并使用它。请参阅维基百科的conio.h。它列出了getch
,它在Visual C++中声明为不赞成使用。getch
函数。 (尝试man getch
查看其联机帮助页)。请参阅维基百科的Curses。如果您的目标是跨平台兼容性,我建议您使用curses。也就是说,我确定有一些函数可以用来关闭行缓冲(我相信这就是所谓的“原始模式”,而不是“熟化模式”(查看man stty
))。如果我没有弄错,诅咒会以便携方式为你处理。
请注意,现在`ncurses`是'curses`的推荐变种。 – 2016-05-07 03:04:01
如果你确实需要一个图书馆,那他们是怎么做到的?为了使图书馆你一定要编程它,这意味着任何人都可以编程,所以为什么我们不能编程我们自己需要的库代码?这也将使**这不可能在纯粹的C + +错误 – NathanProgrammer 2017-01-03 09:49:00
@ kid8我不明白 – 2017-01-03 16:51:24
假设Windows,看看ReadConsoleInput函数。
C和C++采用非常抽象的I/O视图,并且没有标准的做你想做的方式。有标准的方法可以从标准输入流中获取字符,如果有任何可以获得的字符,其他任何语言都不会定义其他字符。因此,任何答案都必须是平台特定的,可能不仅取决于操作系统,还取决于软件框架。
这里有一些合理的猜测,但没有办法在不知道目标环境是什么的情况下回答你的问题。
CONIO.H
您需要的功能是:
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
或
Linux下C++实现CONIO.H的 http://sourceforge.net/projects/linux-conioh
如果您使用的是Windows,你可以使用PeekConsoleInput来检测是否有任何输入,
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
DWORD events;
INPUT_RECORD buffer;
PeekConsoleInput(handle, &buffer, 1, &events);
然后使用ReadConsoleInput“消费”输入字符..
PeekConsoleInput(handle, &buffer, 1, &events);
if(events > 0)
{
ReadConsoleInput(handle, &buffer, 1, &events);
return buffer.Event.KeyEvent.wVirtualKeyCode;
}
else return 0
说实话这是来自我的一些旧代码,所以你必须用它来摆弄一下。
虽然很酷的事情是它读取输入时没有提示任何内容,所以字符根本不显示。
以下是从提取的解决方案专家C编程:深度秘密,它应该在SVr4上工作。它使用stty和ioctl。
#include <sys/filio.h>
int kbhit()
{
int i;
ioctl(0, FIONREAD, &i);
return i; /* return a count of chars available to read */
}
main()
{
int i = 0;
intc='';
system("stty raw -echo");
printf("enter 'q' to quit \n");
for (;c!='q';i++) {
if (kbhit()) {
c=getchar();
printf("\n got %c, on iteration %d",c, i);
}
}
system("stty cooked echo");
}
我发现这在另一个论坛上,同时寻找解决同样的问题。我从我发现的内容中修改了一下。它效果很好。我正在运行OS X,因此如果您运行的是Microsoft,则需要找到正确的system()命令切换到raw和cooked模式。
#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;
}
在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);
}
基本上你必须关闭典型模式(和回声模式,以抑制呼应)。
#include <conio.h>
if (kbhit() != 0) {
cout << getch() << endl;
}
这使用kbhit()
检查是否被按下了键盘,并使用getch()
来获取被按下的字符。
您可以使用SDL(Simple DirectMedia Library)轻松转换,尽管我怀疑您可能不喜欢它的行为。当我尝试它时,我不得不让SDL创建一个新的视频窗口(尽管我不需要它用于我的程序),并让此窗口“抓住”几乎所有的键盘和鼠标输入(这对我的使用来说是可以的,但可以在其他情况下令人讨厌或不可行)。我怀疑它是过度的,不值得这样做,除非完全的可移植性是必须的 - 否则尝试其他建议的解决方案之一。
顺便说一句,如果你喜欢这样,这将分别为你提供按键和发布事件。
我一直想要一个循环来读取我的输入,而不按回车键。 这为我工作。
#include<stdio.h>
main()
{
char ch;
system("stty raw");//seting the terminal in raw mode
while(1)
{
ch=getchar();
if(ch=='~'){ //terminate or come out of raw mode on "~" pressed
system("stty cooked");
//while(1);//you may still run the code
exit(0); //or terminate
}
printf("you pressed %c\n ",ch); //write rest code here
}
}
为我工作在Windows上:
#include <conio.h>
char c = _getch();
我用的kbhit(),看是否有烧焦存在,然后的getchar()读取数据。 在窗口上,您可以使用“conio.h”。在Linux上,你将不得不实现你自己的kbhit()。
见下面的代码:
// 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;
}
你在Windows或不呢? – hasen 2009-01-08 00:55:46
@adam - 你能否澄清一下:你是否想要一个函数,如果没有可用的字符,它会立即返回,或者一直等待一个按键? – Roddy 2009-01-08 09:47:30
@Roddy - 我想要一个总是等待一个按键的功能。 – Adam 2009-05-28 04:52:54