본문 바로가기
프로그래밍/C

버퍼를 사용하는 입력 함수

by 길냥이 2025. 6. 9.

목차

  1. scanf 함수의 문자 입력 과정
  2. getchar 함수를 이용한 문자열 입력
  3. 입력 버퍼 지우기

 

1. scanf 함수의 문자 입력 과정

scanf 함수는 분명 좋은 입력 함수이지만, 자꾸 예상하지 못한 에러를 내는 경우가 많습니다.

이제부터는 입력 함수의 내부 동작에 대해 조금 더 깊이 알아보도록 하겠습니다.

 

우리가 키보드를 통해 어떤 값을 입력하면, 그 값은 곧바로 변수에 저장되는 것이 아닙니다.

먼저 입력 버퍼(input buffer)라는 공간에 머무르며, 이 버퍼는 메모리의 한 영역으로 입력된 데이터가 잠시 머무는 공간입니다.

이후 scanf 함수가 호출되면, 버퍼에 있는 데이터 중 해당 형식에 맞는 값을 읽어 변수에 저장합니다.

 

예를 들어 다음과 같은 코드가 있으면..

char ch;
scanf("%c", &ch);

사용자가 키보드로 A를 입력하고 엔터를 치면, 버퍼에는 A와 \n도 버퍼에 들어갑니다.

버퍼는 한 줄 단위로 저장되어요.

 

하지만 %c 형식 지정자는 문자 하나만 읽기 때문에, scanf는 A를 ch에 저장하고 나머지 \n은 버퍼에 남겨둡니다.

 

이와 같은 특성 때문에, 이후 입력을 받을 때 남아있는 버퍼의 문자들이 영향을 줄 수 있습니다.

이것이 바로 scanf를 사용할 때 종종 에러가 발생하는 이유입니다.

원리는 다음과 같아요.

만약 키보드를 통해 A \n을 하면..

다음과 같이 버퍼에 들어가고

scanf 함수는 형식에 맞는 문자만 버퍼에서 꺼내고, 그 외의 문자는 남겨둡니다.

지금 같은 경우는 A만 버퍼에서 꺼내고 나머지는 버퍼에 그대로 남아있어요.

따라서 버퍼에 남은 \n과 같은 공백 문자들이 나중에 입력받을 때 영향을 줄 수 있어요.

 

2. getchar 함수를 이용한 문자열 입력

음... 

프로그램의 사용자가 키보드로 한 줄을 입력할 때 입력을 끝내려면 Enter을 누르면 됩니다.

그런데, 이것도 입력 데이터로 사용하고 싶으면요?

 

음.. 그럴 때는 scanf 함수의 반환값을 이용하면 된답니다.

scanf 함수는 키보드로 Ctrl + Z를 누르면 -1을 반환합니다. 

 

그러면 한번 실습해봅시다!

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
	char ch;   //문자를 입력받을 변수

	while (1)
	{
		ch = getchar();      //변수를 입력받음
		printf("%d  ", ch);  //변수의 아스키코드 값 출력
	}

	return 0;
}

출력은 다음과 같아요.

d? /:) 13
100  63  32  47  58  41  32  49  51  10

이해하기 쉽게 표로 만들자면 다음과 같습니다.

 

d ? ' ' / : ) ' ' 1 3 \n
100 63 32 47 58 41 32 49 51 10

왜 Enter을 쳤을 때 printf가 실행되고요?

사실 위쪽에 우리가 쓴 글은 버퍼이고, getchat은 그 값을 ch에 바로 저장하지 않습니다.

 

먼저 입력 버퍼(input buffer)에 저 값을 저장한 다음, 엔터를 쳐서 입력을 끝내면..

버퍼에 한 줄 단위로 저장되고, 

 

getchar이 저 값을 버퍼에서 차례로 받아오면서 while문이 반복되는 거랍니다.

결론적으로, 엔터를 치기 전에는 버퍼에는 아무것도 들어가지 않아요.

 

원한다면 엔터를 통해 출력값을 받은 후 계속 숫자를 입력할 수 있습니다.

나갈 때는 그냥 우상단의 X키를 통해 나가세요. 이 프로그램은 자동적으로 종료하지 않아요.

 

3. 입력 버퍼 지우기

scanf 함수와 getchar 함수는 같은 버퍼를 사용합니다. 입력 데이터를 공유한다는 소리죠.

왜 같은걸 쓰냐고요? 표준 입력 스트림(stdin)을 사용하기 때문이에요.

 

아무튼 입력 데이터는 공유되기 때문에, 앞서 수행한 함수가 남긴 잔여물을 뒤에 실행하면서 가져가 버릴 수 있어요.

이러한 문제로 발생하는 버그들을 예방하기 위해, 버퍼에 쌓인 잔여물들을 미리 제거하는 것이 좋습니다.

 

입력 버퍼의 내용을 지우는 건 간단합니다. 버퍼에 남아 있는 문자들을 모두 입력해서 사용하지 않고 버려버리면 됩니다.

 

한번 예제를 볼까요..

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main(void)
{
	int num, grade;

	printf("학번 입력 : ");
	scanf("%d", &num);
	getchar();

	printf("학점 입력 : ");
	grade = getchar();
	printf("학번 : %d, 학점 : %c", num, grade);

	return 0;
}

출력은 다음과 같습니다.

 

학번 입력 : 609
학점 입력 : B
학번 : 609, 학점 : B

과정은 다음과 같아요.

 

printf로 입력하면 버퍼가 다음과 같이 받고..

변수 num에는 609가 저장됩니다. %d니까요.

 

이때 버퍼에 남은 \n은 9줄의 getchar을 통해 지워집니다.

그리고 학점을 입력하면 버퍼에는 다음과 같이 저장되고

getchar을 통해 A만 가져와서 grade에 저장합니다.

 

즉, 마지막에 버퍼에는 \n이 그대로 남아 있답니다.

 

여담으로, 9행의 getchar 함수가 없다면 학점에는 무조건 \n이 저장됩니다.

'프로그래밍 > C' 카테고리의 다른 글

변수 저장 유형  (2) 2025.06.11
변수 사용 영역  (0) 2025.06.10
문자  (2) 2025.06.07
배열을 처리하는 함수  (0) 2025.06.06
배열과 포인터의 관계  (0) 2025.06.05