본문 바로가기
Language&Framework&Etc/C

문자와 문자열 관련 함수(21-2) 문자 단위 입출력 함수

by 머리올리자 2020. 12. 10.

문자 출력 함수 : putchar, fputc

모니터로 하나의 문자를 출력할 때 일반적으로 사용하는 두 함수

#include <stdio.h>
int putchar(int c);
int fputc(int c, FILE * stream);

함수호출 성공 시 쓰여진 문자정보가, 실패 시 EOF 반환

 

putchar : 인자로 전달된 문자정보를 stdout으로 표현되는 표준 출력 스트림으로 전송하는 함수

→ 인자로 전달된 문자를 모니터로 출력하는 함수.

 

문자를 전송한다는 측면에서는 fputc 함수도 putchar 함수와 동일하다.

 

단 fputc 함수는 문자를 전송할 스트림을 지정할 수 있다.

 

즉, fputc 함수를 이용하면 stdout 뿐만 아니라, 파일을 대상으로도 데이터를 전송할 수 있다.

 

또한 fputc 함수의 두 번째 매개변수 stream은 문자를 출력할 스트림의 지정에 사용된다.

 

fputc 함수의 두 번째 인자

fputc 함수의 두 번째 인자로 파일의 스트림 정보를 전달하면, 해당 파일로 문자가 전달된다(해당 파일에 문자가 저장된다). 때문에 fputc 함수는 이후에 파일 입출력을 공부할 때에도 접하게 된다.

 

문자 입력 함수 : getchar, fgetc

키보드로 하나의 문자를 입력 받을 때 일반적으로 사용하는 두 함수

#include <stdio.h>
int getchar(void);
int fgetc(FILE* stream);

파일의 끝에 도달하거나 함수호출 실패 시 EOF 반환

 

getchar : stdin으로 표현되는 표준 입력 스트림으로부터 하나의 문자를 입력 받아서 반환하는 함수

키보드로부터 하나의 문자를 입력 받는 함수

 

fgetc 함수도 하나의 문자를 입력 받는 함수

다만, getchar 함수와 달리 문자를 입력 받을 스트림을 지정할 수 있다.

 

즉 putchar, fputc 함수의 관계와 동일하다.

 

예제

 

#include <stdio.h>
int main(void)
{
	int ch1, ch2;

	ch1 = getchar();    // 문자입력
	ch2 = fgetc(stdin); // 엔터 키 입력

	putchar(ch1);       //문자 출력
	fputc(ch2, stdout); //엔터 키 출력
} 

소스코드상에서는 분명 두 개의 문자를 입출력

그런데 실행 결과만 보면, 하나의 문자가 입력되고 출력된 것으로 보임.

실제로는 두 개의 문자가 입력되고 출력됨

 

다만, 두 번째 문자가 '엔터 키'이다 보니 눈에 띄질 않았다.

 

'엔터 키'도  아스키 코드 값이 10인 '\n'으로 표현되는 문자이다. 

 

"그런데 위 예제에서 문자를 int형 변수에 저장하는 이유는?"

 

왜냐 getchar 함수와 fgetc 함수의 반환형이 int이기 때문이다.

 

그런데 왜 int? → 나중에 설명한다 함

 

문자 입출력에서의 EOF

EOF는 End of file의 약자로서, 파일의 끝을 표현하기 위해서 정의해 놓은 상수.

 

따라서 파일을 대상으로 fgetc 함수가 호출되면, 그리고 그 결과로 EOF가 반환되면, 이는 '파일의 끝에 도달해서 더 이상 읽을 내용이 없다'는 뜻이 된다.

 

그렇다면 키보드를 대상으로 하는 fgetc 함수와 getchar 함수는 언제 EOF를 반환할까?

이는 다음 두 가지 경우 중 하나가 만족되었을 때

 

  • 함수호출의 실패
  • Windows에서 CTRL+Z키, Linux에서 CTRL+D 키가 입력되는 경우

키보드의 입력에 '파일의 끝'이라는 것이 존재할 수 있겠는가

따라서 EOF의 반환시기를 CTRL+Z 또는 CTRL+D 키의 입력으로 별도로 약속

 

다음 예제(키보드를 통한 EOF 입력)

#include <stdio.h>


int main(void)
{
	int ch;

	while (1)
	{
		ch = getchar();
		if (ch == EOF)
			break;
		putchar(ch);
	}
	return 0;
} 

getchar 함수가 호출된다고 해서 하나의 문자만 입력하려고 노력하지 않아도 된다.

문자가 아닌 공백을 포함하는 문장을 입력해도 된다.

문장이 입력되면 문장을 구성하는 문자의 수만큼 getchar 함수가 호출되면서 모든 문자를 읽어 들인다.

반환형이 int이고, int형 변수에 문자를 담은 이유는?

int getchar(void);
int fgetc(FILE* stream);

반환되는 것은 1바이트 크기의 문자인데, 반환형이 int이다.

이유는?

 

이전에 언급했던. "char형은 예외일 수 있습니다.", "char를 unsigned char로 처리하는 컴파일러도 존재한다"

 

그런데 위의 두 함수가 반환하는 값 중 하나인 EOF는 -1로 정의된 상수

 

따라서 반환형이 char이라면, 그리고 char를 unsigned char로 처리하는 컴파일러에 의해서 컴파일이 되었다면,

EOF는 반환의 과정에서 엉뚱한 양의 정수로 형 변환이 되어버리고 만다.

 

그래서 어떠한 상황에서도 -1을 인식할 수 있는 int형으로 반환형을 정의.

 

문자 단위 입출력 함수의 존재 이유

  • 기존 문자의 입출력에도 printf와 scanf 함수를 사용해 왔고 불편함도 없었다.
  • 그런데 문자 단위 입출력 함수를 제공하는 이유는?
  • printf와 scanf 함수는 본래 서식지정을 통해서 새로운 입출력의 형태를 구성하는 함수이다.
  • 이러한 화려한 기능을 제공하는 함수는 그에 따른 대가가 요구 된다.
  • 화려한 기능을 제공하는 만큼 사용하는 메모리 공간도 크고, 해야 할 연산의 양도 많아서 상대적으로 속도가 느리다.
  • 뿐만 아니라 별도의 서식지정을 해야 하니 문장을 구성하는 것도 번거로운 편이다.
  • 따라서 단순히 문자 하나를 입출력 하는 것이 목적이라면 printf 함수나 scanf 함수를 사용하는 것보다는 앞서 새로 소개한 함수들을 사용하는 것이 낫다.

 

 

 

참고 : [윤성우 열혈 C 프로그래밍] - 대부분의 내용 및 코드는 이 책에서 개인 공부 정리 목적으로 참고하였습니다.