I need to recreate the `printf` function for a school project. My current function works flawlessly, except if there are two arguments.

If I do the following: `ft_printf("%c%c", 'a', 'b');`

it will print `aa`, instead of `ab`.

If I do the following: `ft_printf("%c%d", 't', 29);`

it will not print `t29` like it's supposed to.
Instead, it will print `t116` as it does detect that I would like to print an int, but doesn't use the right argument (it converts "t" in its ascii value (116)).

I have included below the code of my main `printf`function, the ft\_analysis function (to find the flags), the ft\_utilities\_one function (which has some basic functions like putchar() for example) as well as the parsing function I'm using to parse the string given as primary argument. Due to how many code there is, I have only included the `char` printing function (ft\_c\_craft) as an example. If you need more clarity regarding how these functions are used, you can find [here my printf repository](https://github.com/maxdesalle/42/tree/main/ft_printf).

ft\_printf.c

```
int ft_printf(const char *str, ...)
{
    t_list  box;
    va_list argptr;

    va_start(argptr, str);
    ft_parser(argptr, (char *)str, &box);
    va_end(argptr);
    return (box.len);
}

```

ft\_parser.c

```
static void ft_craft1(va_list argptr, t_list *box)
{
    if (box->type == 'c')
        ft_c_craft(va_arg(argptr, int), box);
    else if (box->type == 's')
        ft_s_craft(va_arg(argptr, char *), box);
    else if (box->type == 'd' || box->type == 'i')
        ft_di_craft(va_arg(argptr, int), box);
}

static void ft_craft2(va_list argptr, t_list *box)
{
    if (box->type == 'u')
        ft_u_craft(va_arg(argptr, unsigned int), box);
    else if (box->type == 'x')
        ft_xx_craft(va_arg(argptr, int), 0, box);
    else if (box->type == 'X')
        ft_xx_craft(va_arg(argptr, int), 1, box);
    else if (box->type == 'p')
        ft_p_craft(va_arg(argptr, unsigned long long), box);
}

static void ft_type_selector(va_list argptr, t_list *box)
{
    if (box->type == 'c' || box->type == 's' || box->type == 'd'
            || box->type == 'i')
        ft_craft1(argptr, box);
    else
        ft_craft2(argptr, box);
}

void        ft_parser(va_list argptr, char *str, t_list *box)
{
    int i;

    i = 0;
    while (str[i] != '\0')
    {
        if (str[i] == '%' && str[i + 1] != '%')
        {
            ft_analysis(&str[++i], box);
            while (ft_strchr("cspdiuxX", str[i]) == NULL)
                i++;
            if (ft_strchr("cspdiuxX", str[i]))
                box->type = str[i];
            ft_type_selector(argptr, box);
        }
        else if (str[i] == '%' && str[i + 1] == '%')
            ft_putchar(str[++i], box);
        else
            ft_putchar(str[i], box);
        i++;
    }
}

```

ft\_analysis.c

```
static void ft_precision(char *str, t_list *box)
{
    box->precision = 0;
    while (*str != '\0')
    {
        if (*str == '.')
        {
            box->precision = ft_atoi_alpha(++str);
            return ;
        }
        str++;
    }
    return ;
}

static void ft_width(char *str, t_list *box)
{
    box->width = 0;
    while (*str != '\0' && *str != '.')
    {
        if (*str >= '0' && *str <= '9')
        {
            box->width = ft_atoi_alpha(str);
            return ;
        }
        str++;
    }
    return ;
}

static void ft_flag(char *str, t_list *box)
{
    box->fzero = 0;
    box->fplus = 0;
    box->fminus = 0;
    box->fspace = 0;
    while (*str != '\0' && (!(*str >= '1' && *str <= '9')))
        if (*str++ == '0')
            box->fzero += 1;
    else if (ft_strchr(str, '+'))
        box->fplus += 1;
    else if (ft_strchr(str, '-'))
        box->fminus += 1;
    else if (ft_strchr(str, ' '))
        box->fspace += 1;
    return ;
}

void        ft_analysis(char *str, t_list *box)
{
    ft_precision(str, box);
    ft_width(str, box);
    ft_flag(str, box);
}

```

ft\_c\_craft.c

```
static void ft_print_char(char c, t_list *box)
{
    if (box->fminus == 1)
    {
        ft_putchar(c, box);
        ft_super_putchar(box->width - 1, ' ', box);
        return ;
    }
    else if (box->fzero == 1)
        ft_super_putchar(box->width - 1, '0', box);
    else if (box->fminus == 0)
        ft_super_putchar(box->width - 1, ' ', box);
    ft_putchar(c, box);
    return ;
}

void    ft_c_craft(char c, t_list *box)
{
    if (box->width > 1)
        ft_print_char(c, box);
    else
        ft_putchar(c, box);
}

```

ft\_utilities\_one.c

```
void    ft_putchar(char c, t_list *box)
{
    write(1, &c, 1);
    box->len += 1;
}

void    ft_putstr(char *str, t_list *box)
{
    while (*str != '\0')
    {
        write(1, str++, 1);
        box->len += 1;
    }
}

void    ft_putstr_precision(char *str, t_list *box)
{
    int i;

    i = box->precision;
    while (*str != '\0' && i-- > 0)
    {
        write(1, str++, 1);
        box->len += 1;
    }
}   

void    ft_super_putchar(int len, char c, t_list *box)
{
    while (len-- > 0)
    {
        write(1, &c, 1);
        box->len += 1;
    }
}

long    ft_atoi_alpha(const char *nptr)
{
    long    result;

    result = 0;
    while (*nptr && ((*nptr >= 9 && *nptr <= 13) || *nptr == ' '))
        nptr++;
    if (*nptr == '-' || *nptr == '+')
        nptr++;
    while (*nptr && *nptr >= '0' && *nptr <= '9')
        result = result * 10 + (*nptr++ - '0');
    return (result);
}

```
['https://Stackoverflow.com/questions/65466881', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/14608442/']
> 
> If I do the following: `ft_printf("%c%c", 'a', 'b');`
> 
> 
> it will print aa, instead of ab.
> 
> 
> If I do the following: `ft_printf("%c%d", 't', 29);`
> 
> 
> it will not print t29 like it's supposed to. Instead, it will print t116 as it does detect that I would like to print an int, but doesn't use the right argument (it converts "t" in its ascii value (116)).
> 
> 
> 

visibly you do not progress and always use the first argument, this is because you give the *va\_list* by value, so you use a copy of it and you cannot progress in the list of argument. Just give it by pointer

in *ft\_printf*

```
ft_parser(&argptr, (char *)str, &box);

```

and :

```
static void ft_craft1(va_list *argptr, t_list *box)
{
    if (box->type == 'c')
        ft_c_craft(va_arg(*argptr, int), box);
    else if (box->type == 's')
        ft_s_craft(va_arg(*argptr, char *), box);
    else if (box->type == 'd' || box->type == 'i')
        ft_di_craft(va_arg(*argptr, int), box);
}

```

etc
Use `switch() case` as in this simple example

```
int ts_formatstring(char *buf, const char *fmt, va_list va)
{
    char *start_buf = buf;
    while(*fmt)
    {
        /* Character needs formating? */
        if (*fmt == '%')
        {
            switch (*(++fmt))
            {
              case 'c':
                *buf++ = va_arg(va, int);
                break;
              case 'd':
              case 'i':
                {
                    signed int val = va_arg(va, signed int);
                    if (val < 0)
                    {
                        val *= -1;
                        *buf++ = '-';
                    }
                    ts_itoa(&buf, val, 10);
                }
                break;
              case 's':
                {
                    char * arg = va_arg(va, char *);
                    while (*arg)
                    {
                        *buf++ = *arg++;
                    }
                }
                break;
              case 'u':
                    ts_itoa(&buf, va_arg(va, unsigned int), 10);
                break;
              case 'x':
              case 'X':
                    ts_itoa(&buf, va_arg(va, int), 16);
                break;
              case '%':
                  *buf++ = '%';
                  break;
            }
            fmt++;
        }
        /* Else just copy */
        else
        {
            *buf++ = *fmt++;
        }
    }
    *buf = 0;

    return (int)(buf - start_buf);
}

```

PS not mycode it is from atollic - used for example purposes. Sme potential UBs.