[2-5] 표준 출력 : printf(), putchar(), putc(), puts()

표준 입출력 라이브러리(stdio.h)에서 표준 출력 함수를 제공합니다. 표준이라 함은 어떠한 C 시스템에서도 호환성이 유지된다는 뜻입니다. 그러므로 에서 제공하는 함수는 시스템에 의존하고 않고 같은 방법으로 사용할 수 있습니다.

표준 입출력은 프로그램과 단말기 사이에 연결된 입출력 방식입니다. 표준 입출력은 유닉스 계열 OS을 중심으로 사용되었습니다. 표준 입력(stdin), 표준 출력(stdout), 표준 에러(stderr)로 구성됩니다. 표준입력 장치는 키보드, 표준출력 장치는 디스플레이입니다.

표준 입출력

각 스트림에 대한 파일 설명자는 다음과 같습니다. 대표적인 표준입력으로 scanf() 함수, 표준출력으로 printf()가 있습니다. 이 두 함수는 사실 표준 서술자(file descriptor, 파일 설명자, 파일 기술자 라고도 합니다)가 고정된 경우입니다. sprintf() 함수를 사용하면 파일 서술자로 각각 0, 1를 입력해도 scanf()와 printf() 함수와 같은 작업을 할 수 있습니다. 표준 에러는 sprintf() 함수에서 파일 서술자를 2로 쓰면 됩니다.

다음 표에 표준 입출력에 대해 정리해두었습니다.

구분 스트림 스트림 포인터 원형 파일 서술자 버퍼 함수
표준입력 stdin FILE *stdin; 0 사용 scanf(), getchar(), gets(), getc()
표준출력 stdout FILE *stdout; 1 미사용 printf(), putchar(), puts(), putc()
표준에러 stderr FILE *stderr; 2 미사용 sprintf()

여기서는 표준 출력 함수만 다루고, 표준 출력 함수는 2.7절에서 다룰 겁니다.

  • printf() 함수
  • putchar() 함수
  • putc() 함수
  • pets() 함수

printf() 함수

printf()는 형식 지정자를 이용해 다양한 형식으로 표준 출력하는 함수입니다. 함수 원형은 다음과 같습니다.

int printf(const char *format, ...)

사실 그동안 printf()문을 줄곧 써와서 기본적인 사용법은 알 겁니다. 그런 의미에서 printf() 함수에 대해 분석하는 시간을 살짝 가져 보겠습니다.

int형으로 출력한 문자 수를 반환한다는 건 쉽게 파악이 가능할 겁니! printf() 함수는 출력하는 문자수를 결과로 반환합니다.

그런데 ‘const char *format, …’이 무얼 의미하는지는 잘 모르겠네요. 이 구분은 ‘가변 변수’를 표현한 겁니다. 쉽게 말해 가변 변수는 변수 수가 고정되지 않은 경우를 말합니다. %d와 같은 형식 지정자를 여럿 쓸 수 있다는 말입니다. 예를 들어 다음과 같이 하나 이상의 형식 지정자를 사용해 제 관우의 신체의 비밀을 출력할 수 있습니다.

#include <stdio.h>

int main(void) {
	char *s = "Guan Yu";
	float w = 71.5;
	int a = 100;
	
	printf("%s : weight(%fkg),  age(%d years old)\n", s, w, a);
	
	return 0;
}

[출력]

Guan Yu : weight(71.500000kg),  age(100 years old)

형식 지정자가 어떻게 적용되었는지 그림으로 살펴보겠습니다.

형식 지정자 적용 순서

이미 여러 차례 사용해서 기본적인 사용법은 어렵지 않을 겁니다. 형식 지정자를 사용하는 방법은 다음과 같습니다.

형식 지정자 포맷

복잡해 보이는군요. 각각에 대해 알아보겠습니다.

  • % : 형식 지정자를 사용하는 예약어입니다.
  • 공란 : 형식지정자와 % 사이에 공란(스페이스)를 넣을 수 있습니다. 출력문의 세로 열을 맞추는 용도로 사용합니다.
  • 부호 : +와 - 모두 올 수 있습니다. -는 왼쪽 정렬, +는 그냥 기호 출력입니다(오른쪽 정렬되기는 합니다. 오른쪽 정렬이 기본값이죠).
  • 폭 : 출력되는 문자 수입니다.
  • . : 소수점 아래를 표현합니다.
  • 소수점 아래 출력 길이 : 소수점 아래 출력하는 문자 수입니다.
  • 형식 지정자 : 자료형의 출력 형식을 지정합니다.

예를 들어 % -10.3f를 해석해보겠습니다.

  • % : 형식지정자
  • 공란 : 공란을 두고
    • : 왼쪽 정렬하여
  • 10 : 총 10문자로 출력
  • . : 소수점 출력
  • 3 : 소수점 3자리까지 출력
  • f : 부동 소수점 형식

% -10.3f를 포함해서 부동 소수점 표기를 다양하게 출력하는 예제를 살펴보겠습니다.

#include <stdio.h>

int main(void) {
	float f = 0.002;
	
	printf("%f\n", f);	// float형 출력
	printf("%10f\n", f);	// 10칸을 사용해 우측 정렬
	printf("%-10f\n", f);	// 10칸을 사용해 좌측 정렬
	printf("%.10f\n", f);	// 소수점 아래 10자리까지 표시 + 우측 정렬
	printf("%-.10f\n", f);	// 소수점 아래 10자리까지 표시 + 좌측 정렬
	printf("%10.3f\n", f);	// 10칸을 사용해 우측 정렬
			// + 소수점 아래 3자리까지만 우측 정렬 출력
	printf("% -10.3f\n", f);// 10칸을 사용해 우측 정렬
			// + 소수점 아래 3자리까지만 좌측 정렬 출력
	printf("%e\n", f);	// 지수 표현

	return 0;
}

[출력]

0.002000
  0.002000
0.002000  
0.0020000001
0.0020000001
     0.002
 0.002     
2.000000e-03

상세 설명은 주석을 살펴보시기 바랍니다. 문자열이나 다른 자료형에 대해서는 여러분이 직접 확인해보세요.

putchar() 함수

putchar()은 표준 출력으로 1바이트를 출력하는 함수입니다. 함수 원형은 다음과 같습니다.

int putchar( int ch );

입력 : 입력값을 unsigned char로 형변환하여 표준 출력합니다. 반환 : 성공하면 성공한 글자 수를, 실패하면 EOF를 반환하고, 표준 에러에 오류 메시지를 남깁니다.

EOF는 End of File의 약자입니다. 더 읽을 데이터가 없음을 나타냅니다. putchar()는 출력 에러로 사용합니다.

#include <stdio.h>

int main(void) {
	int c = 65;
	
	for(int i = 1 ; i < 27 ; i++, c++)
	{
		putchar(c);
		if(!(i%5))
		{
			printf("\n");
		}
	}
	
	return 0;
}

[출력]

ABCDEFGHIJ
KLMNOPQRST
UVWXYZ

정숫값으로 65부터 90까지 입력했는데 어쩐 일로 A~z까지 출력했습니다. 입력값을 unsigned char형으로 형변환하여 출력하기 때문에 아스키 코드가 출력된 겁니다.

if문의 조건식 !(i%10)은 ‘나머지가 참이 아니면’이라는 뜻입니다. 즉 거짓이면 이라는 거죠. 출력문이 너무 길게 나올까봐 열 번에 한 번 줄내림 하고자 if 문을 넣었습니다.

표준 에러 메시지는 다음과 같습니다.

  • ECONVERT : 변환 오류 발생
  • EPUTANDGET : 읽기 조작 후 허용되지 않는 쓰기 조작 발생
  • EIOERROR : 회복 불가능한 I/O 오류 발생
  • EIORECERR : 회복 가능한 I/O 오류 발생

putc() 함수

사용자가 지정한 출력으로 1바이트를 출력하는 함수입니다. 함수 원형은 다음과 같습니다.

int putc(int c, FILE *stream);
  • 입력
    • int c : 입력값을 unsigned char로 형변환하여 표준 출력합니다.
    • FILE *stream : 출력할 파일을 지정합니다.
  • 반환 : 성공하면 성공한 글자 수를, 실패하면 EOF를 반환하고, 표준 에러에 오류 메시지를 남깁니다.

FILE *stream는 파일이거나 장치일 수 있습니다. 표준 장치인 stdout를 인수로 입력하면 됩니다. 그러면 putc()와 putchar()는 완전히 같은 기능을 수행합니다. 앞서 다룬 putchar() 예제를 putc()로 구현해보겠습니다.

#include <stdio.h>

int main(void) {
	int c = 65;
	
	for(int i = 1 ; i < 27 ; i++, c++)
	{
		putc(c, stdout);
		if(!(i%10))
		{
			printf("\n");
		}
	}
	
	return 0;
}

[출력]

ABCDEFGHIJ
KLMNOPQRST
UVWXYZ

stdout 대신 파일 스트림에 대한 포인터를 입력하면 해당 파일에 출력을 합니다. 아직 파일 입출력을 배우지 않았으니까 이 정도까지만 알면 됩니다.

puts() 함수

puts()는 표출 출력으로 문자열을 출력하는 함수입니다. 함수 원형은 다음과 같습니다.

int puts ( const char * str );
  • 입력 : 출력할 문자열
  • 반환 : 성공적으로 출력한 문자 수 혹은 오류 발생 시 EOF를 반환합니다.

예제 코드를 살펴보겠습니다.

#include <stdio.h>

int main(void) {
	int result = 0;
	char *s = "Guan Yu : weight(71.500000kg),  age(100 years old)";
	
	result = printf("%s\n", s);
	printf("result = %d\n", result);
	
	return 0;
}

[출력]

Guan Yu : weight(71.500000kg),  age(100 years old)
result = 51

이상으로 표준 출력을 하는 네 가지 함수를 살펴보았습니다.