인프런 커뮤니티 질문&답변

정현준님의 프로필 이미지
정현준

작성한 질문수

홍정모의 따라하며 배우는 C언어

6.18 루프 안에서 함수의 반환값 사용하기

scanf()함수 반환값

해결된 질문

작성

·

915

2

scanf()함수의 반환값은 입력받은 개수를 출력한다(단 정상적인 형식에 맞춘 값을 받을때만)

라는 것을 이해하고 

int main ()

{

for(int a=0; a=scanf("%d",&a)!=0;)
{

printf("계속출력");

printf("\n');

}

이렇게 하면 scanf()함수가 반복적으로 시행되면서, 문자를 입력하기 전까지 계속 printf함수가 반복출력되는 것을 확인할 수있다는 것 까지 이해했습니다.

근데, 거꾸로 생각해보면, scanf함수에서 문자를 입력하면 반환값이 0이되니까,

문자를 입력 받으면 오류 문구를 띄우고 다시 치세요 라는 프로그램을 작성해 보려고 만들었는데, scanf()의 반환값은 0이 나와서 맞는데 왜 scanf가 다시 뜨지않고 무한루프로 뜨는지 이해가 되질 않습니다.

int scan_function(void);

int main()

{

int my_num;

my_num = scan_function();

printf("my number is %d", my_num);

return 0;

}

int scan_function(void)

{

int return_num = 0;

printf("input the integer :");

/*while(temp=(scanf("%d",&return_num)!=*/

for (int temp=0;(temp = scanf("%d", &return_num))!=1; )

{

printf("try again, you must input only integer ");

if (temp == 1)

{

break;

}

(temp = scanf("%d", &return_num)) != 1;

}

return  return_num;

답변 4

4

안녕하세요!

질문자님의 코드가 무한 루프에 빠진 이유는 질문자님께서 입력 버퍼를 비우시지 않았기 때문입니다.

이해를 돕기 위해 예시로 적어본 코드입니다. scanf 입력을 3 번 받을건데 첫번째 두번째 scanf 는 정수를 받고 세번째 scanf 는 char 문자를 받게끔 해봤습니다. 이 상태에서 정수가 아닌 'q' 문자를 입력해보았습니다. q 문자 한번만 입력했을 뿐인데 3 번 입력받기는 커녕 위와 같은 결과들이 출력되고 종료 된 것을 확인할 수 잇습니다. q 문자는 한번만 입력했을 뿐인데요! 이렇게 되는 이유는.. 

입력을 하면 입력 값과 입력을 완료하고 친 엔터 '\n' 개행 문자가 입력 버퍼에 들어가게됩니다. q를 입력했으니 시스템 내의 입력 버퍼에는 'q' '\n' 이렇게 두 개의 문자가 들어있게 됩니다. 

사용자가 한번 입력하면 그 입력한 모든 것들이 입력 버퍼에 들어가게되고 scanf는 이 입력 버퍼로부터 "%d", "%c" 이런 출력 변환지정자에 맞는 데이터를 꺼내오는 식으로 작동하게 되요! 근데 입력 버퍼의 가장 앞에 있는 'q'는 정수가 아닌 char 타입의 문자이기 때문에 "%d" 정수 포맷으로 입력 받기로한 i 와 j 에는 입력 될 수가 없습니다. 따라서 i 와 j 는 'q' 를 가져올 수 없으므로 'q' 를 입력 받는 것을 무시하게 됩니다. 그래서 첫 번째 두 번째 scanf는 i와 j에 입력 하는 것을 실패했으므로 0 을 리턴하는 것을 확인할 수 있네요! 그리고 세 번째 scanf 인 "%c" 에서 그제서야 i와 j에 입력되지 못해 버퍼에 그대로 남아있던  'q'를 가져와 c 변수에 저장하게 됩니다. 그래서 이와 같은 작동원리 떄문에 scanf 는 3 번 있었음에도 불구하고 사용자가 문자 'q'를 입력하는바람에 정수인 i와 j는 이 q 를 안받고 무시했고 c에서 이 'q'를 받았기 때문에  사용자 입력은 총 1 번만 이루어졌네요.

질문자님의 코드의 for문에 있는 scanf들은 모두 "%d" 정수만 입력 받는 scanf 입니다. 따라서 정수가 아닌 문자를 입력했을 때는 입력 버퍼에 정수가 아닌 '문자'가 들어있게 되므로 이를 return_num에 입력 받을 수 없게 됩니다. 따라서 입력 버퍼에는 이 문자를 받을 수 있는 scanf가 없어 문자는 버퍼에 계속 남아있게 되고 temp 는 계속 0 인 상태로 고정되기 때문에 무한 루프에 돌게 된 것입니다. 

(덧붙여서 맨 아랫줄에 있는 temp = scanf(...) 문은 이미 for문의 반복 조건문에 작성 해주셨기 때문에 필요 없어보입니다. 그리고 printf("try, again"...)또한 if break 문 아래에 위치하는 것이 더 좋을 듯 싶습니다. 정수가 잘 입력되어 빠져 나왔다면 try again을 출력할 이유가 없으니까요.)

따라서 문제를 해결하려면 입력 버퍼에 들어가 있는 '문자' '\n'  들을 전부 빼내어 입력 버퍼를 비워주어야 합니다. 입력 버퍼에서 scanf가 가져올게 아무것도 없으므로 그래야지만 사용자 입력이 활성화 되요! 

이렇게 코드를 바꿔서 해결했습니다. 

while(getchar() != '\n') continue; 문장이 바로 입력 버퍼를 비워주는 역할을 해요! 입력 버퍼에 '\n' 개행 문자가 나올 때 까지 읽어오고 동시에 비웁니다.

아직 getchar() 에 대해 잘 모르시거나 위 문장이 이해가 안가신다면 7.2 강의에서 교수님께서 자세히 설명해주실거에요!

q를 입력 했고 for문에 있는 scanf 가 정수만 입력 받기 때문에 이 q를 받아올 수 없었을 것입니다. 따라서 temp 는 0 이고 버퍼에는 q 와 개행문자가 들어있게 됩니다. 이 q 와 개행문자를 while(getchar() != '\n') continue; 를 통해 입력 버퍼에서 청소하고 다시 temp = scanf(...) 에서 입력 받으려고 하면, 입력 버퍼에 현재 아무 것도 없으므로 사용자의 입력을 새롭게 받게 됩니다. 

아무튼! 정수를 입력 받으려는데 문자를 입력 했으면 그 문자가 입력 버퍼에 계속해서 남아있는 상태이므로 정수를 입력 받는 scanf는 입력 버퍼에 있는 이 문자를 가져가지 않기 때문에 계속 무시하게되어 무한루프에 빠지게 됩니다. 따라서 입력 버퍼를 싹 깨끗이 비워주어야 새롭게 사용자 입력을 받을 수 있다는 것이 결론입니다.

2

헉 말씀 너무 감사합니다.. 질문자님도 행복한 크리스마스 되세요. 

2

정현준님의 프로필 이미지
정현준
질문자

와 진짜 감사합니다 

크리스마스 이브 행복하게 보내세요 언제나 축복이 있길 바라겠습니다 고생하셨습니다!

0

질문자님, 답변자님 모두 감사드립니다.

고민 해결하고 가네요 히 

정현준님의 프로필 이미지
정현준

작성한 질문수

질문하기