c-为什么我的printf函数中的变量函数不起作用



我需要为学校项目重新创建printf函数。我当前的函数工作得很完美,除非有两个参数。

如果我执行以下操作:ft_printf("%c%c", 'a', 'b');

它将打印aa而不是ab

如果我执行以下操作:ft_printf("%c%d", 't', 29);

它不会像预期的那样打印CCD_ 6。相反,它将打印t116,因为它确实检测到我想打印一个int,但没有使用正确的参数(它在其ascii值中转换"t"(116((。

我在下面包含了我的主printf函数、ft_analysis函数(用于查找标志(、ft_utilities_one函数(例如,它有一些基本函数,如putchar(((以及我用来解析作为主参数的字符串的解析函数的代码。由于代码太多,我只以char打印函数(ft_c_craft(为例。如果您需要更清楚地了解如何使用这些函数,您可以在这里找到我的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] != '')
{
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 != '')
{
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 != '' && *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 != '' && (!(*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 != '')
{
write(1, str++, 1);
box->len += 1;
}
}
void    ft_putstr_precision(char *str, t_list *box)
{
int i;
i = box->precision;
while (*str != '' && 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);
}

如果我执行以下操作:ft_printf("%c%c", 'a', 'b');

它将打印aa,而不是ab。

如果我执行以下操作:ft_printf("%c%d", 't', 29);

它不会像预期的那样打印t29。相反,它会打印t116,因为它确实检测到我想打印int,但没有使用正确的参数(它在其ascii值中转换"t"(116((。

很明显,你没有进步,总是使用第一个参数,这是因为你按值给了va_list,所以你使用了它的副本,你不能在参数列表中进步。只需通过指针

ft_printf

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

和:

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

使用switch() case作为这个简单的示例

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不是霉菌,它来自环礁岛——用于举例说明。Sme潜在UBs。

最新更新