CS(computer science)

ft_print 구현해보기(printf, 가변인자 이해하기)

ebang 2022. 11. 29. 23:00
반응형

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);
}

 

반응형