----------------
title : 씹어먹는 C 언어 - <15 - 2. 일로와봐, 문자열(string) - 버퍼에 관한 이해>
cat_title : 15 - 2. 일로와봐, 문자열(string) - 버퍼에 관한 이해
next_page : 33
publish_date : 2010-01-25
tex_title : 버퍼에 대한 이해
path : /C
--------------


이번 강좌에서는

* 버퍼(stdin)에 대한 이해

* 고질적인 `scanf` 문제에 대한 해결 및 이해

![씹어먹는 C 언어](/img/ChewingClogo.png)

안녕하세요 여러분. 요즘에 제가 많이 바빠서 글을 자주 못올리고 있지만 여러분은 너그러운 마음으로 이해해 주시라 믿고 있습니다. 그렇다면, 지난번의 강좌를 계속 이어 나가도록 하겠습니다.

```cpp-formatted
/* 이상한 scanf */
#include <stdio.h>
int main() {
  int num;
  char c;

  printf("숫자를 입력하세요 : ");
  scanf("%d", &num);

  printf("문자를 입력하세요 : ");
  scanf("%c", &c);
  return 0;
}
```

성공적으로 컴파일 하였다면

```exec
숫자를 입력하세요 : 1
문자를 입력하세요 : 
```

허거걱! 여러분은 위 소스를 실행했을 때 충격을 금치 못했을 것입니다. 분명히 우리는 다음과 같이 `scanf` 를 이용해서 정수를 입력 받고 그 다음에 문자를 입력받으라고 명시했습니다.

```cpp-formatted
printf("숫자를 입력하세요 : ");
scanf("%d", &num);

printf("문자를 입력하세요 : ");
scanf("%c", &c);
```

분명히 우리는 컴퓨터로 하여금 숫자를 입력받은 후, "문자를 입력하세요 : " 를 출력한 다음, `c` 에 문자를 입력받으라고 명령하였습니다. 그리고, 컴퓨터가 정말 특별히 우리를 싫어하지 않는 한 무조건 우리의 말을 따라아 하는 것이지요. 그런데, 이게 무슨 일입니까? 우리의 컴퓨터는 우리가 친절히 명시해 준 `scanf("%c", &c);` 명령을 완전히 무시한 것 아닙니까? 이게 도대체 무슨 일이죠?? 사실, 우리가 컴퓨터에게 화풀이를 하기 전에 `scanf` 함수가 어떻게 작동하는 것인지 먼저 확인해볼 필요가 있습니다.

우리가 컴퓨터에 무언가를 입력하면 컴퓨터는 어떻게 처리를 할까요? 예를 들어서 우리가 컴퓨터에게 `abcde` 를 입력하였을 때, 컴퓨터가 각 문자를 입력받을 때 마다 처리를 한다면 (즉 우리가 `a` 를 누르는 순간 `a` 라는 문자를 변수에 저장하고 등등 작업을 하고 그 다음에 `b` 가 들어오면 다시 이 문자를 ...) 비효율적일 것입니다.

하지만 이렇게 하면 어떨까요. 우리가 문자를 입력한다면 다른 곳에 잠시 보관해 놓았다가 우리의 입력이 끝난다면 잠깐 보관해 놓았던 곳의 정보를 한꺼번에 처리하는 것입니다. 따라서, 만일 우리가 `abcde` 를 입력하였다면 `abcde` 를 잠시 다른 곳에 보관해놓았다가 입력이 끝난다면 이를 한꺼번에 처리하는 것입니다.

사실, 이 두 방법이 어떤 차이가 있을 수 있느냐 라고 물을 수 있지만 아래 비유를 보면 쉽게 이해가 될 것입니다. 우리가 만일 약수터에 가서 물을 떠온다고 해봅시다. 물을 3 L 받아 온다고 했을 때 우리는 물을 두 가지 방법으로 받아올 수 있습니다. 하나는 손에 물을 받아서 약수터까지 수십번 왔다 갔다 하는 것이고, 다른 방법은 양동이를 들고가서 3 L를 채운 후, 다시 양동이를 가지고 내려오는 것입니다.

자. 그럼 어떤 방법이 합리적인것 같습니까? 손으로 조금씩 조금씩 받아서 수십번 왔다갔다 하는 것이 나을 까요? 아니면 양동이를 들고 한 번만 갔다오는 것이 나을까요? 당연히, 후자가 훨씬 좋은 방법이겠지요. 컴퓨터도, 원리는 조금 더 복잡하지만 이러한 방법을 채택하고 있는 것입니다.

그렇다면 컴퓨터의 양동이에 해당하는 부분은 무엇일까요? 바로, **버퍼(buffer)** 라고 부르는 것입니다. 또한, 수 많은 버퍼 중에서도 키보드의 입력을 처리하는 버퍼는 바로 입력 버퍼, 혹은 `stdin` (흔히 입력 스트림) 이라 부르는 것입니다.

다시말해 우리가 키보드로 쳐다는 모든 정보는 일시적으로 `stdin` 에 저장되었다가 나중에 입력이 종료되면 한꺼번에 처리를 하는 것입니다. 그런데, 컴퓨터가 어떻게 우리가 입력을 종료했는지 알 수 있죠? 바로 엔터를 치면 됩니다. 왜냐하면 이전에도 우리가 계속 보았듯이 엔터를 치기만 하면 입력을 끝내고 프로그램이 계속 실행되었잖아요. 안그래요?

다시말해 컴퓨터는 개행 문자, 즉 `\n` 을 '입력을 종료하였으니 버퍼에 들어 있는 내용을 가지고 놀아라' 라는 뜻으로 받아 들입니다.\sidenote{잘 알고 게시고 있겠지만 \n 은 두 개의 문자 '\' 와 'n' 이 아니라, 하나의 문자 (개행문자 - 키보드 상의 엔터)를 의미합니다!} 그런데 컴퓨터는 `\n` 까지 버퍼에 저장하게 됩니다. 즉, 우리가 1 을 쓰고 엔터를 딱 치면 버퍼에 아래와 같은 상태가 됩니다.

![](http://img1.daumcdn.net/thumb/R1920x0/?fname=http%3A%2F%2Fcfile21.uf.tistory.com%2Fimage%2F130AA41A4B59433D75F8F5)

자. 그럼 입력을 끝냈다면 컴퓨터는 `scanf` 함수를 이용해서 `stdin` 으로 부터 숫자를 얻어옵니다. 왜 숫자냐면, 잘 아겠지만 우리가

```cpp-formatted
scanf("%d", &num);
```

로 하였기 때문이죠. 즉 오직 숫자 데이터만 `stdin` 에서 얻어온다는 말입니다. 그렇다면 `scanf` 함수는 언제까지 `stdin` 으로 부터 데이터를 얻어올까요? 바로 `' ', '\n', '\t'` 를 만날 때 까지 입니다. 여기서 `' '` 는 띄어쓰기 한 칸 (키보드의 Space) 을 의미합니다. 또한 `\t` 는 탭 문자로 여러분이 키보드에 `Tab` 키를 누를 때 나오는 문자 입니다.

또한 `\n` 은 이전에 이야기 했던대로 개행문자 (키보드의 Enter) 입니다. 다시 말해 `scanf` 함수는 `stdin` 에서 위 세 개의 문자들을 만난다면 **아. 여기서 입력은 끝이구나** 하고 입력을 종료해 버립니다.

참고적으로 `%d` 계열의 것들, 즉 수를 입력받는 형식은 수가 아닌 데이터가 와도 입력을 종료해 버립니다. 즉, `a` 를 입력했다면 `num` 에는 아무런 값이 들어가지 않아 치명적인 결과를 야기할 수 있습니다. 뿐만 아니라 수 데이터를 입력받는 형식의 경우 처음 부터 공백문자가 나타나면 수가 나타날 때 까지 입력을 계속 받게 됩니다. (다시 말해, 수를 입력 받는데 엔터를 아무리 쳐도 숫자를 치기 전까지 넘어가지 않는다) 암튼 `scanf` 함수는 공백 문자(`' ', '\n', '\t'`) 를 만나기 전까지 `stdin` 에서 데이터를 가져간 후 버퍼에서 삭제해 버립니다. 다시말해, 위 `scanf` 함수가 `num` 에 1 을 저장한 후 버퍼의 모습은 아래와 같습니다.


![](http://img1.daumcdn.net/thumb/R1920x0/?fname=http%3A%2F%2Fcfile22.uf.tistory.com%2Fimage%2F18672D274B594AE6470168)

자, 이제. 우리의 말을 아주 잘 듣는 컴퓨터는

```cpp-formatted
scanf("%c", &c);
```

를 실행하게 됩니다. 그런데 말이죠, `%c` 는 이유를 불문하고 `stdin` 에서 딱 한개의 문자만을 가져오게 됩니다. 만일 `stdin` 에 아무것도 없다면 사용자의 입력을 기다리고 있겠지만 `stdin` 에 무언가가 있다면 그 것을 냉큼 가져오게 되지요. 그런데 공교롭게도 위에서 `\n` 을 버퍼에 남겨 놓았기 때문에 `scanf` 는 냉큼 이를 `c` 에 저장하게 됩니다. 즉, `c` 에는 사용자의 입력을 받지도 않고 `\n` 을 집어 넣은 것이지요.

따라서 만일 우리가 `printf("%c 출력", c);` 를 해보게 된다면 '출력'이 한 칸 개행(엔터가 쳐져서)되어 나타나게 됩니다.

#### %s 로 scanf 에서 받을 경우

```cpp-formatted
/* 그렇다면 %s 는 ? */
#include <stdio.h>
int main() {
  char str[30];
  int i;

  scanf("%d", &i);
  scanf("%s", str);

  printf("str : %s", str);

  return 0;
}
```

성공적으로 컴파일 한다면

```exec
1
asdfasfasdf
str : asdfasfasdf
```

오오.. 이번에는 다행입니다. `%c` 와는 달리 `%s` 의 경우 컴퓨터가 사용자로 부터 입력을 잘 받았습니다. 사실, 그 이유는 간단합니다. 일단,

```cpp-formatted
scanf("%d", &i);
```

를 실행하여 사용자로 부터 수를 입력 받게 된다면 역시 `stdin` 에는 \n 이 남아있게 됩니다. 그리고

```cpp-formatted
scanf("%s", str);
```

를 실행하게 되면 역시 수 데이터를 입력 받는 형식 처럼실질 적인 데이터 (공백 문자가 아닌 것들) 이 나오기 전 까지 버퍼에 남아 있던 공백 문자들은 무시하고 실질 적인 문자(공백 문자가 아닌 것들)가 입력이 된다면 그 다음 부터 등장하게 되는 공백 문자에서는 종료하게 됩니다. 즉, 기존에 1 을 입력하였을 때 남아있었던 `\n` 은 사라지고, 내가 `aasdfdasfads` 를 입력하고 난 후, 엔터를 쳤을 때 들어가는 `\n` 을 인식 하게 된다는 것이지요.

결론적으로 요약하자면 `%s` 나 `%d` 그리고 다른 모든 수 데이터를 입력 받는 형식은 버퍼에 남아 있는 공백 문자에 신경쓰지 않고 사용할 수 있습니다. \sidenote{그렇다고 해서 %s 를 입력 받는 후 버퍼가 완벽히 깨끗해 지는 것이 아닙니다. 개행 문자는 뒤에 남아있죠!}

하지만 `%c` 를 이용할 때 에는 버퍼에 무엇이 남아 있는지 잘 고려해야 합니다. 이는 정말로 번거로운 일이 아닐 수 없습니다. 물론, 이를 대체할 수 있는 멋진 대안이 있지만 이는 조금 있다가 고려하도록 하고 다음 예제를 살펴 보도록 합시다.

```cpp-formatted
/* 마지막 stdin 예제 */
#include <stdio.h>
int main() {
  char str1[10], str2[10];

  printf("문자열을 입력하세요 : ");
  scanf("%s", str1);
  printf("입력한 문자열 : %s \n", str1);

  printf("문자열을 입력하세요 : ");
  scanf("%s", str2);
  printf("입력한 문자열 : %s \n", str2);

  return 0;
}
```

성공적으로 컴파일 하였다면

```exec
문자열을 입력하세요 : hello
입력한 문자열 : hello 
문자열을 입력하세요 : baby
입력한 문자열 : baby 
```

상당히 평범한 내용입니다. 여태까지의 강좌를 잘 따라오고 있었다면 위 내용쯤이야 쉽게 이해할 수 있을 것입니다.

그렇다면 다음과 같이 입력 해보도록 하겠습니다.

```exec
문자열을 입력하세요 : hello baby
입력한 문자열 : hello 
문자열을 입력하세요 : 입력한 문자열 : baby 
```

헉.. 이번에는 우리의 두번째 `scanf` 를 완전히 무시하고 지나갔습니다. 하지만 똑똑한 여러분이라면 왜 두번째 `scanf` 에서 사용자로 부터 입력을 받지 않았고, `str1` 에는 `hello, str2` 에는 `baby` 가 제대로 들어갔는지도 알 수 있을 것입니다. 우리가 "hello baby" 를 입력하였을 때 `stdin` 의 상태를 살펴봅시다.


![](http://img1.daumcdn.net/thumb/R1920x0/?fname=http%3A%2F%2Fcfile1.uf.tistory.com%2Fimage%2F127C1E1D4B59E46F05B6EA)

그렇다면

```cpp-formatted
scanf("%s", str1);
```

`scanf` 함수는 `stdin` 으로 부터 **의미가 있는 문자 (공백 문자(`' ', '\n', '\t'`) 를 제외한 나머지 문자)** 가 나올 때 까지 모든 공백 문자들을 무시합니다. 위의 경우 `stdin` 에서 처음에 공백 문자가 하나도 없으므로 바로 `stdin` 으로 부터 데이터를 가져오겠군요. 데이터를 가져오다가 공백 문자를 만나게 되면 입력을 중지합니다. 위의 경우 `' '` 이 공백 문자의 역할을 하기 때문에 `str1` 에는 `hello` 까지만 입력이 됩니다.

첫번째 `scanf` 함수를 지나게 되면 `stdin` 의 모습은 아래와 같습니다.


![](http://img1.daumcdn.net/thumb/R1920x0/?fname=http%3A%2F%2Fcfile10.uf.tistory.com%2Fimage%2F207CC11D4B59E5270372BB)

이제 두번째 `scanf` 를 지나갈 차례입니다.

```cpp-formatted
scanf("%s", str2);
```

`scanf` 함수는 `stdin` 에 아무 것도 없거나, 공백 문자들 밖에 없다면 사용자가 무언가 의미 있는 문자를 입력해줄 때 까지 기다리겠지만 위 경우는 상황이 다릅니다. 일단, 처음에 공백 문자인 띄어쓰기는 살포시 무시합니다. 왜냐하면 아직 의미 있는 문자를 받지 않았기 때문이죠. 그 다음에 `b` 를 보고 `str2` 에 입력을 쭉 받기 시작합니다. 그러다가 마지막에 공백 문자인 \n 을 보고 입력을 중지합니다. 따라서 메모리에는 다음과 같이 \n 만이 덩그러니 남아있게 됩니다.


![](http://img1.daumcdn.net/thumb/R1920x0/?fname=http%3A%2F%2Fcfile5.uf.tistory.com%2Fimage%2F163DC31C4B59E62A0DE398)

아무튼. `scanf` 는 상당히 이해하기 복잡한 것임은 틀림이 없습니다. 가뜩이나 머리 아픈데 `%c` 를 이용하면 고려해야 될 것이 더욱 많아지니 정말 짜증이 나는 것 같습니다. 하지만 다행스럽게도 이러한 문제를 해결할 수 있는 방법이 있을 뿐더러 실질 적으로 `%c` 는 많이 쓰이지 않으니 다행인 것 같습니다.



###  도대체 이 문제를 어떻게 해결하냐


하지만, 아무리 `%c` 를 사용하지 않는다고 해도 필연적으로 사용할 일이 생기게 됩니다. 그렇다면 그 때 마다 이처럼 버퍼에 \n 이 남아 있는 것을 고려해야 할까요? 정말 번거로운 일이 아닐 수 없습니다. 하지만 걱정 마십시오. 이를 해결할 수 있는 방법이 여러 가지가 있습니다.

```cpp-formatted
/*

버퍼 비우기

주의하실 점은 반드시 MS 계열의 컴파일러로 컴파일 해주세요. 즉, Visual Studio
계열의 컴파일러로 말이죠. 이 말이 무슨 말인지 모르면 그냥 늘 하던대로 하면
됩니다.

gcc 에서는 정상적으로 작동되지 않는 위험한 코드 입니다.

*/
#include <stdio.h>
int main() {
  int num;
  char c;

  printf("숫자를 입력하세요 : ");
  scanf("%d", &num);

  fflush(stdin);

  printf("문자를 입력하세요 : ");
  scanf("%c", &c);
  return 0;
}
```

성공적으로 컴파일 했다면


![](http://img1.daumcdn.net/thumb/R1920x0/?fname=http%3A%2F%2Fcfile26.uf.tistory.com%2Fimage%2F1130C20E4B5B07C295272E)

아마도 여러분은 컴파일 하면서 포스 넘치는 주석을 보며 무언가 당황 하셨을 수 도 있습니다. 하지만 걱정하진 마세요. 지금 수준의 프로그래밍에서는 크게 걱정할 문제는 아닙니다. 먼저 위 소스가 어떻게 해서 올바르게 작동하는지 부터 살펴보도록 합시다. 사실, 올바르게 라는 말 보다는 '`scanf` 가 사용자의 입력을 무시하지 않는지' 가 적당할 듯 하네요.

```cpp-formatted
printf("숫자를 입력하세요 : ");
scanf("%d", &num);
```

위까지 실행했을 때 에는 이전처럼 `stdin` 에 '\n' 이 남아 있습니다. 그런데 말이죠.

```cpp-formatted
fflush(stdin);
```

두둥. 새로운 문장이 등장했습니다. 위 문장의 의미는 'stdin 을 비워버려라' 라는 의미이죠. 다시말해 `stdin` 에 있는 모든 데이터들을 날려버리게 되는 것입니다. 따라서 버퍼가 완전히 비워지게 됩니다. 즉 버퍼에 가시 처럼 남아 있던 \n 이 사라지게 됩니다.

```cpp-formatted
scanf("%c", &c);
```


따라서 그러한 상태에서 `scanf` 를 호출하게 되면 `%c` 는 버퍼에 아무것도 남아 있는 것이 없으므로 사용자의 입력을 차분히 기다리고 있게 됩니다. 즉, 우리가 `c` 에 원하는 값을 넣을 수 있다는 뜻이 되죠. 하지만 프로그램 코드 상단에 있는 무서운 주석을 보면 알겠지만 사실 위 코드는 추천하고 싶지 않습니다. 왜냐하면 `fflush` 가 표준으로 '무슨 역할은 한다' 라고 정해진 것이 아니기 때문입니다.

다시 말해 우리의 `Visual Studio` 에선 `fflush` 함수가 버퍼를 비우는 훌륭한 역할을 하지만 다른 것 - 예를 들면 `gcc` 같은 데에서는 이러한 작업을 하지 않을 가능성이 매우 매우 큽니다. 다시 말해, 위 방법은 그다지 권장하고 싶은 방법은 아니지만 적어도 우리의 수준에서는 정확하게 작동하고 편리하기 때문에 많이 사용합니다.\sidenote{Visual Studio 2015 부터는 표준을 따라서 fflush 가 위와 같이 작동하지 않습니다.}

```cpp-formatted
/* getchar 함수 이용 */
#include <stdio.h>
int main() {
  int num;
  char c;

  printf("숫자를 입력하세요 : ");
  scanf("%d", &num);

  getchar();

  printf("문자를 입력하세요 : ");
  scanf("%c", &c);

  return 0;
}
```

성공적으로 컴파일 했다면

```exec
숫자를 입력하세요 : 1
문자를 입력하세요 : c
```

오. 이번에도 제대로 작동하고 있습니다.

```cpp-formatted
printf("숫자를 입력하세요 : ");
scanf("%d", &num);
```

일단, 위 부분까지만 실행하면 역시 `stdin` 에는 \n 이 남아있게 됩니다. 상당히 곤란한 일이죠.

```cpp-formatted
getchar();
```

그렇데 말이죠, 우리가 `getchar` 이라는 함수를 호출했습니다. 이 함수의 역할은 'stdin 에서 한 문자를 읽어와서 그 값을 리턴한다' 입니다. 물론 한 문자를 읽어오면 읽어온 문자는 `stdin` 에서 사라지게 되지요. 따라서 위 함수를 호출 함으로써 \n 을 `stdin` 에서 읽어와 지워버릴 수 있는 것이지요.

  만일 우리가

```cpp-formatted
ch = getchar();
prinf("%c", ch);
```

을 해서 `getchar` 함수가 리턴한 값을 출력해보았다면 화면상에 한 칸 엔터(== \n)가 쳐진 것이 출력될 것입니다. (여러분이 한 번 해보세요~) 이제, 버퍼가 비워진 상태에서 `scanf` 함수를 호출하게 되면 성공적으로 사용자의 입력을 받게 되는 것입니다. 상당히 단순하지요?

`getchar` 함수를 호출한 방법은 여러 모로 많이 쓰이는 방법 입니다. 기본적으로 `scanf` 에서 `%c` 형식을 사용하는 것을 권하고 싶지는 않지만 정 사용하고자 한다면 `getchar()` 을 `scanf` 이전에 호출해서 버퍼를 비워주기 바랍니다. 그런데 말이지요. 위 방법도 문제가 어지간히 있습니다. 만일 버퍼에 한 문자만 남겨져 있는 것이 아니면 어떡할까요? 한 번 숫자를 입력할 때 `123abc` 를 쳐 보았습니다.

```cpp-formatted
/* c 에 무엇이 들어가는지 살짝 보아야 하므로 코드를 약간 수정했습니다 */
#include <stdio.h>
int main() {
  int num, i;
  char c;

  printf("숫자를 입력하세요 : ");
  scanf("%d", &num);

  getchar();

  printf("문자를 입력하세요 : ");
  scanf("%c", &c);

  printf("입력한 문자 : %c", c);
  return 0;
}
```

성공적으로 컴파일 했다면

```exec
숫자를 입력하세요 : 123abc
문자를 입력하세요 : 입력한 문자 : b
```

아.. 역시 제가 우려했던 대로 `scanf` 에서 사용자의 입력을 기다리지 않고 지나쳐 버렸습니다. 뿐만 아니라 `c` 에도 우리가 원하지 않던 `b` 라는 값이 들어가 있습니다. 도대체 왜 이런 일이 발생한 것일까요? 일단 버퍼에서 무슨 일이 벌어지고 있는지 차근 차근 살펴보도록 합시다.

```cpp-formatted
printf("숫자를 입력하세요 : ");
scanf("%d", &num);
```

일단 위 코드가 실행되어서 사용자로 부터 입력을 기다립니다. 사악한 Psi 는 `123abc` 를 쳤습니다. 그렇다면 버퍼에 다음과 같이 들어가겠지요.


![](http://img1.daumcdn.net/thumb/R1920x0/?fname=http%3A%2F%2Fcfile22.uf.tistory.com%2Fimage%2F1416F5184B5C68F604F2AF)

이제, `scanf` 함수가 `stdin` 에서 차례 차례 데이타를 읽어옵니다. 그 때도 말했들이 데이타를 읽어올 때 공백문자나 숫자가 아닌 것들을 만나게 되면 `stdin` 에서 부터 그만 읽어온다고 했죠? 이 때 `a` 가 숫자가 아니기 때문에 123 까지 읽은 후 `stdin` 에서 부터 그만 읽어 옵니다. 따라서 `stdin` 은 다음과 같은 모습이 되겠군요.


![](http://img1.daumcdn.net/thumb/R1920x0/?fname=http%3A%2F%2Fcfile26.uf.tistory.com%2Fimage%2F196982264B5C697793720F)
그렇다면 아래의 문장이 실행됩니다.

```cpp-formatted
getchar();
```

이는 이전의 문제점을 말끔히 해결해 주었죠. `stdin` 으로 부터 한 문자를 얻어오는 방법으로 말이지요. 여기서도 `getchar` 은 똑같은 역할을 수행합니다. 즉 `stdin` 으로 부터 한 문자, 위 경우 `a` 를 읽어옵니다.


![](http://img1.daumcdn.net/thumb/R1920x0/?fname=http%3A%2F%2Fcfile26.uf.tistory.com%2Fimage%2F116E46254B5C69DB816B7D)

  아 이런. 버퍼가 깔끔하게 비워지지 않았습니다. 이러한 우려 속에서 아래의 코드가 실행됩니다.

```cpp-formatted
printf("문자를 입력하세요 : ");
scanf("%c", &c);
```

음.. `scanf` 의 입장에서 버퍼에 읽어올 것들이 잔뜩 있으니 행복할 것 같습니다. 버퍼에서 한 문자를 읽어 옵니다. 그것이 바로 `b` 가 됩니다. 따라서 `c` 에는 우리가 원하지 않던 `b` 가 들어가게 됩니다. 그리고 물론 `b` 는 `stdin` 에서 사라지게 되죠. 다음에 또 `scanf("%c", &c");` 를 하게 되면 이번에는 `c` 가, 한 번 더하면 `\n` 이 읽어지겠죠?

아무튼. 여기서 내릴 수 있는 결론은 "되도록이면 `%c` 를 사용하지 말자" 입니다. `scanf` 에서 `%c` 를 사용하는 것은 정말로 권장하고 싶지 않은 일입니다. 만일 정말로 문자 하나만을 입력받는 프로그램을 만드려면 `scanf` 에서 `%s` 형태로 문자열을 입력 받은 뒤에 맨 앞의 한 문자만 취하는 식으로 만들면 되겠습니다.

```warning
결론 : 문자 대신 문자열을 입력 받도록 하자!

```

### 생각해보기

#### 문제 1

키보드로 부터 입력을 받는 함수는 `scanf` 나 `getchar` 말고도 여러가지가 있습니다. 이들에 대해 조사해 보는 것이 어떨까요? (난이도 : 無 - 쉬운 것도 아니고 어려운 것도 아님)

#### 문제 2

화면에 출력하는 함수도 `printf` 만 있는 것이 아닙니다. 화면에 출력하는 함수에 대해서 알아보는 것이 어떨까요?(난이도 : 無)

##@ chewing-c-end