[C] 사용자에게서 문자를 입력받는 방법

프로그램을 작성하다 보면 사용자로부터 입력을 받을 일이 생긴다. 그래서 다음과 같이 작성하곤 한다.

#include <stdio.h>

int main() {

        char a_char;

        int a_int = 0;

        printf("input one char\n");
        scanf("%c", &a_char);

        printf("%c", a_char);

        printf("input one char\n");
        scanf("%c", &a_char);
        //doesn't get input

        printf("%c", a_char);

}

그런데 저렇게 작성하면 두 번째 scanf 함수에서 사용자의 입력을 받지 않고 그냥 넘어갈 것이다.

버퍼

scanf 함수는 사용자의 입력을 직접 받지 않는다. 키보드의 입력을 먼저 버퍼에 저장한 다음, 버퍼를 읽어서 변수로 넘겨준다.

이 때 마지막으로 입력한 개행문자 Enter까지 버퍼에 저장된다. 그리고 scanf 함수는 버퍼를 개행문자가 나올 때까지 읽는다.

첫 번째 scanf 함수는 개행문자 전까지만 읽어서 변수에 저장하고, 두 번째 scanf 함수는 그 다음부터 읽는데, 이 때 개행문자가 나와버려서 그냥 넘어가는 것이다.

해결책

이 것을 방지하려면 다음 입력을 받기 전까지 버퍼에 남아있는 개행문자를 제거해주면 된다.

한 글자 무시하기

getchar()

버퍼에서 한 글자를 무시한다. 여기서는 개행문자를 무시하고 지나간다.

공백 추가하기

scanf(" %c", &a_char);

다음과 같이 %c 앞에 공백을 추가해주면 공백이나 개행과 같은 버퍼를 무시하고 입력을 받아올 수 있다.

입력 받아 저장 안하기

scanf("%*c", c);

입력은 받지만 저장은 안한다. 즉 비어있는 \n를 날려버린다.

입력 스트림 비워버리기

fflush(stdin);

그런데 이 방법은 표준이 아니다. 그리고 fflush 함수는 출력 스트림에만 사용하는 함수이다. 입력 스트림에는 쓰지 않는 것이 좋다.

가장 추천하는 방법

void flush() {
  while(c=getchar() != '\n' && c != EOF);
}

이렇게 생긴 함수를 만들어서 쓰면 된다.
입력 스트림에서 개행 문자나 EOF를 만날 때까지 한 문자씩 슥삭! 해버린다.
입력받은 다음 이 함수를 호출해서 버퍼를 비워주자.

문자 입력 함수

C에는 scanf 말고도 문자 입력 함수가 많다. 몇 개만 살펴보자.

getchar()

int getchar(void);

이 함수는 stdin, 즉 표준 입력 스트림에서 문자 하나를 받는다. 성공하면 문자의 아스키 코드 값을 반환하고, 아니면 EOF를 반환한다.

getc()

int getc(FILE *stream);

위에서도 살펴보았던 함수다. 이 함수는 getchar()와 같지만 입력 스트림을 선택할 수 있다.

getch()

int getch();

표준 함수는 아니다.
이 함수도 한 개의 문자를 받지만, 버퍼를 사용하지 않고 직접 입력받는 것이 다르다.

gets()

char * gets ( char * str );

문자열을 입력받는 함수이다.
표준 입력에서 문자들을 개행 문자 (‘\n’) 이나 파일 끝(EOF) 를 만나기 전 까지 가져와서 str 에 저장한다.
이 때, 개행 문자 (‘\n’) 은 문자열에 포함되지 않는다.
널 문자 (‘\0’) 는 문자열 맨 마지막에 자동적으로 추가된다.

fgets()

char * fgets ( char * str, int num, FILE * stream );

gets 함수와 거의 같지만, 입력받은 문자열 끝에 개행문자가 포함된다.

댓글