C언어에서 scanf()
함수는 입력 데이터를 처리할 때 **개행 문자('\n')**를 버퍼에 남기는 특성이 있습니다. 이로 인해 입력이 제대로 처리되지 않거나 예상치 못한 결과가 발생할 수 있습니다. 특히, %c
와 같은 문자 입력을 처리할 때 이 문제가 두드러집니다. 아래에서 문제의 원인과 해결 방법을 단계별로 살펴보겠습니다.
1. 문제의 원인
scanf()
함수는 입력 데이터를 처리할 때, 공백 문자(스페이스, 탭, 개행 등)를 기본적으로 무시합니다. 하지만%c
,%[ ]
,%n
과 같은 형식 지정자에서는 공백 문자를 무시하지 않고 그대로 처리합니다.- 따라서 숫자나 문자열 입력 이후에 남아 있는 개행 문자가 다음
%c
입력에 그대로 전달되어 문제가 발생합니다.
예제 코드:
int main() {
int a;
char c1, c2;
printf("숫자를 입력하세요: ");
scanf("%d", &a); // 개행 문자가 남음
printf("문자를 입력하세요: ");
scanf("%c", &c1); // 이전 입력의 개행 문자가 여기서 처리됨
printf("다른 문자를 입력하세요: ");
scanf("%c", &c2); // 사용자 입력 대기 없이 개행 문자 처리
printf("입력된 문자: %c, %c\n", c1, c2);
return 0;
}
문제:
%d
입력 후 남아 있는 개행 문자가%c1
에 저장됩니다.%c2
입력 시에도 사용자 입력을 대기하지 않고 바로 처리됩니다.
2. 해결 방법
2.1. 공백 추가
%c
형식 지정자 앞에 **공백(' ')**을 추가하면, scanf가 공백 문자를 무시하도록 설정할 수 있습니다.- 코드 수정:
scanf(" %c", &c1); // 공백 추가
scanf(" %c", &c2); // 공백 추가
- 동작 원리: 공백 문자는 이전 입력에서 남은 개행 문자나 탭 등을 건너뛰고 유효한 문자만 처리합니다.
2.2. 버퍼 비우기
- 입력 버퍼에 남은 데이터를 제거하는 방법으로
getchar()
또는fflush(stdin)
(Windows 환경에서만 지원)을 사용할 수 있습니다.
예제 1: getchar() 사용
scanf("%d", &a);
getchar(); // 남은 개행 문자 제거
scanf("%c", &c1);
getchar(); // 다음 입력 전에 개행 문자 제거
예제 2: fflush(stdin) 사용 (비표준 방식)
scanf("%d", &a);
fflush(stdin); // 입력 버퍼 초기화
scanf("%c", &c1);
주의: fflush(stdin)
은 비표준 함수이며, 다른 플랫폼(C 표준 준수 컴파일러)에서는 작동하지 않을 수 있습니다.
2.3. 할당 억제 방식 사용
%*c
형식 지정자를 사용해 개행 문자를 읽되 버퍼에 저장하지 않도록 설정할 수 있습니다.- 코드 예제:
scanf("%d%*c", &a); // %*c로 개행 문자 제거
scanf("%c%*c", &c1); // 문자 입력 후 개행 제거
2.4. fgets() 사용
fgets()
를 활용하면 입력을 한 줄 단위로 처리할 수 있어, 개행 문자 문제를 간단히 해결할 수 있습니다.- 예제 코드:
char buffer[100];
fgets(buffer, sizeof(buffer), stdin); // 한 줄 입력 받기
sscanf(buffer, "%d", &a); // 입력값 파싱
3. 총 정리: 권장 방법
- 문자 입력 시:
%c
앞에 공백 추가 (scanf(" %c", &c1);
) - 입력 처리 후:
getchar()
로 잔여 문자 제거 - 복잡한 입력 처리:
fgets()
와sscanf()
조합 사용
4. 결론
scanf()
는 효율적인 입력 함수이지만, 입력 버퍼에 남아 있는 개행 문자로 인해 예기치 않은 동작이 발생할 수 있습니다. 위에서 소개한 방법을 사용해 이 문제를 효과적으로 해결할 수 있습니다. 입력 데이터를 처리하기 전에 항상 버퍼 상태를 고려하는 습관을 들이는 것이 중요합니다.
Reference
https://stackoverflow.com/questions/5240789/scanf-leaves-the-newline-character-in-the-buffer