c언어 정수 입력 scanf에서 문자열 입력 시 예외 처리


#include <stdio.h>
#include <stdlib.h>
int main()
{
  int num = 0;

  while(1) {
    printf("number : ");
    scanf("%d", &num);
    printf("%d\n", num);
    num = 0;
  }
}

여기서 정수가 아닌 문자열을 입력했을 때, 무한 루프를 돌지 않고 다시 입력 받게 하는 방법이 있나요?

  • 알 수 없는 사용자

조회수 334


1 답변


전통적인(?) 해결 방법으로 아래와 같은 코드가 있습니다.

 while (getchar() != '\n');

원리를 간단하게 설명드리면, scanf라는 함수는 입력버퍼가 비어있을 때 입력을 받을 수 있는 상태로 전환하고, 엔터가 입력되는 순간까지의 값을 버퍼에 저장합니다.

그리고 버퍼의 값을 &num 과 같이 인자로 전달한 변수로 추출해줍니다.

그런데, 만약 버퍼에 기록된 값이 전달된 변수와 타입이 일치하지 않는다면, 추출에 실패하게 되고, 그러면 입력버퍼는 그대로 유지가 되기 때문에, 무한루프에 빠지게 되는 것입니다.

getchar() 라는 함수는 입력버퍼에서 값을 읽어서 반환해주는 함수입니다. 이 때 읽은 값은 입력버퍼에서 제거됩니다.

따라서 getchar()는 호출될 때마다 입력버퍼를 조금씩 제거하는 역할도 하게 되지요.

우리가 처음에 scanf 함수를 통해 값을 입력했을 때, 엔터를 치면서 끝내게 되는데, 이 때 마지막으로 입력버퍼에 들어가게 되는 값이 바로 '\n' 값입니다.

따라서 while (getchar() != '\n'); 이 코드는 엔터값을 만날 때까지 입력버퍼를 비우게 되는 것이지요.

엔터를 친 이후에는 당연히 아무 값도 넣지 못하였기 때문에 입력버퍼는 완전히 비워지게 되고, 그 다음에 scanf 함수를 호출하게 되면, 다시 입력을 받을 수 있는 상태로 전환되게 되는 것입니다.

해당 코드는 어느 위치에 넣어도 상관 없습니다.

int main()
{
    int num = 0;

    while(1) {
        while (getchar() != '\n'); // 이렇게 루프 맨 위에 넣어도 되고,
        printf("number : ");
        scanf("%d", &num);
        // scanf()를 호출한 직후도 괜찮고
        printf("%d\n", num);
        num = 0;
        // 루프 제일 마지막에 넣어도 괜찮습니다.
    }
}
  • 2016년 09월 28일에 작성됨
    C++, C# 좋아합니다.

로그인이 필요한 기능입니다.

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 작성한 답변에 다른 개발자들이 댓글을 작성하거나 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.
► 로그인
► 계정만들기
Close