C언어 입력버퍼 지우기

Yk Lee·2022년 6월 9일
0

C언어

목록 보기
1/3

버퍼


버퍼란?
1.특정 크기의 메모리 공간을 의미한다
2.운영체제는 입력과 출력을 돕는 입출력 버퍼를 생성하여 제공한다
3.표준 입출력 함수를 기반으로 데이터 입출력시 입출력 버퍼를 거친다.
입력버퍼는 키보드를 통해서 입력하는 데이터는 바로 프로그램으로 읽혀지는 게 아니라, 입력버퍼라는 곳에 저장이 되고 이 입력버퍼에 존재하는 데이터가 입력 스트림을 타고 프로그램으로 이동하는 것이다.
입력버퍼가 반환되는 시점은 엔터를 입력했을때의 시점이다.
출력버퍼는 프로그램으로부터 받은 데이터를 바로 출력하지 않고 버퍼에 모아두었다가 출력한다.
호출된 출력함수가 반환되는 시점이 출력버퍼로 데이터가 완전히 전송되는 시점이다.
이러한 버퍼링을 하는 이유는 데이터의 이동의 효율과 관련이 있다. 데이터를 모아서 전송하는 것이 하나씩 전송하는 것보다 효울적이기 때문다. 그리고 CPU 성능과의 차이도 존재한다.
키보드가 1개를 입력하고 처리하면 CPU는 그 짧은 시간안에 10개 이상의 데이터를 처리할 수 있기 때문이다.

버퍼비우기

출력버퍼를 비우는 것은 출력버퍼에 저장된 데이터를 지우는 것이 아니라 출력 버퍼에 저장된 데이터를 목적지로 최종적으로 전송한다는 것을 의미한다.

#include<stdio.h>
int fflush(FILE * stream);
//성공시 0, 실패시 EOF 반환

입력버퍼를 비우는 것은 입력 버퍼에 저장된 데이터의 소멸을 뜻한다. 그럼 어케 지워야 할까 방법은 많지만 필자는 단 하나의 케이스만 정리할 것이다.

#include <stdio.h>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
void clearInputBuffer(void);


int main(){
	char number[7]; 
	char name[4];
	char a[5];
	
	
	fputs("주민번호를 입력해주세요: ", stdout);
	fgets(number,sizeof(number),stdin);  // 최대 크기 7byte를 키보드로부터 입력받음
	clearInputBuffer(); //입력버퍼 비우기. 반환없이 읽어들임
	
	fputs("이름을 입력하세요: ", stdout);
    fgets(name, sizeof(name), stdin); //최대 크기 4byte를 키보드로부터 입력 받음.
    clearInputBuffer();

    
    fputs("성별을 입력하세요: ", stdout);
    fgets(a, sizeof(a), stdin);
    
    printf("주민번호: %s \n",number);
    printf("이름: %s \n",name);
    printf("성별: %s ",a);
   
   return 0;
}
void clearInputBuffer(void)
{
    // 입력 버퍼에서 문자를 계속 꺼내고 \n를 꺼내면 반복을 중단
    while (getchar() != '\n');
}

결과

자 결과를 봐보면 주민번호 6자리는 잘 입력됐는데
웬걸 이름이 이상하다. 답은 간단한다. 첫번쨰로 이름 배열을 4byte로 설정했고 한글은 2byte를 먹는데 그래서 홍만 나오게 된다. 홍길이 안나오는 이유는 홍길 다음에 개행문자인 "\n"이 있기 때문이다. 자그럼 여기서 홍길동만 나오도록 해보자. 홍길동은 3글자로 6byte고 "?" 가 안나오도록하려면 개행문자 1byte가 필요하니 총 name[7]을 선언한다.

음 잘나온다.
위에 내용은 둘째 치고 왜 입력 버퍼 지우기를 해야 하는지 알아야한다.
fgets함수에 지정된문자열의 길이보다 더 긴 문자열이 들어올 경우 stdin 버퍼에 입력 받고 남은 문자들이 남아있는데 이것을 없애줘야지 문제가 발생하지 않는다.
stdin 버퍼에 남아있는 문자들은 '\n' 문자가 나올때까지 무한루프를 도는데 그 이유는 Enter가 나올떄까지 입력 스트림에서 버퍼로 저장되기 떄문이다. 즉 \n이 마지막에 존재할 꺼다. 그래서 \n이 나올떄까지 무한루프를 돌리면 입력 버퍼는 깨끗이 비워진다. 입력버퍼를 비우지 않으면 문제가 생기는데

이런 결과값이 나타나게 된다.
이름을 입력도 하지도 않았는데 뒤에 나머지 숫자들이 이름에 입력이 되어버렸다
그럼 why?
6자리 숫자가 number에 {'1','2','1','2','1','2','\0'} 저장이 된다.
하.지.만
stdin 버퍼에는 -121212가 남아있고 그상태에서 fgets 함수가 호출되면서 자동으로 name에 {'-','1','2','1','2','1','\0'}이 저장되면서 값이 바로 나와버리는 상황이면서 동시에 stdin 에는 {'2','\n'}가 남게되었다.
이때 while (getchar() != '\n'); 를 입력하고 돌리면 number에 {'1','2','1','2','1','2','\0'} 저장이 된 후 나머지 {'-','1','2','1','\0'}를 while문의 getchar함수로 버퍼에 남아 있는 것을 문자단위로 읽어 들인다. 그 후 \n과 비교하여 \n이 아니면 남아 있는 것을 계속 읽어들이면서 비워낸다. 마지막으로 \n이 나타나면 반복문이 종료되면서 버퍼에는 아무것도 남아 있지 않게 된다. 다순히 사용만하고 저장하지 않으면 비워지게 되는 것이다.
getchar 함수는 문자열과 문자를 입력 받고 바로 지정된 변수에 저장되는 것이 아니라 입력 버퍼에 저장이 된다. 반환값으로 입력버퍼에서 문자 한개를 꺼내서 함수를 선언한 변수에 값을 저장한다. 그러니 while문을 돌고 지정된 변수가 없이 그냥 선언됐고 따로 저장되는 변수가 없으므로 읽고 버리게 되고 종국에는 내용이 빈 stdin만이 남게 된다.

profile
AR개발자지망생

0개의 댓글