回答:
これは、純粋なC ++では移植可能な方法では不可能です。これは、接続される可能性のある使用される端末に大きく依存しているためですstdin
(通常はラインバッファリングされています)。ただし、そのためのライブラリを使用できます。
Windowsコンパイラで利用可能なconio。この_getch()
機能を使用して、Enterキーを待たずにキャラクターにキャラクターを与えます。私は頻繁にWindows開発者ではありませんが、クラスメートがそれをインクルード<conio.h>
して使用するだけであることを見てきました。conio.h
ウィキペディアで参照してください。getch()
Visual C ++で非推奨と宣言されているをリストします。
Linuxで利用できるcurses。Windowsでも互換性のあるcurses実装を利用できます。getch()
機能もあります。(man getch
そのマンページを表示してみてください)。ウィキペディアのCursesを参照してください。
プラットフォーム間の互換性を目指す場合は、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()コマンドを見つけて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;
}
#include <stdlib.h>
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
正直に言うと、これは私が持っている古いコードからのものなので、少しいじる必要があります。
ただし、何もプロンプトを表示せずに入力を読み取るため、文字がまったく表示されないというのはすばらしいことです。
#include <conio.h>
if (kbhit() != 0) {
cout << getch() << endl;
}
これはkbhit()
、キーボードが押されているかどうかを確認getch()
するために使用され、押されている文字を取得するために使用されます。
Windowsを想定して、ReadConsoleInput関数を見てみましょう。
kbhit()を使用してcharが存在するかどうかを確認し、次に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;
}
以下は、SVr4で動作するはずのエキスパートCプログラミング:ディープシークレットから抽出したソリューションです。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");
}
Returnキーを押さなくてもループで入力を読み取る必要がありました。これは私のために働いた。
#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 -lncurses .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;
}
私のWindowsで動作します:
#include <conio.h>
char c = _getch();
SDL(Simple DirectMedia Library)を使用すると、移植性の高い方法で実行できますが、その動作は気に入らないかもしれません。試してみると、SDLで新しいビデオウィンドウを作成し(プログラムには必要ありませんでした)、このウィンドウにほとんどすべてのキーボードとマウスの入力を「グラブ」させる必要がありました(これは私の使用では問題ありませんでしたが)他の状況では煩わしい、または機能しない。完全な移植性が必須でない限り、それはやり過ぎであり、価値がないと思います。それ以外の場合は、他の推奨される解決策の1つを試してください。
ちなみに、これにより、キープレスとリリースのイベントを別々に行うことができます。
これはシステムにシェルアウトしないバージョンです(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 );
}