기타 언어(C, PHP 등)

[c/c++] scanf

노루아부지 2019. 7. 31. 17:24
반응형

C언어에서 기본 출력함수가 printf()가 있다면 입력함수는 scanf()가 있다.

 

본격적인 설명에 앞서 입력의 원리를 이야기 하겠다.
우리가 입력하는 것들은 프로그램에 바로 입력된다고 생각하지만
사실은 입력버퍼에 저장이 되었다가 입력이 종료되면 버퍼에서 데이터를 꺼내 변수에 다시 저장이 된다.
이 사실을 알아두고 아래 설명을 보기를 바란다.

-------------------------------------------------------------------------------------------------------------------

scanf("서식문자열", &변수 [,&변수, ...]);

위의 내용은 scanf() 함수의 기본 양식이다. printf()와는 달리 서식 문자열에는 오직 서식만 들어갈 수 있다.


예1) int input;
     printf("숫자를 입력하세요 : ");
     scanf("%d", &input);

 

위 예제 1번의 scanf() 함수를 보자.

scanf("%d", &input);

함수 안의 서식문자열에 해당하는 "%d"는 정수형을 입력받는다는 서식이다.
다른 서식은 책을 참조하기 바란다.


&변수에 해당하는 &input에서 &는 주소값을 나타내는 기호이다.
문자열을 제외한 자료형에는 &기호를 붙여주어야 하는데, 자세한 이유는 다음에 설명하도록 하겠다. (지금은 그냥 외우도록..)

즉, scanf("%d", &input); 을 해석해 보면, 
"input이라는 이름을 가진 메모리 공간에 정수형 데이터를 입력받아라" 는 의미이다.

 


예2-1)  #include<stdio.h>

 

          void main()
          {
             char x[10],y, z;
 
             printf("input char:");
             scanf("%c",&y);

             printf("inrput char:");
             scanf("%c",&z);

             //printf("z : %d", z);
          }

 

위와 같은 소스가 있다.
눈으로 보기에는 아무런 이상이 없어 보이고 컴파일에도 이상이 없다.
하지만 이것은 잘못된 코딩이다.

먼저, 프로그램을 실행시켜 본 뒤, a를 입력해 보자. 그러면 변수 y에는 a라는 값이 잘 들어가고 뒤이어 z를 입력받아야 하는데, 입력받지 않고 프로그램이 종료되어버린다.
그 이유는 입력을 종료하기 위해 입력한 '엔터'가 버퍼에 저장되기 때문이다.

우리가 a라고 입력을 한 뒤 엔터를 누르면 버퍼에는 a와 '\n'가 입력이 된다.
변수에 문자를 넣으려고 보니 입력은 2개의 문자가 되었는데 y변수에는 하나의 문자밖에 넣을수가 없다.
따라서 y에 a라는 값이 저장이 되고 '\n'라는 문자는 버퍼에 남는다.
그 다음 z변수의 값을 입력받을 차례가 되었는데 여기서 문제가 발생한다.
y변수에 값을 저장했는데 버퍼에 '\n'이 남아버린 것이다.
그렇기 때문에 z변수에는 버퍼에 남아있던 '\n'이 저장되었기 때문에 프로그램이 종료되는 것이다.
이 설명을 더 자세히 알고 싶으면 마지막 printf()함수의 주석을 해제하고 실행해 보기를 바란다.

주석을 해제하고 실행하면 z : 10이라는 값이 출력될 것이다. 여기에서 10이라는 값은 아스키 코드값으로 '\n'을 나타내는 것이다.

 

 

아래 예제를 더 살펴보자

예2-2) #include<stdio.h>

 void main()
 {
  char x[10],y, z, ab = '\0', ac='\n';
 
  printf("input char:");
  scanf("%s", x);

  printf("inrput char:");
  scanf("%c",&z);

  printf("\n\n%d\n", z);
 }

 

이 프로그램을 실행하여 x라는 변수에 문자열을 넣으면 어떻게 될까?
x라는 변수에 ppppp를 입력하여 보자. 그러면 예제2-1과 마찬가지로 scanf("%c", &z);는 우리의 입력을 기다려주지 않고 프로그램을 종료한다.
이것 역시 예제2-1과 마찬가지로 '\n'가 버퍼에 남아있기 때문이다.

그렇기 때문에 문자 자료형(%c)를 입력받을 경우에는 fflush(stdin); 라는 함수를 통해 항상 버퍼를 비워주어야 한다.

여기에서 놀랄만한 사실은 문자형 자료형만 이러한 문제가 발생한다는 것이다.

 

아래 예제를 보자

예제2-3)#include<stdio.h>

       

            void main()
            {
               char x[10],y, z, ab = '\0', ac='\n';
               int abc;

               printf("input char:");
               scanf("%c", &y);

               printf("inrput char:");
               scanf("%s",x);
            }

예제2-4)#include<stdio.h>

 

           void main()
           {
              char x[10],y, z, ab = '\0', ac='\n';
              int abc;

              printf("input char:");
              scanf("%c", &y);

              printf("inrput char:");
              scanf("%d", &abc);
           }

 

예제2-3번이나 예제2-4번같이 문자열이나 숫자 등의 입력은 전혀 문제가 되지 않는다.

그 이유는 입력방식의 차이인데 %d(숫자)의 경우 입력의 첫부분에 '\n'문자가 나타나면 입력을 계속 다시 받는다. 또한 %s(문자열)의 경우 실질적인 데이터(공백이 아닌 것들)이 나오기 전까지 버퍼에 남아있던 모든 공백 문자들은 무시하게 된다.
이것이 그 이유라 할 수 있다.
결론은 %c만 조심하면 된다는 그런 내용이다.

 

 

[* 추가사항 *]
scanf()함수에서 서식 부분. 즉, "%d"에서 입력을 조절할 수 있다는 사실을 아는가?

예3) #include<stdio.h>

 

      void main()
      {
         int abc;
         scanf("%2d", &abc);

         printf("%d", abc);
      }

 

이와 같은 프로그램이 있다. 여기서 scanf("%2d", &abc); 가 생소하게 보일 것이다.

여기서 "%2d"란 몇자리의 수를 입력하든지간에 2자리까지만 저장하고 나머지는 저장하기

않겠다는 것이다.

 

 

예4) #include<stdio.h>

    

       void main()
       {
          char abc[50];
          scanf("%[a-d]s", abc);

          printf("%s", abc);
       }

 

예4와 같은 프로그램은 결과가 어떨까?
scanf("%[a-d]s", abc); 에서 "%[a-d]s"라는 서식은 알파벳 중에서 소문자 a,b,c,d만 입

력받겠다는 서식이다. a,b,c,d안에 포함된 알파벳을 입력 받다가 범위를 벗어나는 문자를

입력하면 입력을 받지 않는다.

728x90
반응형
loading