반응형
printf를 구현하면서 느낀 중요한 것들을 정리하려고 한다.
Mandatory part
<공부, 평가 기준>
* 주관적인 기준이다.
1. 가변인자 va_list 를 사용할 수 있는가?
2. printf의 원리를 아는가?
3. putstr, putnbr, putchar 를 올바르게 구현할 줄 아는가?
#hint
1. #include <stdarg.h> 부터 시작하자.
2.(bonus part에서 진행하는 진짜 format : 정확도, padding 등에 대한 건 나중에 정리하려고 한다)
%이후 format이 있다. 두번째 인자부터는 format에 해당하는 진짜 변수
3. int, unsigned int, unsigned long long 변수를 잘 이해했으며
이를 write함수를 이용해 출력할 수 있는가?
(특히 숫자 출력시 재귀 함수 이용, 오버플로우에 대한 이해)
#include <unistd.h>
#include <stdarg.h>
int ft_strlen(char *str)
{
int i = 0;
while(str[i] != '\0')
i++;
return i;
}
int ft_putchar_fd(char c, int fd)
{
return(write(fd, c, 1));
}
int ft_putstr_fd(char *str, int fd)
{
int i = 0;
while(*str)
{
i+= ft_putchar_fd(*str, fd);
str++;
}
return i;
}
void ft_print(int nb)
{
char print;
if (nb >= 10)
ft_print (nb /10);
ft_putchar_fd (nb%10 - '0',1);
}
/*
2
13
124
1235
*/
int ft_number(int n) //자릿수 세는 함수
{
int copy = n;
int cnt = 0;
while (copy > 0)
{
cnt++;
copy /= 10;
}
return cnt;
}
/*
10 (0)
1 (1)
0(2)
*/
int ft_putnbr(int n)
{
int i;
i = 0;
if(nb == -2147483648)
return (write(1, "-2147483648", 11));
else if(nb == 0)
return(write(1, "0", 1));
else if(nb < 0)
{
nb = -nb;
i += write(1, "-", 1);
i += ft_number(nb);
ft_print(nb);
}
else
{
i += ft_number(nb);
ft_printf(nb);
}
return i;
}
int ft_put_pointer(void *pointer)
{
unsigned long long p;
int ret;
ret = 0;
ret = ft_put_str_fd("0x", 1);
p = (unsigned long long)pointer;
ret += ft_putnbr_unsigned_base(p, "0123456789abcdef");
return ret;
}
int ft_unumber(unsigned long long nb, int base)
{
unsigned long long copy = nb;
int cnt = 0;
while(copy >0)
{
cnt++;
copy /= base;
}
return cnt;
}
void ft_print_ubase(unsigned long long nb, int card, char *base)
{
if(nb >= card)
ft_print_unsigned(nb/10, card);
write(1, &base[nb % card], 1);
}
/*
card = 16
10 = A
11 = B
256 => 100
1 ->1
16 ->0
256 ->0
*/
int ft_putnbr_unsigned_base(unsigned long long nbr, char *base)
{
int card;
unsigned long long int n;
int ret;
ret = 0;
n = nbr;
card = ft_strlen(base);
if(nbr < 0)
return (0);
else if(nbr == 0)
return (write(1, "0",1));
else
{
ret += ft_number(n, card);
ft_print_ubase(number, card, base);
}
return ret;
}
int ft_printf_conv(char *fmt, va_list *ap)
{
int ret;
ret = 0;
if (*fmt == 'c')
ret += ft_putchar_fd((char)va_arg(*ap, int), 1);
else if(*fmt == 's')
ret += ft_putstr_fd((char*)va_arg(*ap, char *), 1);
else if(*fmt == 'd'|| *fmt == 'i')
ret += ft_putnbr_fd((int)va_arg(*ap, int));
else if(*fmt == 'p')
ret += ft_put_pointer((void*)va_arg(*ap, (void*));
else if (*fmt == 'u')
ret += ft_putnbr_unsigned_base(unsigned int)va_arg(*ap, unsigned int, "0123456789");
else if(*fmt == 'x')
ret += ft_putnbr_unsigned_base((unsigned int)va_arg(*ap, unsigned int), "0123456789abcdef");
else if(*fmt == 'X')
ret += ft_putnbr_unsigned_base((unsigned int)va_arg(*ap, unsigned int), "0123456789ABCDEF");
else if(*fmt == '%')
ret += ft_put_char_fd('%s', 1);
return ret;
}
int ft_printf(const char *fmt, ...)
{
va_list ap;
int ret = 0;
va_start(ap, fmt);
while(*fmt)
{
if(*fmt != '%')
{
ret += ft_putchar_fd(*fmt, 1);
fmt++;
}
if(*fmt == NULL)
return ret;
ret += ft_printf_conv((char*)fmt, &ap);
fmt++;
}
return ret;
}
int main()
{
char *str = "hello world";
ft_printf("the string is: %s\n", str);
}
반응형
'CS(computer science)' 카테고리의 다른 글
makefile 오류 - 'linker' input unused [-Werror,-Wunused-command-line-argument] (0) | 2022.12.10 |
---|---|
컴퓨터네트워크 - 애플케이션 계층 (간단 맛보기) (1) | 2022.12.04 |
linux - pthread_create 매뉴얼 뜯어보기[pthread] (4) | 2022.12.01 |
Makefile 뜯어보기 (0) | 2022.11.29 |
linux - 메모리 릭 확인하는 법[쉘, 리눅스, do leaks] (4) | 2022.11.29 |