C++ 从标准输入捕获字符,无需等待按enter键
我永远记不起我是怎么做到的,因为我很少想到这一点。但是在C或C++中,从标准输入中读取字符的最好方法是不等待换行(按下回车)。C++ 从标准输入捕获字符,无需等待按enter键,c++,c,inputstream,C++,C,Inputstream,我永远记不起我是怎么做到的,因为我很少想到这一点。但是在C或C++中,从标准输入中读取字符的最好方法是不等待换行(按下回车)。 理想情况下,它不会将输入字符回显到屏幕上。我只想捕获击键而不影响控制台屏幕。 在纯C++中,这是不可能的,因为它太依赖于与“代码”> STDIN < /代码>连接的终端(它们通常是行缓冲的)。但是,您可以使用库进行以下操作: conio可用于Windows编译器。使用\u getch()函数为您提供一个字符,而无需等待回车键。我不是一个经常使用Windows的开发人员,
理想情况下,它不会将输入字符回显到屏幕上。我只想捕获击键而不影响控制台屏幕。 在纯C++中,这是不可能的,因为它太依赖于与“代码”> STDIN < /代码>连接的终端(它们通常是行缓冲的)。但是,您可以使用库进行以下操作:
\u getch()
函数为您提供一个字符,而无需等待回车键。我不是一个经常使用Windows的开发人员,但我看到我的同学只使用了
。见维基百科。它列出了getch()
函数。(尝试mangetch
查看其手册页)。见维基百科如果你想实现跨平台兼容性,我建议你使用诅咒。这就是说,我确信有一些函数可以用来关闭缓存线(我认为这叫做“原始模式”,而不是“熟食模式”——查看
manstty
)。如果我没弄错的话,诅咒会以便携的方式为你处理 >假设Windows,请参阅<强> RealCuloSealEng/<强>函数。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.
利科尼奥
或
Linux C++的CONIO.H实现
最接近便携式的方法是使用库将终端置于“cbreak模式”。API是巨大的;你最想要的常规是
和initscr
endwin
和cbreak
nocbreak
getch
祝你好运 如果您在windows上,您可以使用来检测是否有任何输入
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编程中提取的解决方案:Deep Secrets,它应该可以在SVr4上工作。它使用stty和ioctl
#包括
int kbhit()
{
int i;
ioctl(0、FIONREAD和i);
return i;/*返回可读取的字符数*/
}
main()
{
int i=0;
intc='';
系统(“stty原始回波”);
printf(“输入'q'退出\n”);
for(;c!='q';i++){
if(kbhit()){
c=getchar();
printf(“\n在迭代%d时得到%c”,c,i);
}
}
系统(“stty-echo”);
}
我在另一个论坛上发现了这个问题,当时我正在寻找解决同样问题的方法。根据我的发现,我对它做了一些修改。它工作得很好。我运行的是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;
}
#包括
#包括
使用名称空间std;
int main(){
//输出提示
cout在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);
}
#包括
#包括
char getch(){
char-buf=0;
结构termios old={0};
if(tcgetattr(0,&old)<0)
perror(“tcSetttr()”);
old.c_lflag&=~ICANON;
old.c_lflag&=~ECHO;
old.c_cc[VMIN]=1;
old.c_cc[VTIME]=0;
if(tcsetattr(0、TCSANOW和old)<0)
佩罗尔(“tcsetattr ICANON”);
如果(读取(0,&buf,1)<0)
perror(“read()”);
old.c|lflag |=ICANON;
old.c|lflag |=回声;
if(tcsetattr(0、TCSADRAIN和old)<0)
佩罗尔(“tcsetattr~ICANON”);
返回(buf);
}
基本上,您必须关闭规范模式(和回音模式以抑制回音)。#包括
如果(kbhit()!=0){
你可以使用SDL(简单的DirectMedia库)进行移植,尽管我怀疑你可能不喜欢它的行为。当我尝试它时,我不得不让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
}
}
#包括
main()
{
char ch;
系统(“stty raw”);//在raw模式下设置终端
而(1)
{
ch=getchar();
如果(ch=='~'){//在按下“~”时终止或退出原始模式
系统(“stty熟食”);
//while(1);//您仍然可以运行代码
退出(0);//或终止
}
printf(“您按了%c\n”,ch);//在此处编写rest代码
}
}
在windows上对我有效:
#include <conio.h>
char c = _getch();
#包括
char c=_getch();
我使用kbhit()来查看是否存在字符,然后使用getchar()
#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
}
}
#include <conio.h>
char c = _getch();
// 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;
}
#include <iostream>
#include <ncurses.h>
#include <future>
char get_keyboard_input();
int main(int argc, char *argv[])
{
initscr();
raw();
noecho();
keypad(stdscr,true);
auto f = std::async(std::launch::async, get_keyboard_input);
while (f.wait_for(std::chrono::milliseconds(20)) != std::future_status::ready)
{
// do some work
}
endwin();
std::cout << "returned: " << f.get() << std::endl;
return 0;
}
char get_keyboard_input()
{
char input = '0';
while(input != 'q')
{
input = getch();
}
return input;
}
#include <unistd.h>
#include <termios.h>
#include <stdio.h>
#include <string.h>
char* getStr( char* buffer , int maxRead ) {
int numRead = 0;
char ch;
struct termios old = {0};
struct termios new = {0};
if( tcgetattr( 0 , &old ) < 0 ) perror( "tcgetattr() old settings" );
if( tcgetattr( 0 , &new ) < 0 ) perror( "tcgetaart() new settings" );
cfmakeraw( &new );
if( tcsetattr( 0 , TCSADRAIN , &new ) < 0 ) perror( "tcssetattr makeraw new" );
for( int i = 0 ; i < maxRead ; i++) {
ch = getchar();
switch( ch ) {
case EOF:
case '\n':
case '\r':
goto exit_getStr;
break;
default:
printf( "%1c" , ch );
buffer[ numRead++ ] = ch;
if( numRead >= maxRead ) {
goto exit_getStr;
}
break;
}
}
exit_getStr:
if( tcsetattr( 0 , TCSADRAIN , &old) < 0) perror ("tcsetattr reset to old" );
printf( "\n" );
return buffer;
}
int main( void )
{
const int maxChars = 20;
char stringBuffer[ maxChars+1 ];
memset( stringBuffer , 0 , maxChars+1 ); // initialize to 0
printf( "enter a string: ");
getStr( stringBuffer , maxChars );
printf( "you entered: [%s]\n" , stringBuffer );
}