ft_printf 과제는 7월에 문제가 수정되었다
<stdio.h>
헤더파일 안에 있으며
int printf(const char *restrict format, ...)
로 정의된다.
출저 : https://linux.die.net/man/3/printf
첫 번째 매개 변수로 문자열(format)이 입력되고, 그 이후는 가변 인자로 n개의 매개 변수를 받는다.
반환값이 int형으로 정의된 이유는 출력된 문자열의 수가 반환됨
format은 %[parameter][flags][width][.precision][length] type
형식을 가지며 해석하면
%[n][flag][출력 너비][출력되는 값(숫자)의 정확도][데이터 타입 범위] type(서식문자)
이다.
.만 사용된 경우
.n이 입력된 경우 앞의 width를 무시하고 n만큼 출력됨
문제 정리글에 적음
printf함수의 매개 변수는 0 ~ n개의 값을 가질 수 있으며, format의 형식 지정자값에 따라 매개 변수의 수가 다르다.
예를들어
printf("%d %d %d", 1, 2, 3, 4);
`
인 경우, 형식 지정자가 3개 이므로 매개 변수는 최소 3개 이상이 와야한다. 형식 지정자보다 매개 변수가 많을 경우 그 이후는 무시된다.
그러므로 형식 지정자 <= 매개 변수 조건이 맞춰줘야 한다.
가변 인자에 사용할 함수는 <stdarg.h>
헤더 파일 안에 있다.
va_list
는 가변 인자의 메모리 주소를 저장할 포인터이다.
#include <stdio.h>
#include <stdarg.h>
void printNumbers(int args, ...)
{
va_list ap; // 가변 인자의 주소를 저장할 포인터 선언
va_start(ap, args); // 가변 인자 변수가 args이후에 들어올 변수를 가르키게 한다
for (int i = 0; i < args; i++)
{
int num = va_arg(ap, int); // 가변 인자 변수에서 int자료형 크기만큼 데이터를 읽고 int형으로 반환
printf("%d ", num);
}
va_end(ap); // 가변 인자 변수를 NULL로 초기화
}
int main()
{
printNumbers(4, 10, 20, 30, 40); // 인수 개수 4개
return 0;
}
그림으로 표현하면 va_start(ap, args)
한 순간 ap는 args이후 매개 변수를 가르키고 있다.
코드, 그림 출저 : https://dojang.io/mod/page/view.php?id=577
int num = va_arg(ap, int);
char ch = va_arg(ap, int);
%d, %c같이 int나 char형의 값을 읽어올 때 동일하게 int형을 사용했다.
int형은 4byte char형은 1byte인데 왜 똑같이 사용하는 걸까?
평가 진행 중, 한 평가자가 이런 질문을 했는데 대답하질 못했다.
그 평가자분이 답을 알려주셨는데 va_list 자료형이 내부적으로 가르키는 값은 4byte씩 나뉘어져 있어서 char, int 자료형을 동일하게 사용한다는 것이다.
지금와서 생각해보면 va_list 자료형은 포인터 변수이고, 포인터 변수는 4byte이기 때문에
가변 인자들이 4byte씩 나뉘어져있다고 생각한다.
bonus part는 못했고 mandatory part만 했다.
int ft_printf(const char *format, ...)
{
int result;
va_list ap;
result = 0;
va_start(ap, format);
result = parse_format(ap, (char *)format);
va_end(ap);
return (result);
}
va_list 가변 인자 포인터 변수를 ap라는 이름으로 선언하고, va_start(ap, format)
를 이용해 가변 인자를 가르키게 했다.
이제 ap(가변 인자를 가르킴), format을 parse_format함수를 이용해 문자열을 파싱하며 출력하고 출력된 문자열의 수를 반환하게 했다.
int parse_format(va_list ap, char *format)
{
int result;
result = 0;
while (*format)
{
if (*format == '%')
{
format++;
if (*format == 0)
break ;
/*
서식 문자에 따라 맞는 값을 출력한다.
*/
}
else
result += ft_putchar(*format); // 일반 문자를 출력
format++;
}
return (result);
}
ft_printf("test%d", 123)
"test%d" 라는 문자열이 들어오면 처음부터 문자열의 끝까지 순회하며
일반 문자의 경우 바로 출력하고, %(서식문자)인 경우 다음 문자를 확인에 해당하는 값을 가변인자에서 읽어와 출력한다.
if (*format == 0)
break ;
이 코드를 넣은 이유는 ft_printf("test %")
와 같이 맨 끝에 %만 있을 경우 다음 문자를 확인할 때 NULL을 검사하기 때문에 문제가 생길 수 있어 NULL일 경우 바로 빠져 나오게 했다.
https://github.com/paulo-santana/ft_printf_tester
https://github.com/chronikum/printf42_mandatorytester
https://github.com/Tripouille/printfTester