Answers:
在纯C ++中这不可能以可移植的方式实现,因为它在很大程度上取决于所使用的连接终端stdin
(它们通常是行缓冲的)。但是,您可以为此使用库:
Windows编译器可用的conio。使用该_getch()
功能可以为您提供一个字符,而无需等待Enter键。我不是Windows的常客,但是我看到我的同学只是在<conio.h>
使用和使用它。参见conio.h
Wikipedia。它列出getch()
,在Visual C ++中声明为已弃用。
适用于Linux的curses。兼容的curses实现也可用于Windows。它还具有getch()
功能。(尝试man getch
查看其联机帮助页)。参见维基百科的诅咒。
如果您希望跨平台兼容,我建议您使用curses。就是说,我确定您可以使用一些功能来关闭行缓冲(我认为这称为“原始模式”,而不是“熟模式”-查看man stty
)。如果我没记错的话,Curses会以一种可移植的方式为您解决这个问题。
ncurses
是的推荐变体curses
。
在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);
}
基本上,您必须关闭规范模式(和回声模式以抑制回声)。
read
。我已经包括两个标题。
error: ‘perror’ was not declared in this scope
编译时,但stdio.h
与一起使用时效果很好unistd.h
。
我在寻求解决相同问题的同时在另一个论坛上找到了这个。我已经对发现的内容进行了一些修改。效果很好。我正在运行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;
}
#include <stdlib.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
要么
conio.h的Linux c ++实现 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
老实说,这是从我的一些旧代码中摘录的,因此您必须对其进行一些调整。
不过,很酷的一点是,它读取输入时不会提示任何内容,因此根本不会显示字符。
我使用kbhit()查看是否存在字符,然后使用getchar()读取数据。在Windows上,您可以使用“ 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;
}
与可移植性最接近的事情是使用该ncurses
库将终端置于“ cbreak模式”。该API巨大;您最想要的例程是
initscr
和 endwin
cbreak
和 nocbreak
getch
祝好运!
以下是从Expert C编程中提取的解决方案:Deep Secrets,应该在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");
}
我一直希望有一个循环来读取我的输入而无需按回车键。这对我有用。
#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
}
}
ncurses提供了一种不错的方法!这也是我的第一篇文章(我记得),因此欢迎提出任何意见。我会感激有用的,但欢迎大家!
编译:g ++ -std = c ++ 11 -pthread -Incurses .cpp -o
#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;
}
这是一个不包含在系统中的版本(在macOS 10.14上编写和测试)
#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 );
}