
printf 함수는 서식 문자열(format string) 기능을 수행하도록 만들어졌다.
printf(string, expr1, expr2, …);
서식 문자열은 일반적으로 %로 시작하는 변환 규격(conversion specification)을 포함할 수 있다.
int i;
int j;
float x;
float y;
i = 10;
j = 20;
x = 43.2892f;
y = 5527.0f;
printf("i = %d, j = %d, x = %f, y = %f\n", i, j, x, y);
// i = 10, j = 20, x = 43.289200, y = 5527.000000
변환 규격은 다음과 같은 형식을 갖는다.
%m.pX or %-m.pXm은 최소 범위 너비(minimum field width)를 의미한다. 출력할 글자의 최소 개수를 지정한다. 정수 상수를 사용한다.
printf("%4d", 123);
printf("%4d", 12345);
printf("%-4d", 123);
// 출력(스페이스를 ·로 표기)
// ·123
// 12345
// 123·
p는 정확도(precision)를 의미한다. 정확도는 X 변환 규격자(conversion spcifier)의 종류에 따라 다르게 정의된다. X는 값이 출력되기 전 어떤 방식으 ㅣ변환이 적용되어야 하는지를 결정한다. 가장 자주 사용되는 숫자의 변환 규격자는 다음과 같다.
d - 정수를 십진법 형식으로 보여준다. p는 최소 자리수를 의미한다. 만약 필요하다면 숫자가 시작하는 부분에 추가적으로 0을 추가해준다. 만약 p가 포함되지 않았다면 p의 값이 1이라고 가정한다. 다시 말해 %d와 %.1d는 같은 것이다.e - 소수를 지수 형식(물리량을 나타낼 때 사용하는 방식)으로 보여준다. p는 출력할 소수점 이하 자리수를 결정한다. 기본값은 여섯자리이다. 만약 p의 값이 0이라면 소수점을 출력하지 않는다.f - 소수를 지수 없이 고정 소수점 형식으로 보여준다. p는 e 규격자와 같은 의미를 갖는다.g - 소수를 숫자의 크기에 따라 지수 형식 혹은 고정 소수점 형식으로 보여준다. p는 최대 유효 숫자 자리수를 의미한다. 이는 소수점 아래 자리수를 의미하는 것이 아니다. f 변환과는 달리 g 변환은 추가적인 0을 출력하지 않는다. 심지어 출력할 값이 소수점 이하 자리수가 없다면 g는 소수점 조차 출력하지 않는다.g 규격자는 숫자 사이즈를 예측할 수 없거나 사이즈가 다양할 때 유용하다.
/* Prints int and float values in various formats */
#include <stdio.h>
int main(void)
{
int i;
float x;
i = 40;
x = 839.21f;
printf("|%d|%5d|%-5d|%5.3d|\n", i, i, i, i);
printf("|%10.3f|%10.3e|%-10g|\n", x, x, x);
return 0;
}
// |40| 40|40 | 040|
// | 839.210| 8.392e+02|839.21 |
\a : 경보(종소리)\b : 백스페이스\n : 새 줄\t : 수평탭\\ : 특수문자 \\" : 특수문자 "확장 비트열은 printf의 서식 문자열 중에서 가장 먼저 실행된다. 또한 문자려은 여러개의 확장 비트열을 제한 없이 사용할 수 있다. 다음 예시에서는 여섯 개의 확장 비트열을 사용한다.
printf("Item\tUnit\tPurchase\n\tPrice\tDate\n");
// Item Unit Purchase
// Price Date
// "Hello!"
// \
scanf 함수는 다음과 같이 사용한다.
int i;
int j;
float x;
float y;
scanf("%d%d%f%f", &i, &j, &x, &y);
printf처럼 scanf도 변환 규격과 변수의 개수가 같은지 유의해야 한다. 또한 변수 앞에 &를 붙여 포인터를 생성할 수 있도록 해줘야 한다.
scanf는 서식 문자열(format string)과 무관한 문자가 나오면 읽는 것을 멈춘다. 읽기가 완료되면 그 다음 서식 문자열을 처리한다.
숫자를 입력받을 때 scanf 함수는 공란 문자(white-space characters - 빈칸, 탭, 개행문자 등)을 무시한다. 다음 예시를 살펴보자.
scanf("%d%d%f%f", &i, &j, &x, &y);
이 프로그램에 다음 세 줄을 입력했다고 가정해보자.
1
-20 .3
-4.0e3
scanf 함수는 이를 세 줄이 아닌 하나의 문자열로 인식한다.
●●1¤-20●●●.3¤●●●-4.0e3¤
(여기서 ●는 빈 칸을, ¤은 개행문자를 의미한다.)
scanf 함수는 여기서 숫자를 읽어야 하므로 숫자를 찾는 도중에 발견되는 모든 공란문자를 무시한다. 그 결과 네 숫자를 정상적으로 읽을 수 있게 된다.
scanf가 현재 읽고 있는 서식 문자열에 속할 수 없는 문자를 읽게될 경우 해당 문자는 "뒤로 밀려나" 다음 아이템을 찾거나 다음 scan 호출을 기다릴 때까지 대기한다. 아래 예시를 통해 알아보자.
앞서 사용한 예시와 동일한 scanf 함수를 호출한다.
scanf("%d%d%f%f", &i, &j, &x, &y);
그리고 1-20.3-4.0e3¤를 입력하면 scanf 함수는 새로운 입력을 다음과 같이 처리한다.
%d : 공란문자가 아닌 첫 문자는 1이다. 정수는 1로 시작할 수 있으므로 scanf 함수는 그 다음 문자인 -를 읽는다. - 문자는 정수에 포함될 수 없으므로 scanf 함수는 1을 i에 저장하고 -를 뒤로 미룬다.%d : scanf 함수는 이제 다시 - 문자를 읽고, 순서대로 2, 0, .을 읽는다. 정수는 소수점을 갖고 있지 않으므로 scanf은 -20을 j에 저장하고 . 문자를 뒤로 미룬다.%f : scanf 함수는 ., 3, -를 읽는다. 고정소수는 숫자 이후에 - 기호가 올 수 없으므로 0.3을 x에 저장하고 - 문자는 뒤로 미룬다.%f : 마지막으로 scanf 함수는 -, 4, ., 0, e, 3과 ¤(개행문자)를 읽는다. 고정소수는 개행문자를 가질 수 없으므로 -4.0 × 10³을 y에 저장하고 개행문자를 뒤로 미룬다.개행문자는 읽히지 않았으므로 다음 scanf 호출 때 사용될 것이다.
scanf 함수는 입력을 읽을 때 공란문자를 무시하기 때문에 서식 문자열 외의 문자를 거의 추가하지 않는다. 다음과 같이 scanf 함수를 호출하면 어떤 일이 벌어지는지 확인해보자.
scanf("%d, %d", &i, &j);
scanf은 우선 정수값을 찾을 것이고, 이는i변수에 저장된다. 그 다음엔,을 짝 지어줘야하기 때문에 다음 입력문자는 쉼표여야한다. 만약 다음 입력문자가 빈 칸이라면 거기서j의 값은 읽지도 않은채로scanf함수는 종료된다.
scanf("%d\n", &i);
scanf는 공란문자를 무시하고 정수를 먼저 읽는다. 그리고 또다른 비공란문자가 나올 때까지\n과 공란문자를 짝지어줄 것이다. 즉, 해당 서식 문자열은 사용자가 비공란문자를 입력할 때까지scanf함수를 끝내지 않고 기다릴 것이다.