본문 바로가기
c언어/활용편

scanf("%c")의 문제점

by 감조자림 2023. 1. 15.

scanf("%c", &c);

위와 같은 코드로 하나의 문자를 입력받으려고 할 때, 종종 문제가 생기곤 한다.

정확한 원리는 모르겠지만 scanf("%c", c); 보다 아래에 있는 코드가 먼저 실행되는 것처럼 보이는 경우가 발생한다.

키보드의 입력은 모두 입력버퍼 라는 곳에 담기게 되는데, a를 입력하고 엔터키('\n')를 누르면 'a'라는 문자와 '\n'라는 문자 모두 입력 버퍼에 들어가게 된다. scanf는 입력 버퍼에 있는 두 문자를 모두 읽어버리는데 이게 문제의 원인이다. 반복문 안에 scanf("%c")가 있으면 처음에는 a를 받고, 그 다음 반복에서 자동으로 '\n'을 받게된다. 사용자는 아직 두번째 반복에서 문자를 입력하지 않았다고 생각하지만 컴퓨터는 개행문자를 받아서 반복문을 한 번 더 돌려버린다. 

 

+)예를 들어, 아래와 같은 코드의 경우

while(1){
scanf("%c", &c);
printf("%c", c);
}

a를 입력했다고 치면 

콘솔창에는 아래와 같이 표시된다.

a //scanf에 내가 입력한 값.

a //printf로 출력된 값.

_(입력 대기중)

여기서 printf가 a라는 문자를 출력한 뒤 그 다음 줄에서 입력을 기다리는데 이것은 사실 내가 첫번째 반복에서 a라는 문자와 '\n'라는 개행문자 두개를 입력을 해서 scanf가 자동으로 두번째 반복에서 '\n'을 입력받아서 printf로 개행을 출력한 것이다. 반복문 안에서 변수의 값을 변경시켜보면 한 번의 입력으로으로 변수의 값이 두 번 바뀌는것을 볼 수 있다. 

 

해결법

1. scanf(" %c", &c);

위와같이 따옴표와 % 사이를 한 칸 띄어준다. 이렇게하면 입력한 값 중 공백에 해당되는 것들은 모두 무시한다. 개행, 띄어쓰기, 탭 등 다 무시해준다.

 

2. 입력 버퍼 비우기

2-1. fflush

scanf("%c", &c);

fflush(stdin);

fflush를 실행하면 출력버퍼를 비워준다. gcc환경에선 안된다고 한다. c++에서만 되는건가? 잘 모르겠다.

 

2-2.

scanf("%c", &c);

rewind(stdin);

입력버퍼의 포인터를 맨 앞으로 이동시킨다. 

댓글