프로그래밍/C 2013. 4. 20. 20:54

scanf 함수의 개념은 "입력 버퍼(stdin)에서 format에서 지정한 대로 읽어들
인다" 입니다. 위의 두개의 차이는 다음과 같습니다.

"%d %d" - stdin에서 숫자, 1자 이상의 공백문자(white-space character), 숫
자를 읽어들인다.
"%d %d\n" - stdin에서 숫자, 1자 이상의 공백문자, 숫자, 1자 이상의 공백문
자를 읽어들인다.

C99의 FCD인 N869 문서의 7.19.6.2.5절을 인용하겠습니다.

A directive composed of white-space character(s) is executed by reading
input up to the first non-white-space character (which remains unread),
or until no more characters can be read.

형식(format) 문자열에 있는 공백문자(white-space)는 그 다음에 공백 문자가
아닌 문자(non-white-space)가 올때까지 입력버퍼(stdin)에서 읽어들이라는
뜻입니다. 즉, "%d %d\n"는 숫자 2개, 1자 이상의 공백문자, 공백문자가 아닌
문자를 받아야만 입력이 완전하게 끝나는 것입니다. 참고로 "%d %d\n"과 "%d
%d ", "%d %d\t"는 같은 뜻을 가집니다.

말이 어렵게 되어버렸는데, 예제로 설명하겠습니다.

scanf("%d %d", &a, &b);
숫자값, 1자 이상의 공백문자, 숫자값이 입력버퍼에 있기를 기대한다.
숫자값, 1자 이상의 공백문자, 숫자값까지 읽어들인다. 그 나머지는 입력 버
퍼(stdin)에 그대로 놔둔다.

실행 결과 - 1 2를 입력했을 경우 형식(format) 문자열과 완벽히 일치한다.
그러므로 a와 b에 읽어들인 값을 저장하고 함수(scanf)를 종료한다.

scanf(%d %d\n", &a, &b);
숫자값, 1자 이상의 공백문자, 숫자값, 1자 이상의 공백문자, 공백문자가 아
닌 문자가 입력버퍼에 있기를 기대한다.
숫자값, 1자 이상의 공백문자, 숫자값, 1자 이상의 공백문자까지 읽어들인다.
그 나머지는 입력 버퍼(stdin)에 그대로 놔둔다.

실행 결과 - 1 2를 입력했을 경우 "%d %d"까지 일치가 되지만 \n 문자 때문에
1자 이상의 공백문자와 그 뒤에 공백문자가 아닌 문자를 기다리게 됩니다. 여
기에 3을 또 입력하게 되면 공백문자까지 읽어들이게 되고 나머지(3)는 그대
로 입력버퍼에 남게 됩니다. 이 남아있는 3은 다음 scanf문이 실행될 때 영향
을 주게 됩니다.

그리고 한가지 더. 다음의 예제 코드를 봐 주십시오.

#include <stdio.h>

int main(void)
{
    int a, b;

    printf("\n>>");


    scanf("%d %d\n", &a, &b);
    printf("[%d,%d]\n>>", a, b);

    scanf("%d %d\n", &a, &b);
    printf("[%d,%d]\n>>", a, b);

    return 0;
}

이 프로그램의 실행 결과는 다음과 같습니다.

$ gcc 3.c -o 3
plsj@localhost: ~
$ ./3

>>1 2    <- 1과 2를 입력한다.
3    <- 숫자 2개가 입력되었는데도 입력을 기다린다. 3을 입력한다.
[1,2]    <- 입력된 숫자 출력
>>4 5    <- 숫자 2개를 또 입력
[3,4]    <- 4 5를 출력하는게 아니라 3과 4를 출력한다.
>>plsj@localhost: ~
$ ./3

>>1 2    <- 1과 2를 입력한다.
a    <- 숫자 2개가 입력되었는데도 입력을 기다린다. 3을 입력한다.
[1,2]    <- 입력받은 값을 출력한다.
>>[1,2]    <- 여기에서 입력을 한번 받아야되는데 받지 않고 입력받은 값을

              또한번 출력한다.
>>plsj@localhost: ~
$


첫번째 실행에서 1 2가 입력되면, "%d %d\n" 중에서 "%d %d"까지 일치가 됩니
다. 그러나 \n이 남아있기 때문에 1자 이상의 공백문자와 공백문자가 아닌 문
자의 입력을 기다리게 됩니다. 여기에 3을 입력하면 3 이전의 공백문자까지
읽어들이게 되어 첫번째 scanf 함수가 끝나게 되고 3은 입력버퍼에 그대로 남
습니다. 그다음의 scanf 함수가 실행되면 입력버퍼에 있는 3을 읽어들이게 되
고 " %d\n"이 남게 됩니다. 여기에 4 5를 입력하게되면 "4 "까지 읽어들이게
되고 5는 그대로 입력버퍼에 남게 됩니다. 즉 a에는 3이, b에는 4가 입력되는
것이죠.

두번째 실행에서도 마찬가지 입니다. 다만 첫번째 scanf 함수가 끝난 후에 3
대신 a가 입력버퍼에 남게 되고, 두번째 scanf 함수가 실행되면 형식(format)
문자열의 %d가 a와 일치가 안되기 때문에 두번째 scanf 함수는 하는일 없이
그대로 끝나게 됩니다. 따라서 1 2가 두번 출력되게 됩니다.

//