BLOG ARTICLE flush | 1 ARTICLE FOUND

  1. 2007.11.07 c언어에서 입력버퍼 비우기 10

c언어에서 가끔 발생하는 문제가 scanf로 입력받다가
입력버퍼가 다 비워지지 않아서 문자입력받는게 씹히는 경우가 생긴다.
c언어 공부하다보면 꼭 한번쯤은 겪어보는 문제
예를 들면

#include <stdio.h>

int main()
{
        char string[20];
        char c;

        scanf("%s", string);
        scanf("%c", &c);

        printf("%s\n", string);
        printf("!!%c!!\n", c);

        return 0;
}

실행 결과는?

문자열만 입력받아버리고 프로그램이 끝나버린다.

원인은
scanf("%s", string);
가 실행되고 나서 입력버퍼에는 개행문자가 그대로 남아있는 거다.

그래서
scanf("%c", &c);
를 실행하려고 보니 버퍼에 개행문자가 있어서 그걸 c에다 넣어버린거다.
정작 표준입력으로는 아무것도 입력안했는데
예전에 이걸 몰라서 개고생한거 생각하면..

해결방법은
입력버퍼를 비우면 된다.

어떻게?
        scanf("%s", string);

       scanf("%c", &c);
이 두 사이에 입력버퍼를 비워주는 뭔가를 해주면 된다.

1. 간단하게는 getchar(); 를 추가하는 걸로도 가능

2. fflush(stdin); 추가
그런데 이건 gcc에서 안돌아간다. 왜? 당연히 안된다. 표준 fflush함수는 출력버퍼를 비우는 녀석이다.
VC에서는 확장해서 사용하므로 동작하지만 gcc는 안된다.

3. tcflush(0, TCIFLUSH); 추가
0번 디스크립터를 비워라. 그런데 이는 유닉스 계열에서 터미널과 관련된 함수인 듯

4. rewind(stdio); 추가
rewind함수는 매개변수로 들어온 스트림을 초기화하는데 사용

5.
__fpurge(stdin);
이놈도 리눅스에서만 동작하고 표준은 아니다. stdio_ext.h 추가.

6.
fgets(string, sizeof(string), stdin);
문자열 입력을 scanf가 아니라 fgets로 받는다.
그러나 입력시 사이즈를 오버하면 똑같은 문제가 발생한다.
그리고 사이즈를 오버하지 않더라도 문자열 끝에 개행문자가 추가된다.

그래서 다음 줄에
string[strlen(string)-1] = '\0'; 로 강제로 널문자를 넣어준다.
개인적으로 제일 많이 사용하는 방식

7. scanf("%*c", c);
%*c는 입력은 받지만 저장은 안한다. 즉 비어있는 \n를 날려버린다.

8. scanf("%c", &c);를 scanf(" %c", &c); 로
%c 앞에 공백을 추가하면 white space를 구분자로 인식한다.


입력들이 간단하게 위와 같이 나온다면 위의 방법들 아무거나 사용해도 되지만
복잡한 입력에 입력버퍼에 뭔가 많이 남는다면
버퍼를 비우는 것이 근본적인 해결방법인듯 하다.



상황에 따라 적절히 골라쓰면 될 듯..

AND