기존에 getchar를 사용했지만, 동적인 기능 작업을 위해 추가 구현하게 되었고
윈도우, 맥, 리눅스 환경에서 사용자의 키 입력을 감지해서 반영할 수 있도록 하였다.
1. 플랫폼별 키 입력 처리 분리
코드는 운영 체제에 따라 다른 라이브러리를 사용한다
#ifdef _WIN32
#include <conio.h>
#else
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
- 윈도우 환경
- conio.h 라이브러리의 _kbhit와 _getch를 사용.
- 간단히 키 입력을 처리할 수 있는 함수 제공.
- 맥/리눅스 환경
- 키 입력 감지를 위해 termios, unistd.h, fcntl.h를 활용.
- kbhit와 getch를 직접 구현하여 윈도우와 유사한 동작을 재현.
2. kbhit와 getch 함수 구현
2-1. kbhit 함수 구현 (맥/리눅스용)
- kbhit()는 입력된 키가 있는지 여부를 확인하는 함수
- 주요 동작:
- 터미널 속성을 읽어와 캐논 모드(Canonical Mode)를 비활성화.
- 캐논 모드란 입력된 문자열이 Enter 키를 눌러야 처리되는 모드.
- 입력 버퍼를 비동기로 확인하도록 설정 (fcntl 함수 사용).
- 입력이 있으면 해당 문자를 ungetc로 버퍼에 다시 넣고 1 반환.
- 입력이 없으면 0 반환.
- 터미널 속성을 읽어와 캐논 모드(Canonical Mode)를 비활성화.
int kbhit() {
struct termios oldt, newt;
int ch;
int oldf;
tcgetattr(STDIN_FILENO, &oldt); // 현재 터미널 속성 저장
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO); // 캐논 모드 및 에코 비활성화
tcsetattr(STDIN_FILENO, TCSANOW, &newt); // 새 터미널 속성 적용
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
ch = getchar(); // 키 입력 확인
tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // 터미널 속성 복원
fcntl(STDIN_FILENO, F_SETFL, oldf);
if (ch != EOF) {
ungetc(ch, stdin); // 읽은 문자 반환
return 1;
}
return 0;
}
2-2. getch 함수 구현 (맥/리눅스용)
- getch()는 사용자가 입력한 단일 키를 읽어오는 함수
- 주요 동작:
- 터미널 속성을 읽어와 캐논 모드 및 에코를 비활성화.
- 에코(Echo)는 키 입력 시 화면에 출력되는 동작.
- 단일 키 입력을 getchar로 읽는다.
- 터미널 속성을 복원.
- 터미널 속성을 읽어와 캐논 모드 및 에코를 비활성화.
char getch() {
struct termios oldt, newt;
char 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;
}
'개념정복💫 > C 정복' 카테고리의 다른 글
C언어 입력 오류 해결하기: getchar()로 인한 중복 출력 문제 (0) | 2025.01.10 |
---|