C++ 표준 라이브러리만으로는 개행(Enter)을 기다리지 않고 키 입력을 즉시 읽는 이식 가능한(portable) 방법이 존재하지 않습니다. 운영체제마다 터미널의 동작 방식이 다르기 때문에, 플랫폼별로 다른 접근 방식을 사용해야 합니다.
Windows에서 구현하기 — conio.h의 getch() 함수
Windows에서는 conio(Console I/O) 라이브러리에서 제공하는 getch() 함수를 사용하면 됩니다. 이 함수는 사용자가 누른 문자를 버퍼링 없이 바로 반환해 줍니다.
예제 코드
#include<iostream>
#include<conio.h>
using namespace std;
int main() {
char c;
while(1){ // 무한 루프
c = getch();
cout << c;
}
}위 코드는 사용자가 입력한 문자를 그대로 터미널에 출력합니다. 단, conio.h 헤더는 Windows 전용이므로 이 코드는 Windows 환경에서만 동작합니다.
UNIX/Linux에서 구현하기 — raw 모드 활용
UNIX 계열 시스템(Linux, macOS 등)에서는 터미널을 raw 모드로 전환하여 같은 효과를 얻을 수 있습니다. stty raw 명령어로 터미널의 줄 버퍼링(line buffering)을 비활성화하면, Enter 키를 누르기 전에도 각 키 입력을 즉시 읽을 수 있습니다.
예제 코드
#include<iostream>
#include<stdio.h>
int main() {
char c;
// 터미널을 raw 모드로 설정
system("stty raw");
while(1) {
c = getchar();
// "." 키가 눌리면 종료
if(c == '.') {
system("stty cooked");
exit(0);
}
std::cout << c << " was pressed."<< std::endl;
}
}이 코드는 누른 키마다 "○ was pressed."라는 메시지를 출력하며, 마침표(.)를 누르면 터미널을 원래 상태(cooked 모드)로 복구한 뒤 프로그램을 종료합니다.
주의 사항
- raw 모드 복구: 프로그램이 비정상적으로 종료되면 터미널이 raw 모드로 남아 있을 수 있습니다. 종료 전 반드시
stty cooked로 되돌려 주세요. - system() 호출의 한계: 예제에서는 편의상
system()을 사용했지만, 실제 프로젝트에서는termiosAPI(tcgetattr(),tcsetattr())를 직접 사용하는 것이 더 안전하고 효율적입니다. - 크로스 플랫폼 대안: Windows와 UNIX를 모두 지원해야 한다면 조건부 컴파일(
#ifdef _WIN32)로 두 방식을 분기 처리하거나, ncurses 같은 크로스 플랫폼 라이브러리를 고려할 수 있습니다.