프로그래밍/C언어.

getchar(), getch(), getche()의 차이점. 예제소스 & 그림

K_Coder 2012. 2. 26. 15:28

알듯 모를듯 한 미묘한 3가지 함수의 차이점에 대해서 파헤쳐 보자 -_-!!
 

getchar(), getch(), getche()의 차이점 !!

비슷해 보이는 3가지 종류의 함수가 있다.
차이가 뭘까? 어떻게 보면 사실 결과는 같을 수도 있다.

가장 기본적으로 
getchar()은 #include <stdio.h>
getch(), getche()는 #include <conio.h>
  해야 사용이 가능하다.

비교

getchar()

getche()

getch()

버퍼 사용

O

X

X

화면 표시

O

O

X

종료 인식

\n

\r

\r


첫번째 버퍼 사용 여부의 차이

버퍼를 사용하는 경우( getchar() )
입력을 하면 바로 들어가는게 아니라 입력버퍼 라는 곳에 담긴다. 
 
엔터가 들어올 때 까지 입력을 계속 담아두다가 엔터가 들어오면 입력을 중지하고
지금까지 입력된 내용에서 첫 글자를 리턴한다
 
따라서 잘못 입력해도 엔터를 치기 전엔 수정 가능하다.

getchar() 예제
 
#include <stdio.h>
int main()
{
	char ch;

	ch = getchar();		// 1 문자 입력.
	printf("%c", ch);	// 1 문자 출력.

	printf("\n");
	return 0;
}


getchar() 는 한글자를 입력 받는 함수이지만,
입력 버퍼를 사용하므로, 엔터가 입력 될 때 까지 입력을 계속 받아 버퍼에 담아둔다.

그리고 엔터가 들어오면 입력을 종료하고 버퍼중에서 가장 첫번째 글자를 리턴.

ch 에 K 가 들어가게 되고, printf() 문에 의해서 출력이 된다.




버퍼를 사용하지 않는 경우( getch(), getche() )
키보드를 눌렀다가 떼는 동시에 그 값을 가져가 버린다.
그렇기 때문에 잘못 입력하고 백스페이스를 누르면 삭제되기는 커녕 백스페이스 값도 들어간다..- -;; 


getch() 예제
 
#include <stdio.h>
#include <conio.h>		// getch() 사용을 위해 필수.
int main()
{
	char ch;

	ch = getch();		// 1 문자 입력.
	printf("%c", ch);	// 1 문자 출력.

	printf("\n");
	return 0;
}


getch()는 마찬가지로 한글자를 입력 받지만,
입력 버퍼를 사용하지 않는다. 따라서 엔터를 입력할 때 까지 기다리지 않는다.

얼핏 보면, K를 입력하고 출력이 안된거 같은,
또는 입력을 하지 않고 출력만 한거 같은 착각을 불러 일으킨다.

하지만 실제로 동작하는 원리를 알면 다르다는 사실을 알 수 있다.
K 에서 ?손을 떼는 순간 바로 ch 에 들어가고, printf()문에 의해서 출력된다. 

키보드에서 K를 눌렀지만 getch()는 입력 값을 화면에 보여주지 않는다.
게다가, 입력 버퍼라는 중간 과정이 없으니 대기하는 과정이 보이지 않고
바로 출력이 되어 버려서 착각을 일으키는 것이다.

결과적으로 위에서 나온 K 라는 글자는
입력 시에 화면출력을 하지 않는 getch()의 특성상 입력 한 K는 무시되고
출력으로 인해 K 라는 글자가 나타난 것이다.  




getche() 예제

 
#include <stdio.h>
#include <conio.h>		// getche() 사용을 위해 필수.
int main()
{
	char ch;

	ch = getche();		// 1 문자 입력.
	printf("%c", ch);	// 1 문자 출력.

	printf("\n");
	return 0;
}


getche()는 getch()와 동일하지만 입력 값을 화면에 출력하는 차이가 있다.

따라서 과정은 getch()와 동일하며, 다만. 입력한 K를 화면에 보여줘서
내가 입력한 K가 화면에 보이고, 그 값을 printf()가 찍어서 K가 찍혀서
K가 연달아 보이는 것이다.




두번째
 화면표시의 차이. 

단순하다. getch()의 경우 입력하는 값이 화면에 나타나지 않는다. - -;
getch()를 반복해서 여러개 받는다고 해도, 화면에는 나타나지 않는다.

getche() 의 경우 입력하는 값이 화면에 출력되며 이를 ehco 라고 해서 앞자를 딴 e가 붙는다고 한다.
getchar() 또한 화면에 나타난다.



세번째 종료인식의 차이.

각각의 함수가 Enter 값을 인식하는데 차이가 있다.
getchar()의 경우 \n 으로 인식,  getch(), getche() 는 \r 인식한다.

뭐 별거 있나? 싶기도 한데. 이로 인해 알아야할 중요한 내용이 있다.

아래의 예제 소스를 살펴 보도록 하자.
#include <stdio.h>
void main()
{
	char tmp;
    
	while( (tmp = getchar()) != '\n')
	{
		putchar(tmp);
	}

	printf("\n종료됨\n");			// 반복문 탈출
}


while문의 종료 조건을 자세히 보자. '\n' 과 비교하고 있다.
즉, \n 값이 들어오면 반복문을 종료 하라는 의미가 된다.

아래 화면에서 보면 test가 두번 찍힌 것을 알 수 있다. 이유가 뭘까? 첫번째 test는 내가 입력하면서 적힌 내용이다.
test를 입력하고 엔터를 치면, while문의 getchar() 에 의해서 test라는 글자가 입력 버퍼로 들어감. (때문에 화면에 test가 남음)
 
그럼과 동시에 첫 글자인 t가 tmp에 들어가고 putchar(tmp)에서 t를 출력한다.
이게 두번째 줄의 t 이다. 그리고는 다시 getchar()을 실행 하는데,

입력버퍼에 아까 입력한 값이 남아 있으므로 더 이상 값을 입력 받지 않고
est 중에서 첫번째 글자인 e 를 tmp에 저장하고 putchar(tmp)로 출력.

이를 반복해서 test 가 찍히고 마지막으로 엔터 입력으로 들어간 \n 가 빠져나오면서
조건문과 비교해 \n 이므로 탈출하게 되는 것.



test 후에 엔터를 입력하자 test를 출력하고 반복문을 빠져나왔다. 이는 엔터 입력시 '\n' 로 처리함을 알 수 있다. 


이제 getch()와 getche()에 위와 같은 소스코드를 적용해 볼자.

#include <stdio.h>
#include <conio.h>				// getch() 사용을 위함.
void main()
{
	char tmp;
    
	while( (tmp = getch()) != '\n')
	{
		putchar(tmp);
	}

	printf("\n종료됨\n");			// 반복문 탈출
}

이번에도 동일한 코드에 getch()로만 바꿔 보았다.

일단, 이번엔 test가 한번만 나온 이유를 알아보자. getch()는 화면에 출력을 하지 않는다.
따라서 화면에 보이지 않게 t가 들어가고 tmp로 저장된 후 바로 putchar(tmp)로 인해서 화면에 t가 출력된다.
엔터 입력 없이 바로 출력이 되버려서, 마치 내가 입력한 글자가 보이는 것처럼 착각 할 수 있으나, 절대 아니다.

이렇게 test를 키보드에서 손을 떼자마자 putchar(tmp)로 출력을 해댄다. 그리고 엔터를 입력
원래 기본적으로 글자의 마지막에 있어야 할 커서가, t 밑에 가 있는 것을 알 수 있다.
\r 이라는 의미인데, \r 이란. 케리지 리턴으로 커서를 현재 행의 처음 위치로 돌리는 것이다.
게다가 while문이 끝나지도 않고 계속 입력을 받게 되고. 당연히 while문 밖에 있는 출력문은 나오지 않는다.


test의 t 에 커서가 입력을 대기하고 있다.
이것으로 \r 으로 처리한다는 것을 알 수 있지만. 의심이 많은 사람을 위해
\r 로 바꿔서 while문을 돌려보자. 그래서 while문이 종료가 된다면 맞는거겠죠?ㅎㅎ



조건문에서 \n을 \r로 바꾸어서 실행해 보자.
#include <stdio.h>
#include <conio.h>				// getch() 사용을 위함.
void main()
{
	char tmp;
    
	while( (tmp = getch()) != '\r')	// \n 에서 \r로 변경
	{
		putchar(tmp);
	}

	printf("\n종료됨\n");			// 반복문 탈출
}



짜잔 ~ 정상적으로 종료가 되었다.

결론을 이야기 하자면 getch(), getche() 로 문자를 반복적으로 입력 받다가
엔터 입력시 종료 하고 싶다면 조건문에 '\r' 과 비교를 해주어야 한다.