변수나 제어문을 공부하기 전에 기본적인 입출력 방법을 먼저 알아보도록 하자. 변수의 값을 확인하거나 처리 결과가 어떻게 나오는지 보려면 일단 화면에 찍어 봐야 하므로 효율적인 실습을 위해서는 입력과 출력 명령을 먼저 사용할 수 있어야 한다. 초보자들은 이론적인 설명보다는 눈에 보이는 것을 더 믿는 경향이 있어서 int Num=12; 선언문에 의해 정수형의 Num 변수가 생성되고 12로 초기화된다고 해도 "증거를 대라"는 식으로 믿지 않는 희한한 버릇이 있다. 공부할 때는 아무리 간단한 것이라도 확인해 보고 넘어가는 것이 좋다.

베이직 PRINT라는 기본적인 출력문을 언어 차원에서 제공한다. 이에 비해 C언어는 문법의 간결성과 이식성 확보를 위해 언어 자체에 입출력 명령이 포함되어 있지 않다. 대신 컴파일러 제조사가 라이브러리 (일단 명령의 집합이라고 생각하면 된다) 형태로 입출력 명령을 제공하며 이 명령등른 C 표준에 의해 모든 컴파일러가 의무적으로 제공하도록 되어 있으므로 언제든지 사용할 수 있다.

printf는 C의 표준 출력 함수이며 C를 배우는 사람이 가장 먼저 대하는 명령어이다. 마치 도스를 처음 배우는 사람이 dir을 가장 먼저 배우고 윈도우즈를 처음 배울 때 탐색기부터 배우듯이 말이다. 함수의 정확한 개념에 대해서는 다음에 상세하게 배워 보기로 하되 일단은 명령의 일종이라고 생각하면 된다. 이 함수의 철자에 조금 주의해야 하는데 print가 아니라 printf이며 읽을 떄는 "프린트에프"라고  읽는다. printf의 제일 뒤에 있는 f는 Formatting의 약자이며 서식화된 출력을 한다는 뜻이다.

서식화라는 말이 어렵게 들린다면 일단 조립이라고 생각하도록 하자. 가장 기초적인 명령이면서도 사실 이만큼 복잡한 명령어도 드물어서 완벽하게 자유 자재로 사용하려면 많은 경험을 필요로 한다. 복잡한 내용은 차후에 천천히 알아보기로 하고 여기서는 기본적인 사용법만 익혀보도록 하자.

printf는 괄호안의 문자열을 화면으로 출력한다. 가장 단순한 형태는 printf("문자열"); 인데 겹따옴표안의 문자열이 화면으로 그대로 출력된다. printf("나는 바보다"); 라는 명령은 "나는 바보다"를 화면으로 출력한다. 앞장에서 이미 printf("korea\n");이라는 명령을 사용해 본 적이 있지 않은가? 이 함수의 일반적인 사용법은 다음과 같다.

printf("서식문자열"[,인수,인수,...]);

서식 문자열을 화면으로 출력하되 문자열 내에 %로 시작되는 서식이 있으면 이 서식과 대응되는 뒤쪽의 인수(일단 변수라고 생각하기 바란다)를 문자열안에 넣어 같이 출력한다. 즉 출력하기 전에 서식과 인수를 대응시켜 조립(Formatting)하는 과정을 먼저 거친다. 뒤쪽의 인수는 서식의 개수만큼 오되 서식이 없으면 인수를 생략할 수 있다.

: printf

#include <Turboc.h>

void main()
{
     int value=12;
     char ch='S';


     printf("값은 %d이며 문자는 %c이다.\n",value,ch);

정수형 변수 value를 12로 초기화하고 문자형 변수 ch는 "S"문자로 초기화한후 printf로 이 변수들의 값을 출력해 보았다. 출력 결과는 다음과 같다.

사용자 삽입 이미지

서식 문자열 안에는 %d, %c 등의 서식이 포함되어 있으며 이 서식과 대응되는 인수 value와 ch가 서식문자열 다음에 온다. 이 함수는 문자열내의 서식을 대응되는 실제 변수값으로 바꾸어 화면에 출력한다. %d 서식은 value에 대응되므로 이 자리에 value 변수의 실제값인 12가 삽입되고 %c 서식은 ch에 대응되므로 ch변수의 실제값인 "S"가 삽입된다.

서식 문자열의 서식과 뒤쪽의 인수는 나타나는 순서대로 1:1 서로 대응된다. 따라서 서식의 개수와 인수의 개수가 같아야 하며 또한 데이터형도 서로 일치해야 한다. %d는 정수형 서식이므로 정수형 변수와 대응되어야 하며 %c는 문자형 서식이므로 문자형 변수와 대응되어야 한다. 만약 개수나 타입이 일치하지 않으면 프로그램이 제대로 동작하지 않을 뿐만 아니라 어떤 경우에는 에러를 일으키고 다운될 수도 있다. 표준은 서식이 일치하지 않을 경우의 동작에 대해서는 정의하고 있지 않으므로(Undefined) 개발자가 반드시 일치시켜야 한다.

서식은 % 다음에 알파벳 문자 하나로 표기하며 다음과 같은 종류가 있다. 서식의 수가 좀 많은데 이 중 %d, %c, %s, %f 정도만 알아 두면 변수값을 확인해 보는 용도로 충분히 활용할 수 있을 것이다. 나머지 서식은 필요할 떄 이 표를 다시 참조하면 된다.

서식

의미

설명

%d 또는 %i

Decimal, Integer

 

10진 정수로 출력한다.

%o

Octal

 

8진 정수로 출력한다.

%x또는 %x

heXadecimal

16진 정수로 출력한다. 대문자 X를 쓰면 A~F까지의 숫자도 대문자로 출력된다.

%u

Unsigned

부호없는 10진 정수로 출력한다.

%c
%s
%f
%e 또는 %E
%g 또는 %G
%p

%n
%%

Character
String
Float


Pointer

1개의문자열을 출력한다.
문자열을 출력한다.
고정 소수점 형식의 실수로 출력
부동 소수점 형식의 실수로 출력
%e,%f중 더 짧은 형식으로 출력
포인터의 번지값을 출력
출력된 문자 개수를 포인터 변수에 대입한다.
%문자 자체를 출력한다.


printf 함수는 변수값을 화면으로 출력하거나 또는 문자열로 조립할 떄 사용하는 가장 기본적인 함수이며 변수의 출력 위치와 형태를 서식으로 지정할 수 있는 아주 편리한 방법이기도 하다. 확인해 보고 싶은 값의 자리에 서식을 대신 넣어 주기만 하면 된다. 예를 들어 Score 정수형 변수에 총점이 있고 Average 실수형 변수에 평균이 저장되어 있다면 다음과 같이 출력한다.

printf("총점은 %d점이며 평균은 %f점입니다.\n",Score,Average);

%d 자리에 Score에 기억된 정수값이 출력될 것이며 %f 자리에 Average에 기억된 실수값이 출력될 것이다. 서식 문자열은 얼마든지 자유롭게 바꿀 수 있으므로 "총점=%d, 평균=f"나 "총점/평균(%d/%f)"로 작성할 수도 있다. printf는 서식이 있는 자리에 실제값을 끼워 넣기만 할 뿐이다.

서식은 이 자리에 "무엇을" 출력할 것인가를 지정하는데 이 외에도 "어떻게" 출력할 것인지도 지정할 수 있다. "%d와 서식 문자 사이에 원하는 출력 형태를 지정하는데 설명을 나열하는 것보다는 구체적인 예제를 통해 동일한 값을 다양한 형태로 출력하는 실습을 해 보자. 다음 예제는 정수형 변수 Num의 값을 %d 서식으로 출력하되 다양한 양식을 지정해 보았다.

: printf2


#include <Turboc.h>

void main(void)
{
     int Num=123;
     
     printf("-->%d<--\n",Num);
     printf("-->%5d<--\n",Num);
     printf("-->%05d<--\n",Num);
     printf("-->%-5d<--\n",Num);

}

출력 자리수를 확인하기 위해 서식 문자열의 앞뒤에 -->와 <--를 넣어 두고 중간에 세자리의 Num값을 출력했다. 실행 결과는 다음과 같다.

-->123<--
-->  123<--
-->00123<--
-->123 <--

%d만 쓰면 Num의 자리수대로 123만 출력되는데 %와 d사이에 원하는 자리수를 지정하면 Num이 설사 이 자리수보다 작더라도 지정한 자리수만큼 차지하도록 한다. Num이 세 자리밖에 안되지만 %5d 서식을 사용했ㅇ므,ㅡ로 앞쪽에 두 개의 공백을 넣어 다섯  자리를 채운다. 숫자가 많이 들어가는 도표 형식을 출력할 때는 각 자리 수가 들쭉 날쭉한 것보다 일정한 자리수를 지정하며 가지런히 정렬되는 것이 훨씬 더 보기 좋다. 다음 출력 결과 둘을 비교해 보라.

12/9 매출 : 3450000, 매입 : 1200000, 이익 : 820000
12/10 매출 : 6700, 매입 : 8000, 이익 : 10
12/11 매출 : 4500000, 매입 : 0, 이익 : 960000

12/ 9 매출 : 3450000, 매입 : 1200000, 이익 : 820000
12/10 매출 :     6700, 매입 :      8000, 이익 :       10
12/11 매출 : 4500000, 매입 :          0, 이익 : 960000

단, 자리수 지정은 최소한의 지정이므로 만약 자리수보다 값이 더 클 경우에는 지정한 자리수가 무시되고 값의 실제 자리수가 적용된다. 예를 들어 Num이 12345인데 %3d로 이 값을 출력하면 강제로 세 자리가 되는 것이 아니라 다섯 자리가 모두 출력된다. 지정한 자리수를 억지로 맞추기 위해 값을 잘라 버린다면 이는 정확한 출력이 아닐 것이다.

자리수 지정앞에 0을 붙이면 앞쪽에 공백 대신 0을 채운다. %5d 서식은 "123"을 출력하지만 %05d 서식은 "00123"을 출력한다. 이때 앞쪽에 추가된 0을 선행 제로(Leading Zero)라고 하는데 값 자체를 바꾸지 않으면서 자리수만큼 글자를 채우는 역할을 한다. 선행 제로를 붙이지 않으면 10이 9나 8보다 작다고 평가되므로 크기순으로 정렬되어야 하는 수식을 위해 일부러 선행 제로를 삽입하는 경우가 종종 있다. 자리수에 - 를 사용하면 전체 자리수에서 왼쪽으로 정렬되어 공백이 뒤쪽에 배치된다. 다음은 실수를 출력하는 %f 서식에 대해 알아보자.

: printf3


#include <Turboc.h>

void main(void)
{
     double pie=3.14
     printf("-->%f<--\n",pie);
     printf("-->%10f<--\n",pie);
     printf("-->%.2f<--\n",pie);
     printf("-->%10.2f<--\n",pie);
     printf("-->%0.102f<--\n",pie);
     printf("-->%-10.2f<--\n",pie);

}

%d 서식과 마찬가지로 전체 자리수를 지정할 수 있고 앞에 0과 -를 붙여 선행 제로를 붙이거나 왼쪽으로 정렬할 수 있다. 다만 점(.)다음에 소수점 이하 몇 번째 자리까지 출력할 것인지를 따로 지정할 수 있다는 점이 다르다. 출력 결과는 다음과 같다.

-->3.140000<--
-->  3.140000<--
-->3.14<--
-->      3.14<--
-->0000003.14<--
-->3.14      <--

% 서식은 기본적으로 소수점 이하 여섯 자리까지 출력하는데 뒤쪽에 의미 없는 0(이것을 후행 제로 : Trailing Zero라고 한다)이 같이 출력되어 보기에 좋지 않다. 이럴 때 %.2f 서식을 사용하면 소수점 이하 두 자리까지만 출력되므로 보기에 훨씬 더 깔끔하다. %f는 지정한 자리수에서 반올림 처리까지 해 주므로 실수를 출력할 때는 가급적이면 소수점 이하 자리수를 지정하는 것이 좋다. 정수와 실수에 대응되는 두 서식의 완전한 형태는 다음과 같이 정리할 수 있다.

정수 : %[-][0][총자리수]d
실수 : %[-][0][총자리수][.소수점 이하 자리수]f

대표적으로 %d와 %f 서식에 대해서만 출력 양식을 지정하는 방법을 실습해 보았는데 나머지 서식들의 출력 양식도 거의 비슷한 방법으로 사용하면 된다. 더 자세한 사항에 대해서는 필요할 때 레퍼런스를 참고하기 바란다.

이상으로 C의 가장 기본적인 출력 함수인 printf 함수에 대해 알아보았는데 보기보다 훨씬 더 복잡하다는 것을 알 수 있다. 이 방식이 조금 구식인 것처럼 느껴질 수도 있고 배워둘 가치가 없는 것처럼 보이기도 하는데 그렇지 않다. 서식을 사용한 문자열 조립은 서식이 불일치할 때 컴파일러가 오류를 확인할 수 없어 다소 위험한 면이 있기는 하지만 굉장히 직관적이면서 효율적인 방법이다.

최신의 개발툴들도 printf와 유사한 서식 출력을 지원하는데 윈도우즈 API 함수중에 wsprintf 함수가 있고 MFC에도 CSting::Format 함수가 동일한 서식을 사용한다. 심지어는 PHP나 ASP같은 스크립트 언어도 유사한 서식 조립 기능이 있다. 따라서 여기서 서식을 잘 익혀 다음에 유용하게 활용할 수 있을 것이다. printf의 서식들은 애써 외워둘만한 충분한 가치가 있다. 단 개발툴에 따라 서식의 고급 설정 부분은 조금씩 차이가 있으므로 그 부분만 다시 공부하면 된다.

C++ 언어는 printf보다 좀 더 안정적이고 확장 가능한 cout 출력 객체를 제공하는데  이 객체는
printf에 비해 훨씬 진보된 개념임은 분명하다. 그러나 현대적인 그래픽 환경에서 사실 텍스트 화면에 출력할 일은 거의 없다고 볼 수 있으므로 cout도 쓸 일이 많지 않을 것이다. 이에 비해 printf 방식의 서식 조립은 앞으로도 계속 사용될 전망이다.

참고

printf를 영문 발음 그대로 "프린트프"라고 읽는다고 해서 꼭 틀렸다고 할 수는 없다. C 표준 문서에 이 함수를 어떻게 읽으라는 발음기호가 명시되어 이쓴 것은 아니므로 읽는 사람이 편한대로 읽으면 된다. 그러나 혼자서 개발을 하지 않는 한 대화를 해야 하는데 이때 함수 이름을 읽는 방법이 제각각 다르다면 원활한 의사 소통에 방해가 되므로 가급적이면 우세한 발음을 따르는 것이 좋다. 영어 단어는 그대로 읽되 앞뒤에 붙는 약자는 알파벳 그대로 읽는 것이 보편적이다. wsprintf를 "위스프린트프" 이렇게 읽으면 저 사람 참 특이하다는 소리를 듣게 될 것이다.
Posted by 테티스
,