ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C언어 표준 입출력과 버퍼
    Programming/C 2016. 5. 2. 22:46

    표준 입출력과 버퍼

    표준 입출력 기반의 버퍼

    표준 입출력 함수를 통해 데이터를 입출력하면 해당 데이터들은 운영체제가 제공하는 '메모리 버퍼'를 중간에 통과하게 된다.
    이 이미지 처럼...
    '메모리 버퍼'는 데이터를 임시로 모아두는(저장하는) 메모리 공간이다. 키보드를 통해 입력되는 데이터는 일단 입력버퍼에 저장된 후(버퍼링 된 다음에) 프로그램에서 읽혀진다. 키보드로부터 입력된 데이터가 입력 스트림을 거쳐 입력버퍼로 들어가는 시점은 엔터 키가 눌리는 시점이다. 그래서 아무리 문자열을 입력해도 엔터 키가 눌리기 전에는 fgets함수가 문자열을 읽어 들이지 못한다.

    버퍼링을 하는 이유

    '데이터 전송의 효율성'과 관련이 있음. 버퍼링 없이 키보드가 눌릴 때마다 눌린 문자의 정보를 목적지로 바로 이동시키는 것보다 중간에 메모리 버퍼를 둬서 데이터를 한데 묶어 이동시키는 것이 보다 효율적이고 빠르다.

    출력버퍼를 비우는 fflush 함수

    #include <stdio.h>
    int fflush(FILE * stream);

    → 함수호출 성공 시 0, 실패 시 EOF 반환
    - 출력버퍼가 비워진다는 것은 출력버퍼에 저장된 데이터가 버퍼를 떠나서 목적지로 이동됨을 뜻한다. - 출력버퍼가 비워지는 시점은 시스템에 따라 그리고 버퍼의 성격에 따라 달라진다. 예를 들어서 버퍼가 꽉 찼을 때 비워지는 버퍼도 있고 하나의 문장이 완전히 입력되었을 때마다 비워지는 버퍼도 있다. 그래서 위의 함수를 알아놓아야 한다.

    fflush(stdout);
    
    • 위는 표준 출력버퍼를 비우는 기능을 제공한다.
    • 어떠한 시스템에서라도 버퍼에 저장된 내용이 비워지면서 데이터가 목적지로 이동한다. 그리고 파일을 대상으로도 위 함수가 가능하다.

    입력버퍼를 비우는 법

    • 출력버퍼의 비워짐: 저장된 데이터가 목적지로 이동
    • 입력버퍼의 비워짐: 데이터의 소멸

    입력버퍼 비움 사용 예

    int main(void)
    {
        char perID[7];
        char name[10];
    
        fputs("주민번호 앞 6자리 입력: ", stdout);
        fgets(perID, sizeof(perID), stdin);
    
        fputs("이름 입력: ", stdout);
        fgets(name, sizeof(name), stdin);
    
        printf("주민번호: %s\n", perID);
        printf("이름: %s\n", name);
        return 0;
    }
    • 위 코드에서는 처음에 fgets에서 7자리를 받아서 널 문자를 제외 6자리를 받으면 입력버퍼에는 '\n'가 남게 되어 다음과 같은 결과가 나오게 된다.
      주민번호 앞 6자리 입력: 950423
      이름 입력: 주민번호: 950423
      이름:  
      

      그리고 다음처럼 사용자가 앞 6자리 이후로도 입력을 하게 되면 앞 6자리를 제외하고 나머지 문자들을 입력버퍼에서 지워줘야 한다.

      주민번호 앞 6자리 입력: 940513-112345
      이름 입력: 주민번호: 940513
      이름: -112345
      

      다음과 같이 함수를 정의해주면 해결이 된다. getchar()로 \n을 만날 때까지 문자를 모두 읽어들이는 함수를 정의하면 읽어 들이는 문자를 저장하거나 하지는 않기 때문에 버리게 된다.

      void ClearLineFromReadBuffer(void)
      {
          while(get char()!= '\n');
      }

    댓글

Designed by Tistory.