어떻게 리눅스에서 즉시 키 스트로크를 캡처 할 수 있습니까?[중복]
문제
가능한 중복:
리눅스에서 게치()와 게치()에 해당하는 것은 무엇입니까?
나는 리눅스 프로그래밍에 초보자입니다.:-)
난 그냥 내 프로그램(사용 C 언어)는 리눅스에서 모든 단일 키 스트로크를 즉시 캡처 한 다음 에코할지 여부를 결정하고 텔넷처럼 표시하는 방법을 결정할 수 있습니다.
예를 들어,사용자가'에이'를 치면 프로그램이'비'를 표시하기를 원합니다.
그것은 재미 있고 쓸모없는 소리.나는 그것에 대해 단지 궁금합니다.
해결책
기본적으로 즉시 정의하는 방법에 크게 의존합니다.
여기에 두 가지 작업이 있습니다.첫 번째는 대부분의 입력 라이브러리에 내장된 일반 키 반향을 비활성화하는 것입니다.두 번째는 이전 문자 대신 새로운 문자를 인쇄하는 것입니다.
의사 코드에서
echo(off);
while (capturing && charIsAvailable()) {
c = readOneChar();
if (c == '\n') {
capturing = false;
}
printf("%c", c++);
}
echo(on);
키를 누르는 것을 캡처하기 위해 통신하는 여러 시스템이 있습니다.
- 키보드
- (아마도)
- 인터럽트 처리기
- 운영 체제
- 윈도우 서버 프로세스
- 초점이있는 엑스"창".
마지막 단계는 엑스 서버에서 이벤트를 캡처하고 처리하는 연속 루프를 실행하는 프로그램으로 수행됩니다.당신이 특정 방법으로이 프로그램을 확장하고 싶다면(키를 누를 시간의 길이를 얻을)당신은 당신이 정말로 완전히"요리"문자를 수신 할 수 없다는 것을 의미"원시"키보드 이벤트를 원하는 다른 프로그램을 말할 필요가있다.그 결과,당신은 어떤 키가 위아래로,그리고 얼마나 오래 있는지 추적해야 할 것이고,당신의 프로그램에서 모든 이상한 메타 키 동작을 처리해야 할 것입니다. 시프트 다운 등).
또한 이벤트를 줄 지향 청크(줄 이벤트)또는 문자 지향 청크(문자 이벤트)로 수신할지 여부를 제어하는 표준 및 비 표준과 같이 고려해야 할 다른 처리 모드가 있습니다.다시 말하지만,이것은 업스트림 프로그램이 다운스트림 클라이언트의 요구 사항을 인식하도록 해야하기 때문에 다소 복잡합니다.
이제 환경에 대한 아이디어를 얻었으므로 문자 출력을 억제하는 데 필요한 실제 코드를 다시 살펴 보겠습니다.
// define a terminal configuration data structure
struct termios term;
// copy the stdin terminal configuration into term
tcgetattr( fileno(stdin), &term );
// turn off Canonical processing in term
term.c_lflag &= ~ICANON;
// turn off screen echo in term
term.c_lflag &= ~ECHO;
// set the terminal configuration for stdin according to term, now
tcsetattr( fileno(stdin), TCSANOW, &term);
(fetch characters here, use printf to show whatever you like)
// turn on Canonical processing in term
term.c_lflag |= ICANON;
// turn on screen echo in term
term.c_lflag |= ECHO;
// set the terminal configuration for stdin according to term, now
tcsetattr( fileno(stdin), TCSANOW, &term);
심지어 이것은 즉각적인 것이 아닙니다.즉시 얻으려면,당신은 결국 커널 모듈(여전히 스위치가 실제로 닫히는 순간으로 즉각적인되지 않습니다 키보드 마이크로 컨트롤러만큼 즉각적인되지 않습니다)를 의미 소스에 가까이해야합니다.소스와 대상 사이에 충분한 항목이 있으면 결국 차이를 알 수 있습니다.그러나 실제로이 코드는 성능과 유연성 사이의 최상의 트레이드 오프를 찾는 사람들에 의해 많이 작업되었습니다.
다른 팁
에드윈 버크 훌륭한 대답을 제공했습니다.여기 또 다른 대안이 있습니다. ncurses
그런 것들을 좀 더 쉽게 만들고 거의 모든 리눅스 배포판 및 기타 유닉스 변종에서 지원됩니다.
#include <ncurses.h>
int main(int argc, char *argv[])
{
int ch,c;
initscr();
cbreak();
noecho();
while( ch != 'q')
{
switch( c = getch() )
{
case 'a':
ch = 'b';
break;
case 'b':
ch = 'c';
break;
case 'c':
ch = 'd';
break;
default:
ch = c;
break;
}
printw("%c",ch);
}
endwin();
return(0);
}
코드를 사용하여 컴파일하십시오.쨩챌쨔챈쨀
그리고 여기에 몇 가지 지원 링크가 있습니다:
이 코드는 인터넷에서 찾을 수 있으며 kermi3
에서 씨 보드
#include <termios.h>
#include <unistd.h>
int mygetch(void)
{
struct termios oldt,newt;
int ch;
tcgetattr( STDIN_FILENO, &oldt );
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newt );
ch = getchar();
tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
return ch;
}
편집: 물론 당신 문 를 고 싶 경 고 스 값 변경 char
대신 int
과잉 일 수 있지만 다음과 같은 게임 라이브러리를 사용할 수 있습니다 2015 년 그것을 달성하기 위해.