본문 바로가기

프로그래밍

scanf / gets / getchar

C 프로그래밍 파워 업그레이드 - 윤성우 참조.


프로젝트 틀을 만드는 중 gets로 문자열을 받을 때 에러가 생겼다. 이미 한번 아는 문제라 쉽게 해결했지만 머리 속에 내가 정리가 되지 않았구나 하는 생각이 들어서 블로깅을 해본다.



문장은 문자열일까? - ex: Good morning?

단어는 문자열일까? - ex: Good

일반적인 관점에서는 모두 문자열이다.
그렇기 때문에 "문자열"을 입력 받는다는 표현은 애매한 표현이다.

C언어의 "문자열"을 입력 받는 대표적인 함수에는 scanf(), gets()가 있다.
이 둘의 차이는 무엇일까?

그것은 문장과 단어의 차이다.
문장은 공백이 포함된다. 이 때 공백에는 띄어쓰기, 탭, 개행이 포함된다.
단어는 공백이 포함되지 않는다.

scanf는 단어를 받는 함수이다.
만약에 scanf("%s", buf); 라는 문장이 실행되는 동안 입력을 Good morning? 이라고 한다면 buf에는 Good밖에 입력되지 않는다.
그러나 gets(buf); 를 통해 입력 받는다면 buf에는 Good morning? 이 모두 들어가 있다.



이제 getchar를 이야기 하기 전에 데이터 입력 받을 때의 버퍼들에 대해 알 필요가 있다.

기본적인 C언어 문법을 다루는 책에서 소개하는 버퍼는 다음과 같다.

입력 함수를 위한 버퍼 하나. - 입력 버퍼
그래서 우리가 머리 속에 그리는 모습은

1. 키보드로 입력을 하고 엔터를 친다.
2. 그것들이 즉시 입력 버퍼에 다 넣어진다.
3. 그리고 그 입력 버퍼에서 내가 지정한 버퍼(예를 들어 char buf[BUF_SIZE]와 같은 변수로 선언한)에 입력된다.

로 생각할 수 있다.

이런 생각은 좀 더 간소화된 모습이고 좀 더 자세하게 보자.

일단 버퍼는 2개가 존재한다. 
- 키보드 입력 버퍼와 프로세스 입력 버퍼

키보드 입력 버퍼는 내가 키보드를 치는 문자열들이 즉시 이동하는 곳이다.
그리고 프로세스 입력 버퍼키보드에 엔터를 눌렀을 때, 키보드 입력 버퍼에 그 동안 입력된 문자열들이 이동하는 곳이 프로세스 입력 버퍼이다.
그 후 입력 함수들이 이 프로세스 입력 버퍼에서 문자 데이터를 읽어 들이는 것.

즉, 
1. 키보드로 입력을 하는 즉시 키보드 입력 버퍼에 저장.
2. 내가 엔터를 치는 순간, 키보드 입력 버퍼에서 프로세스 입력 버퍼로 이동
3. 해당하는 입력 함수가 각각의 역할에 따라 프로세스 입력 버퍼로부터 특정 일을 시작

으로 생각할 수 있겠다.



그럼 getchar의 함수 이용법과 scanf의 주의점을 보자.


getchar 함수를 이용하는 코드이다.

getchar 함수는 입력 버퍼(프로세스 입력 버퍼)로부터 문자 하나하나를 입력 받는다.
여기서 우리는 fflush를 왜 쓰는지 이해할 필요가 있다.
버퍼를 비우기 위해서 fflush를 사용한다. 왜 비워야 할까?
여기서 알아야 할 것은 우리가 키보드를 누르는 엔터 자체도 아스키 코드 값을 갖고, 이것은 하나의 공백에 해당한다. 즉, getchar함수를 문자 하나 하나만 받기 위해 사용한다면 그리고 우리는 계속 하나의 문자만 입력 받는다면 (ex - a[ENTER], b[ENTER] 등등) 우리가 원하는 것은 a 또는 b 만일 텐데 프로세스 입력 버퍼에는 ENTER도 있는 것. 그렇기 때문에 이 때는 ENTER를 프로세스 입력 버퍼에서 지워야 한다. 그래서 사용하는 것이 바로 fflush.



scanf에서 주의할 것은 무엇인가?
그것은 바로, 문자 단위 즉 %c 를 이용해서 scanf 함수를 사용할 때는 Enter 키와 같은 공백 문자가 하나의 데이터로 인정을 받는다. 그러나 그 외의 경우는 인정 받지 못 한다.

아래의 코드를 보자.


scanf는 %c를 이용할 때는 엔터키도 공백으로 인정 받는다. 그러나 %d는 10진수 정수형을 받을 때 이용된다. 그러므로 우리가 10[엔터]를 눌렀다면 [엔터]는 인정 받지 못 한다. 그러므로 fflush가 불필요.

그러나 %c를 이용하여 하나의 문자로 받는다면 이 때는 [엔터]키도 하나의 공백으로 인정 받고 그렇기 때문에 fflush가 필요해진다.