42 본과정 과제로 나온 printf 재구현하기.
보자마자 와 어렵겠다 싶었다.
왜냐하면 get_next_line 에서 파일입출력 관련해서 배우면서 엄청나게 스트레스를 받았는데,
이번에는 va_list, va_start, va_arg, va_end 그리고 va_cpy 라는 개념을 새로 배워야 한다는 이유 때문이었다.
그래도 내가 libft 를 하나씩 깬 것처럼,
스트레스를 받으면서 get_next_line 을 결국 해낸 것처럼(아마도)
Printf 또한 끝낼 수 있을 것이고 끝내는 그 날을 위해 또 달려본다.(우리는 언젠가 그것을 해결할 것이다. 늘 그랬듯이. 라는 광고문구가 떠오른다.)
일단 va_list 와 va_start 그리고 va_arg 부터 알아보자.
va_로 시작하는 함수들은 #include <stdarg.h>에 있다.
예를 들어 다음과 같은 함수가 있다 치자.
Void print_digit(int args, ...)
{
va_list ap; // 가변 변수들을 가리킬 포인터이다.
va_start(ap, args); // ap라는 포인터가 args만큼
// 가변 변수들을 차례로 가리키게 만듬
for (int i = 0 ; i < args; i++)
{
int num = va_arg(ap, int);
// 윗줄에서 va_arg는 int byte만큼 포인터를 이동시키면서 읽은 정보를 반환함.
printf("%d\n", num); // 이 함수는 인자로 들어온 정수를 출력한다.
}
va_end(ap);
}
이 경우 인자로 받은 args는 가변 인자의 개수이다.
여기서 말하는 가변 변수란 호출할 때마다 그 개수가 달라지는 인자다.
다음 예제를 보면 더 잘 이해가 갈 것이다.
int main()
{
print_digit(1, 10);
print_digit(2, 10, 20);
print_digit(3, 10, 20, 30);
return (0);
}
출력 결과 :
10
10 20
10 20 30
그림으로 살펴보면 다음과 같이 작동한다.
여기서 살펴본 예제에서는 int형으로 인자가 들어왔다.
그런데 우리는 const char *형식으로 받을 것이다.
char *형식에서는 어떻게 처리를 해줘야 하는지 한번 보자.
여기서는 다음의 세 개 형태를 처리해볼 것이다
: d(int) / c(char) / s(char *)
void print_dcs(char *dcs, ...)
{
va_list ap; //가변 인자 목록을 ap에 담을 것이다.
size_t i = 0;
va_start(ap, dcs); //dcs라는 문자열의 개수 만큼 ap가 이동할 것.
while (dcs[i] != '\0')
{
if (dcs[i] == 'd')
printf("%d ", va_arg(ap, int));
if (dcs[i] == 'c')
printf("%c ", va_arg(ap, char));
if (dcs[i] == 's')
printf("%s ", va_arg(ap, char *));
i++;
}
va_end(ap); //ap가 NULL을 가리키도록 만든다.
//end는 안정성을 위해 써주도록 한다.
printf("\n");
}
int main()
{
print_dcs("d", 10); // 정수
print_dcs("dc", 10, 'a'); // 정수, 문자
print_dcs("dcs", 10, 'a', "Hello42"); // 정수, 문자, 문자열
return (0);
}
결과 :
10
10 a
10 a Hello42
먼저 print_dcs가 인자로 char *을 받는 이유는 우리가 일반적으로 printf를 사용할 때에도
printf("something%something", ~);
이런 식으로 문자열을 넣기 때문이다.
위 예제에서 print_dcs("dcs", ~);
이런 식으로 명령을 내리면 print_dcs 함수 내부에서 va_start(ap, dcs)는
char * 형태로 들어온 dcs의 길이를 구해서(==3) ap가 그것 만큼 포인터를 이동시키도록 만든다.
우리가 사용한 것과 같이 print_dcs("dcs", 10, a, Hello42)를 예로 들어 설명해보겠다.
'Code 42 > ft_printf' 카테고리의 다른 글
printf 재구현하기 part3. pseudo-code (0) | 2020.06.29 |
---|---|
printf 재구현하기 part 2. (0) | 2020.06.29 |
최근댓글