[cpp] 입력 버퍼에 관한 진상, 2001

@codemaru · June 16, 2015 · 4 min read

그동안 잘못 알고 있었던 상식중에 입력버퍼에 관한 내용이 있어서 올려봅니다. 제 홈페이지를 통해서도 잘못 전파된 내용이 많을 것 같다는 생각이 드네염. 보통 scanf를 통해서 입력을 받을때 엔터 한번에 쭈루룩 다음 scanf함수까지 넘어가는 것을 본 적이 있을 겁니다. 그런 것들을 보면 보통 scanf하기전에 입력 버퍼를 비우기 위해서 fflush함수를 사용하라고 하는데, 이 fflush라는 놈이 표준안에 정의를 보면 표준 출력에 대해서만 정의되어 있고, 표준 입력에 대해서는 아무런 동작을 하지 않는다는 것입니다. 따라서 fflush(stdin)하는 것은 undefined behavior, 즉 정의되지 않은행동. 따라서 사용하지 말아야 할 행동입니다.

그러면 scanf가 쭈루룩 넘어가는 진상은 과연 어디에 있는가? 입력 버퍼를 비우는 방법은 없는 것인가? 하는 두가지 의문이 드실 겁니다. 일단 첫번째 문제에 대해서 한번 살펴보도록하죠^

scanf는 특성상 개행문자를 입력받지 않는다고 합니다. 따라서 \n을 입력버퍼에 그대로 남겨두게 되고, 다음 번 scanf가 그놈때문에 자동으로 넘어가는 현상이 생기게 되는 것입니다. 따라서 scanf다음에 getchar()등으로 개행문자를 소비해주는 입력함수를 넣어주면 그런 문제를 막을 수 있습니다.

int a;

scanf("%d", &a);
getchar();

그럼 두번째 질문인 입력버퍼에 대해서 알아보도록 하죠. 일반적으로 키보드의 입력 버퍼를 비우는 행동은 표준함수로 제공되지 않습니다. 따라서 그런 행동들은 운영체제나 컴파일러 제조사에 따라 다르다는 이야기입니다. 일반적으로 dos시절에는 아래 함수를 사용해서 입력 버퍼를 비울 수 있었습니다.

while(!kbhit())
    getch();

그리고 gcc를 사용하는 경우에는 stdio.h에 정의된 flushall함수를 사용해서 입력 버퍼를 비울 수 있습니다.

일반적으로 scanf의 경우 입력받은 값이 잘못된 경우 이전 상태로 복원시키는 방법을 전혀 제공하지 않습니다. 따라서 보통의 경우 입력은 문자열로 fgets등을 통해서 입력받은후 sscanf내지는 자신이 직접 제작한 입력함수를 통해서 파싱해 내는 것이 일반적입니다.

참 내가 썼지만 깜찍했네 ㅋㅋㅋ~

@codemaru
돌아보니 좋은 날도 있었고, 나쁜 날도 있었다. 그런 나의 모든 소소한 일상과 배움을 기록한다. 여기에 기록된 모든 내용은 한 개인의 관점이고 의견이다. 내가 속한 조직과는 1도 상관이 없다.
(C) 2001 YoungJin Shin, 0일째 운영 중