C 언어에서 scanf() 함수 다음에 fgets(), gets() 또는 또 다른 scanf()를 호출하면 의도하지 않은 동작이 발생할 수 있습니다. 원인은 표준 입력 버퍼에 개행 문자(newline)가 남아 있기 때문인데, 이 글에서는 두 가지 대표적인 상황을 예제와 함께 살펴보고 해결 방법까지 알아보겠습니다.
1. scanf() 다음에 fgets()/gets()를 사용하는 경우
scanf()로 정수를 입력받은 직후 fgets()나 gets()로 문자열을 입력받으면, 문자열 입력이 아무것도 받지 못하고 건너뛰어지는 현상이 나타납니다.
예제 코드
#include <stdio.h>
int main() {
int x;
char str[100];
scanf("%d", &x);
fgets(str, 100, stdin);
printf("x = %d, str = %s", x, str);
return 0;
}
실행 결과
입력: 30 String 출력: x = 30, str =
원인 분석
fgets()와 gets()는 실행 시점에 사용자로부터 문자열을 입력받는 함수입니다. 위 코드에서 정수 30을 입력하고 Enter 키를 누르면, 그 순간 입력 버퍼에는 개행 문자('\n')가 그대로 남게 됩니다. 이후 호출된 fgets()는 사용자가 입력하려던 "String" 대신 버퍼에 남아 있던 개행 문자를 즉시 읽어버리고 종료해 버립니다. 그래서 출력 결과에서 str이 빈 문자열로 표시되는 것입니다.
2. scanf() 다음에 또 다른 scanf()를 사용하는 경우
반복문 안에서 scanf()를 연속해서 호출할 때도 같은 문제가 발생합니다.
예제 코드
#include <stdio.h>
int main() {
char a;
printf("q를 누르면 종료합니다");
do {
printf("\n문자 하나를 입력하세요(q 입력 시 종료): ");
scanf("%c", &a);
printf("%c\n", a);
} while (a != 'q');
return 0;
}
실행 결과
입력: abq 출력: q를 누르면 종료합니다 문자 하나를 입력하세요(q 입력 시 종료): a a 문자 하나를 입력하세요(q 입력 시 종료): 문자 하나를 입력하세요(q 입력 시 종료): b b 문자 하나를 입력하세요(q 입력 시 종료): 문자 하나를 입력하세요(q 입력 시 종료): q
원인 분석
출력 결과를 보면 안내 메시지가 한 번씩 더 출력되는 것을 확인할 수 있습니다. 그 이유는 scanf("%c")가 문자 하나만 읽고 나머지 개행 문자를 입력 버퍼에 그대로 남겨두기 때문입니다. 다음 반복에서 scanf()는 사용자의 새로운 입력을 기다리지 않고 버퍼에 남아 있는 개행 문자를 바로 읽어버리므로, 화면에는 빈 입력으로 처리된 흔적이 남게 됩니다.
해결 방법
이러한 문제를 해결하는 대표적인 방법은 다음과 같습니다.
- 형식 지정자 앞에 공백 추가:
scanf(" %c", &a);처럼 %c 앞에 공백을 넣으면,scanf()가 공백과 개행 문자를 모두 건너뛰고 실제 문자만 읽습니다. 가장 간단하고 널리 쓰이는 방법입니다. - 버퍼의 개행 문자 직접 제거:
getchar()를 한 번 호출하거나scanf("%*c");를 사용해 버퍼에 남은 개행 문자를 미리 읽어 없앨 수 있습니다. - 형식 문자열에 '\n' 활용:
scanf("%c\n")처럼 작성하면 개행 문자를 건너뛰도록 처리할 수도 있습니다.
정리하면, scanf()는 숫자나 문자를 읽은 후 개행 문자를 입력 버퍼에 남기기 때문에, 이후에 이어지는 문자열 입력 함수나 문자 입력 함수가 엉뚱한 값을 읽게 됩니다. 입력 버퍼를 항상 깨끗하게 관리하는 습관이 이런 문제를 예방하는 핵심입니다.