..

Search

44) 콘솔 입출력

44) 콘솔 입출력

콘솔 입출력


콘솔 입출력

콘솔 입출력을 이해하기 위해서는 우선 C언어의 기본적인 입출력 방식에 대해 알고 있어야 합니다.

C언어의 입출력 방식에 대한 더 자세한 사항은 C언어 기본적인 입출력 수업에서 확인할 수 있습니다.

 

C언어 기본적인 입출력 수업 확인 =>


버퍼(buffer)

지금까지 우리가 사용한 printf(), scanf(), puts() 함수 등은 C언어의 표준 입출력 함수입니다.

이러한 표준 입출력 함수를 사용할 때에는 버퍼(buffer)라는 임시 메모리 공간을 사용하게 됩니다.

 

buffer

 

버퍼를 사용하면서 얻을 수 있는 장점은 다음과 같습니다.

 

1. 문자를 하나씩 전달하는 것이 아닌 묶어서 한 번에 전달하므로, 전송 시간이 적게 걸려 성능이 향상됩니다.

2. 사용자가 문자를 잘못 입력했을 경우 수정을 할 수가 있습니다.

 

하지만 입력 작업에 버퍼를 사용하는 것이 반드시 좋은 것만은 아닙니다.

빠른 반응이 요구되는 게임과 같은 프로그램에서는 키를 누르는 즉시 바로 전달되어야만 합니다.

 

이렇게 버퍼를 사용하는 입력과 버퍼를 사용하지 않는 입력은 서로 다른 용도로 사용됩니다.

따라서 자신의 목적에 맞게 버퍼의 사용 여부를 판단해야 합니다.


버퍼링 방식

입출력에 사용되는 버퍼링에는 다음과 같이 두 가지 방식이 있습니다.

 

1. 완전 버퍼링(fully buffered)

2. 라인 버퍼링(line-buffered)

 

완전 버퍼링은 버퍼가 가득 차면 버퍼 안의 내용을 목적지로 보내는 방식입니다.

이 방식은 보통 파일 입출력에서 사용됩니다.

 

라인 버퍼링은 입력된 문자 중 개행 문자가 나타날 때마다 버퍼 안의 내용을 목적지로 보내는 방식입니다.

이 방식은 보통 키보드 입력에서 사용됩니다.

 

이러한 입력 작업뿐만 아니라 printf() 함수 등을 통해 모니터에 데이터를 출력할 때도 버퍼를 사용합니다.

출력하고자 하는 데이터는 일단 출력 버퍼에 저장되었다가 출력 스트림을 통해 모니터로 전송됩니다.


fflush() 함수

fflush() 함수는 인수로 전달된 스트림에 연결된 버퍼를 비워줍니다.

 

fflush() 함수의 원형은 다음과 같습니다.

원형

#include <stdio.h>

int fflush(FILE *stream);

 

인수로 전달되는 스트림이 입력 스트림과는 관련이 없으며, 출력 스트림과 관련이 있습니다.

출력 스트림이 인수로 전달되면 출력 버퍼 안에 있는 데이터를 즉시 목적지로 보내줍니다.

 

만약에 널 포인터가 인수로 전달되면, 해당 프로그램에서 앞서 정의한 모든 스트림에 대한 버퍼를 전부 비워줍니다.

fflush() 함수는 버퍼를 성공적으로 비우면 0을 반환하고, 버퍼를 비우는 데 실패하면 EOF를 반환합니다.

 

예제

#include <stdio.h>  

 

int main(void)

{

    char str[20];

    char ch;  

 

    puts("당신의 이름을 적어주세요 : ");

    scanf("%s", str);

    puts("당신의 성별을 약자로 적어주세요 : ");

    puts("(남성=M, 여성=F)");

    scanf("%c", &ch);  

 

    if (ch=='m' | ch=='M')

    {

        printf("당신은 남성인 %s입니다.\n", str);

    }

    else if(ch=='f' | ch=='F')

    {

        printf("당신은 여성인 %s입니다.\n", str);

    }

    else

    {

        printf("%s님, 성별을 잘못 입력하셨습니다.\n", str);

    }

    return 0;

}

실행 결과

당신의 이름을 적어주세요 :

홍길동

당신의 성별을 약자로 적어주세요 :

<남성=M, 여성=F>

홍길동님, 성별을 잘못 입력하셨습니다.

 

위의 예제를 실행하면 사용자가 이름을 입력할 수 있지만, 성별은 입력하지 못하고 프로그램이 종료됩니다.

그 이유는 이름을 입력받을 때 마지막으로 입력한 엔터(Enter) 키가 입력 버퍼에 남아있기 때문입니다.

이렇게 입출력 함수는 입력 버퍼에 데이터가 남아 있으면, 키보드로부터 데이터를 입력받지 않고 버퍼에 남아있는 데이터를 먼저 사용합니다.

따라서 이 프로그램이 제대로 동작하기 위해서는 다음과 같이 fflush() 함수를 이용해 버퍼에 남아있는 데이터를 비워야 합니다.

 

예제

...

puts("당신의 이름을 적어주세요 : ");

scanf("%s", str);

 

fflush(stdin); // 표준 입력 스트림의 입력 버퍼를 비움  

 

puts("당신의 성별을 약자로 적어주세요 : ");

puts("(남성=M, 여성=F)");

scanf("%c", &ch);

...

실행 결과

당신의 이름을 적어주세요 :

홍길동

당신의 성별을 약자로 적어주세요 :

<남성=M, 여성=F>

M

당신은 남성인 홍길동입니다.

fflush()은 입력스트림과 관련이 있다고 알고 있지만, 결과적으로는 출력스트림에만 관련이 있습니다. 출력스트림으론 stdout, stderr이 있습니다. Visual Studio 2013에서는 비표준함수인 fflush()를 허용해주고 있지만, Visual Studio2015부터 비표준함수인 fflush()가 사라졌기 때문에 위의 예제에서 fflush(stdin)을 사용하더라도 똑같은 현상이 반복될 것입니다.  그렇기 때문에 입력 버퍼를 지우기 위해서는 fflush()함수가 아닌 getchar() 함수를 이용하여야 합니다.
예제

#include <stdio.h>  

 

int main(void)

{

    char str[20];

    char ch;  

 

    puts("당신의 이름을 적어주세요 : ");

    scanf("%s", str);

    getchar()

 

    puts("당신의 성별을 약자로 적어주세요 : ");

    puts("(남성=M, 여성=F)");

    scanf("%c", &ch);  

 

    if (ch=='m' | ch=='M')

    {

        printf("당신은 남성인 %s입니다.\n", str);

    }

    else if(ch=='f' | ch=='F')

    {

        printf("당신은 여성인 %s입니다.\n", str);

    }

    else

    {

        printf("%s님, 성별을 잘못 입력하셨습니다.\n", str);

    }

    return 0;

}

실행 결과

당신의 이름을 적어주세요 :

홍길동

당신의 성별을 약자로 적어주세요 :

<남성=M, 여성=F>

M

당신은 남성인 홍길동입니다.

 

위의 예제에서 getchar()함수를 이용하면 이름을 입력받을 때 마지막으로 입력한(Enter)키를 입력버퍼에서 비워주기 때문에 프로그램이 정상적으로 작동합니다. fflush()함수는 출력스트림만 관련있기 때문에 fflush()함수를 이용해 입력버퍼를 비우기보다는 getchar()함수를 이용하여 입력버퍼를 지워주셔야 합니다.

 

연습문제