본문 바로가기

C언어

20. 표준 입 · 출력과 버퍼(Buffer)

1) 표준 입 · 출력 기반의 버퍼(Buffer)

지금까지 사용했던 scanf, printf, putchar, getchar 함수들은 모드 표준 입출력 함수라 한다.

이러한 표준 입 · 출력 함수를 사용하는 경우에는 버퍼라는 것을 제공받게 된다는 특징이 있다. 여기서 말하는 버퍼는 '여분의 임시 메모리 공간' 이라고 생각하면 된다.



키보드를 통해서 입력하는 데이터는 실행중인 프로그램으로 바로 읽혀지는 것이 아니라, 일단은 입력 버퍼라는 곳에 저장이 된다는 것을 알 수 있다. 그리고 나서 입력 버퍼에 존재하는 데이터가 프로그램으로 이동하는 것이다.

이렇듯 프로그램상에서 printf와 같은 함수 호출을 통해서 모니터에 데이터를 출력하려는 경우에도 바로 출력이 이뤄지는 것이 아니라, 일단은 출력 버퍼라는 곳에 저장이 되었다가 출력 스트림을 통해 모니터에 전송

그렇다면 키보드로부터 입력된 데이터가 입력 스트림을 거쳐서 입력 버퍼로 들어가는 시점이 언제인가? 키보드로 데이터를 입력하고 나서 Enter 키를 누르는 시점이 바로 데이터가 입력 버퍼로 들어가는 시점이다.

고로 Enter키를 누르기 전까지는 입력 버퍼가 비어있다.

2) 버퍼링(Buffering)을 하는 이유는 무엇인가?

버퍼링이란 데이터를 전송 하는데 있어서 목적지로 바로 보내는 것이 아니라, 중간에 버퍼(여분의 임시 저장소)를 둬서 전송하고자 하는 데이터를 임시 저장해 두는 것을 말한다. 임시 저장된 데이터가 어느 정도 채워지면 한꺼번에 데이터를 전송하게 된다.

버퍼링은 사용하는 이유는 ? 성능의 향상이 그 이유이다. 데이터를 키보드로부터 입력받거나, 데이터를 모니터로 출력하는 것은 여러분이 생각하는 것보다 시간이 걸리는 작업들이다.

그럼에도 불구하고 이러한 작업들(I/O 작업이라 한다)은 컴퓨터가 처리해야 하는 많은 일들과 비교해서 상대적으로 중요도가 떨어지는 작업들이다. 즉 지금 컴퓨터가 바쁘다면, 이러한 입 · 출력과 관련된 일들은 뒤로 미뤄도 된다는 것이다.

3) 버퍼를 비우는 작업을 하는 fflush 함수

가끔은 입 · 출력작업도 긴급을 요하는 경우가 있기 마련이다. 이러한 성능 향상을 목적으로 존재하는 퍼버링이 부담될 수 밖에 없다. 이럴때 유용하게 사용되는 함수이다.


#include <stdio.h>

int fflush(FILE * stream);


fflush 함수의 인자로 전달되는 스트림의 버퍼를 비워버린다. 여기서 비워버린다는 의미는 전달되는 스트림의 종류에 따라서 달라진다. stdin과 같은 입력 스트림이 전달되면 입력 버퍼 안에 존재하는 테이터들은 모두 버려지게 된다.(지워지게 된다.) 그러나 stdout과 같은 출력 스트림이 인자로 전달되면 출력 버퍼 안에 존재하는 데이터들은 목적지를 향해서 출발하게 된다.(즉시 출력이 이뤄진다.)



#include 

int main(){
	char perID[7];	// 6 + null문자 = 7
	char name[10];

	fputs("주민번호 앞 6 자리를 입력 하세요 : ", stdout);
	fgets(perID, sizeof(perID), stdin);

	//fflush(stdin); // 입력 버퍼를 지운다.

	fputs("이름을 입력하세요 : ", stdout);
	fgets(name, sizeof(name), stdin);

	printf("주민번호 앞자리 : %s\n", perID);
	printf("이           름 : %s\n", name);

	return 0;
}


10줄에 fflush함수가 주석처리 되있는 상태에서 실행해보자
실행시 전체 주민등록 번호를 입력해 보자

10번줄 주석 처리시 실행결과

주민번호 앞 6 자리를 입력 하세요 : 881106-1234567
이름을 입력하세요 : 주민번호 앞자리 : 881106
이           름 : -1234567



fgets함수 호출시 키보드를 통해서 입력받은 문자들은 일단 입력 버퍼에 저장이 된다.
그 다음 실행중인 프로그램으로 문자열이 전송되는데,
입력받은 문자가 8번째 줄의 fgets함수에서 요구하는 문자의 수보다 많기 때문에 입력 버퍼에 있는 데이터는 한번에 읽혀 지지 않는다. 즉, 읽혀지고 남은 문자들이 여전히 버퍼에 존재하게 된다.

그 다음 13번줄의 fgets 함수가 호출될 때는 여전히 문자가 남아 있기 때문에 키보드로 부터 문자열을 입력받지 않고, 버퍼에 남아 있는 문자들을 읽어 들이게 되서 원하는 결과를 얻지 못한다.

10번줄 주석을 제거한 실행결과

주민번호 앞 6 자리를 입력 하세요 : 881106-1234567
이름을 입력하세요 : 홍길동
주민번호 앞자리 : 881106
이           름 : 홍길동