나는 종종 그렇게하지 않기 때문에 내가 이것을 어떻게하는지 기억할 수 없다. 그러나 C 또는 C ++에서 줄 바꿈을 기다리지 않고 표준 입력에서 문자를 읽는 가장 좋은 방법은 무엇입니까?
또한 입력 문자를 화면에 에코하지 않는 것이 이상적입니다. 콘솔 화면에 영향을 미치지 않고 키 입력을 캡처하고 싶습니다.
나는 종종 그렇게하지 않기 때문에 내가 이것을 어떻게하는지 기억할 수 없다. 그러나 C 또는 C ++에서 줄 바꿈을 기다리지 않고 표준 입력에서 문자를 읽는 가장 좋은 방법은 무엇입니까?
또한 입력 문자를 화면에 에코하지 않는 것이 이상적입니다. 콘솔 화면에 영향을 미치지 않고 키 입력을 캡처하고 싶습니다.
답변:
순수한 C ++에서는 이식 가능한 방식으로 사용할 수 없습니다. 연결 된 터미널에 너무 많이 의존하기 때문에 stdin
(일반적으로 라인 버퍼링 됨). 그러나이를 위해 라이브러리를 사용할 수 있습니다.
conio는 Windows 컴파일러에서 사용 가능합니다. 이 _getch()
기능을 사용하여 Enter 키를 기다리지 않고 문자를 제공하십시오. 나는 빈번한 Windows 개발자는 아니지만, 반 친구들이 그것을 포함 <conio.h>
하고 사용하는 것을 보았습니다 . conio.h
Wikipedia를 참조하십시오 . 그것은 나열 getch()
Visual C ++에서 사용되지 선언된다.
Linux에서 사용할 수있는 저주. Windows에서도 호환되는 curses 구현을 사용할 수 있습니다. getch()
기능 도 있습니다. ( man getch
맨 페이지를 보려고 시도하십시오 ). Wikipedia의 저주 를 참조하십시오 .
크로스 플랫폼 호환성을 목표로하는 경우 curses를 사용하는 것이 좋습니다. 즉, 라인 버퍼링을 해제하는 데 사용할 수있는 기능이 있다고 확신 man stty
합니다. 내가 실수하지 않으면 저주는 휴대용 방식으로 당신을 위해 그것을 처리 할 것입니다.
ncurses
은의 권장 변형입니다 curses
.
Linux (및 기타 유닉스 계열 시스템)에서는 다음과 같은 방법으로 수행 할 수 있습니다.
#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
창문에 있다면 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"를 사용할 수 있습니다. 리눅스에서는 자신의 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;
}
다음은 Expert C Programming : 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 -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();
다음은 시스템에 셸되지 않는 버전입니다 (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 );
}