목차
ft_printf
mandatory part
-가변인자
-서식지정자
-구현코드
Ft_printf mandatory part
보통 printf 함수를 사용할 때 앞부분은 출력할 서식지정자를 넣어주고 뒷 부분에 출력할 값을 넣어줍니다.
이 부분을 직접 구현하기 위해 stdarg 헤더에 있는 가변인자 관련 매크로를 사용합니다.
가변인자
가변인자 함수 사용에 대한 글
https://jhnyang.tistory.com/293
printf("%d", 1);
뒷 부분이 가변인자 인데, 이 목록을 담기 위해 va_list 를 사용합니다
printf("%d %d %d", 1, 2, 3);
va_arg 는 va_list 에 있는 뒷 부분의 값이 어떤 타입형태로 반환되게끔 합니다.
8진수이건 16진수이건 정수형태이건, va_arg(*ap, int); va_arg(*ap, unsigned int); 등으로 나타납니다.
해당 포인터로 va_list 에 있는 값에 접근 하여 매개변수로 넣어준 타입으로 반환합니다.
서식지정자
%c, %d, %i, %u, %x, %X, %p, %s
%c 정수를 문자로 해석
%d 부호 있는 10진수 정수로 해석
%i 부호 있는 10진수 정수로 해석
%u 부호 없는 10진수 정수로 해석
%x 부호 없는 16진수 정수로 해석(소문자)
%X 부호 없는 16진수 정수로 해석(대문자)
%p 포인터가 참조하고 있는 메모리의 주소값(8자리의 16진수)
%s 정수를 문자열로 해석
참고 자료
https://bigpel66.oopy.io/library/42/inner-circle/4
구현 코드
메인 로직을 보면 서식지정자가 담긴 포인터 format 을 가변인자 목록을 불러와(va_list) 해당 목록에 ap 포인터로 접근하여 인자를 담고(va_start) 그 인자에 하나하나 접근하여 해당 서식지정자에 맞게 va_arg를 사용하여 해당 서식지정자에 맞는 타입을 반환합니다. va_list 에 담겨있는 여러 값들을 ap 포인터로 va_arg 로 접근할 수 있어, 해당 서식지정자에 맞게 출력합니다.
해당 format 이 맞는지 format_checker 로 각각의 서식지정자에 맞게 맞춰 출력합니다.
#include "ft_printf.h"
int ft_putchar(char c)
{
int len;
len = write(1, &c, 1);
return (len);
}
int format_checker(char c, va_list *ap)
{
int len;
len = 0;
if (c == 'c')
len += ft_putchar(va_arg(*ap, int));
else if (c == '%')
len += write(1, "%", 1);
else if (c == 'd' || c == 'i')
len += ft_putnbr(va_arg(*ap, int));
else if (c == 'u')
len += ft_putunbr(va_arg(*ap, unsigned int));
else if (c == 'x')
len += ft_puthex(va_arg(*ap, unsigned int), 1);
else if (c == 'X')
len += ft_puthex(va_arg(*ap, unsigned int), 2);
else if (c == 'p')
{
len += write(1, "0x", 2);
len += ft_putadr(va_arg(*ap, unsigned long int));
}
else if (c == 's')
len += ft_putstr(va_arg(*ap, char *));
return (len);
}
int ft_printf(const char *format, ...)
{
va_list ap;
int len;
int i;
len = 0;
i = 0;
va_start(ap, format);
while (format[i])
{
if (format[i] != '%')
len += write(1, &format[i], 1);
else
{
len += format_checker(format[i + 1], &ap);
i++;
}
i++;
}
va_end(ap);
return (len);
}
각각의 서식지정자에 맞게 출력함수들을 구현했습니다. format_checker 로 넘어온 값을 아래 함수들로 각각에 맞게 출력하게끔 분기해줍니다.
#include "ft_printf.h"
int ft_putnbr(int nb)
{
long long n;
int len;
n = nb;
len = 0;
if (n < 0)
{
len += write(1, "-", 1);
n *= -1;
}
if (n >= 10)
{
len += ft_putnbr(n / 10);
len += ft_putnbr(n % 10);
}
else
len += ft_putchar(n + 48);
return (len);
}
int ft_putadr(unsigned long int nb)
{
int len;
len = 0;
if (nb >= 16)
{
len += ft_putadr(nb / 16);
len += ft_putadr(nb % 16);
}
else
{
if (nb < 10)
len += ft_putchar(nb + 48);
else
len += ft_putchar(nb + 87);
}
return (len);
}
int ft_putunbr(unsigned int nb)
{
int len;
len = 0;
if (nb >= 10)
{
len += ft_putunbr(nb / 10);
len += ft_putunbr(nb % 10);
}
else
len += ft_putchar(nb + 48);
return (len);
}
int ft_puthex(unsigned int nb, int s)
{
int len;
len = 0;
if (nb >= 16)
{
len += ft_puthex(nb / 16, s);
len += ft_puthex(nb % 16, s);
}
else
{
if (nb < 10)
len += ft_putchar(nb + 48);
else
{
if (s == 1)
len += ft_putchar(nb + 87);
else
len += ft_putchar(nb + 55);
}
}
return (len);
}
int ft_putstr(char *str)
{
int len;
len = 0;
if (!str)
str = "(null)";
while (*str)
len += write(1, str++, 1);
return (len);
}
'42Seoul' 카테고리의 다른 글
[42Seoul][GetNextLine] Get Next Line - mandatory part [C] (0) | 2022.05.22 |
---|