c언어를 처음 배우면 마주하게되는 printf, 정말 편리한 함수라고 생각을 하였다
근데 그 편리함을 다 구현하려고 해보니 정말 머리가 미쳐버릴거 같다
이전까지의 과제들은 정리를 안하고 머리속으로만 구현할 수 있었지만 프엡부터는 도저히 불가능 할거 같아서 글로 정리를 해가며 구현해볼것이다
printf
int printf("출력할 데이터와 서식", 변수1, 변수2 ....)
int printf(const char *format, ...)
첫번째 인자는 출력할 데이터를 넣는 공간이다
여기서 데이터를 넣을때 변수를 넣을수 있는데 "%()" %와 해당하는 옵션을 이용하여서 두번째 인자를 불러오는식으로 구성되어있다
데이터 안쪽에서 %의 개수가 들어오는만큼 변수의 개수도 늘어나게되는데 이런식으로 매개변수의 개수가 바뀌는것을 가변인자라고 합니다
가변인자
매번 함수에 들어가는 인수(argument)의 개수가 변하는 것을 가변 인자(가변 인수, variable argument)라고 합니다
반환값 자료형 함수명(자료형 고정매개변수, ...)
가변인자를 사용할때는 고정 매개변수가 한 개 이상 있어야 하며 고정 매개변수 뒤에 ...을 붙여 매개변수의 개수가 정해지지 않았다는 표시를 해줍니다
#include <stdio.h>
#include <stdarg.h> // va_list, va_start, va_arg, va_end 가 정의된 헤더
void printNum(int args, ...)
{
va_list ap; // 가변 인자 목록 포인터
va_start(ap, args); // 가변 인자 목록 포인터 설정
for (int i = 0; i < args; i++) // 가변 인자 개수만큼 반복
{
int num = va_arg(ap, int); // int 크기만큼 가변 인자 목록 포인터에서 값을 가져옴
// ap를 int 크기만큼 순방향으로 이동
printf("%d ", num); // 가변 인자 값 출력
}
va_end(ap); // 가변 인자 목록 포인터를 NULL로 초기화
printf("\n");
}
int main()
{
printNum(1, 10);
printNum(2, 10, 20);
printNum(3, 10, 20, 30);
printNum(4, 10, 20, 30, 40);
return (0);
}
실행결과
10
10 20
10 20 30
10 20 30 40
가변인자를 사용하려면 strarg.h 헤더 파일에 정의된 매크로를 이용해야합니다
va_list
: 가변 인자 목록. 가변 인자의 메모리 주소를 저장하는 포인터입니다.va_start
: 가변 인자를 가져올 수 있도록 포인터를 설정합니다.va_arg
: 가변 인자 포인터에서 특정 자료형 크기만큼 값을 가져옵니다.va_end
: 가변 인자 처리가 끝났을 때 포인터를 NULL로 초기화합니다.
va_list의 구조
va_start
를 사용하여 가변 인자의 첫 번째 매개변수의 값으로 초기화 시키고
va_arg
를 이용하여 가변 인자 포인터에서 특정 자료형 크기만큼 값을 가지고 온다
va_arg는 기본 자료형 인자들은 자료형 승격이 일어난다
va_end
를 사용하여 가변 인자 처리가 끝났을 때 포인터를 NULL로 초기화 시킨다
%[flag][wide][.precision]type
원래는 정밀도 다음 크기를 지정하는 옵션도 있지만 과제에서 요구하는 옵션만 구현하려고 해서 제외시켰다
플래그는 기본출력에서 여러가지 형태에 대해 좀 더 자세하게 지정할 수 있게 해준다.
flag | explanation |
---|---|
- | 결과를 좌측 정렬합니다 |
+ | 출력값의 부호를 출력합니디(+, - 둘다 출력) |
(공백) | 앞에 부호가 붙지 않는다면 한 칸을 띄어서 출력한다 |
# | o, x, X 포맷으로 사용되면, # 플래그는 0(영)이 아닌 출력 값 앞에 0, 0x 또는 0X를 추가합니다 |
0 | 오른쪽 정렬일 때 공백을 0으로 채운다 |
플래그는 여러게 동시에 적용할 수 있다
-
와 0
이 조합되면 0이 무시가 된다출력되는 데이터의 폭을 지정해준다. 출력값이 너비보다 작으면 공백으로 출력, 기본적으로 오른쪽 정렬
-
플래그(좌측정렬)로 간주한다마침표 앞에 오는 음수가 아닌 십진 정수로, 출력될 문자의 수나 소수 자리의 수를 지정합니다.
정수일 경우 출력될 숫자의 최솟값을 지정합니다 인수에서 숫자의 수가 정밀도 보다 작으면, 출력 값은 왼쪽이 0으로 채워집니다
부동소수점은 다음에 출력될 자릿수를 지정합니다. 출력된 마지막 숫자는 반올림됩니다
정밀도에 음수가 들어가면 무시한다
정밀도가 0이거나 숫자 없이 표시되는 경우 1로 설정된다
type | 출력 | 예시 |
---|---|---|
c | 문자 | A |
s | 문자열 | ABC |
p | 포인터값(주소) | 0x10fbeb025 |
d | 부호있는 십진법 정수 | -111 or 111 |
i | 부호있는 십진법 정수(여기선 d랑 똑같음) | 111 |
u | 부호없는 십진법 정수 | 111 |
o | 부호없는 8진수(- 경우 오버플로우) | 35 |
x, X | 부호없는 16진수(소문자, 대문자) | 5a, 5A |
% | %출력 | % |
type | wide | precision | plus | minus | zero | blank | cross |
---|---|---|---|---|---|---|---|
c | o | x | x | o | x | x | x |
s | o | o | x | o | x | x | x |
p | o | x | x | o | x | x | x |
d | o | o | o | o | o | o | x |
u | o | o | x | o | o | x | x |
x | o | o | x | o | x | x | o |