如何以与whilef循环中printf打印字符相同的方式打印字符?

时间:2017-10-23 22:05:38

标签: c printf libc

我正在尝试复制printf,但我无法弄清楚如何让我的行为与printf循环while行为相同。

这是我正在使用的while循环:

while (i-- > 0) {
    ft_printf("myprintf");
    ft_putchar('\n');
    printf("realprintf");
    ft_putchar('\n');
}

这是结果

myprintf

myprintf

myprintf

myprintf

myprintf

myprintf

myprintf

myprintf

myprintf

myprintf

realprintfrealprintfrealprintfrealprintfrealprintfrealprintfrealprintfrealprintfrealprintfrealprintf%

这是我当前的printf,我相对较新,因此代码可能非常糟糕且效率低下,对它的评论将不胜感激

int ft_printf(const char *orgstr, ...)
{
    va_list args;
    char flagprefix;
    int i;

    flagprefix = '%';
    i = 0;
    while(orgstr[i])
    {
        va_start(args, orgstr);
        if(orgstr[i] == flagprefix)
            flag_handler(orgstr[i++], args);
        else
            ft_putchar(orgstr[i]);
        i++;
        va_end(args);
    }
    return (0);
}

flag_handler函数尚未完成,但我提供的示例无论如何都不会调用该函数。

2 个答案:

答案 0 :(得分:1)

您观察到的问题来自ft_putchar()和真实printf()使用的不同缓冲机制。您可以通过在stdout的开头和结尾处或在ft_printf()循环中的调用之间刷新while来解决此问题:

while (i-- > 0) {
    fflush(stdout);
    ft_printf("myprintf");
    ft_putchar('\n');
    fflush(stdout);
    printf("realprintf");
    fflush(stdout);
    ft_putchar('\n');
    fflush(stdout);
}

请注意,您的ft_printf()功能框架存在问题:

  • 您应该在循环开始前使用args初始化va_start,而不是格式字符串中的每个字符。
  • 如果您将va_list传递给flag_handler函数,则其上的副作用可能不会反映回调用方。您应该直接从ft_printf()函数中提取变量参数列表中的参数。

以下是修改后的版本:

int ft_printf(const char *orgstr, ...) {
    va_list args;
    int i, c;

    va_start(args, orgstr);
    i = 0;
    while ((c = orgstr[i++]) != '\0') {
        if (c == '%') {
            switch (c = orgstr[i++])) {
            case 's':
                ft_putstr(va_arg(args, char *));
                continue;
            /* ... handle other cases ... */
            case '\0':
                break;
            default:
                ft_putchar(c);
                continue;
            }
            break;
        } else {
            ft_putchar(c);
        }
    }
    va_end(args);
    return 0;
}

答案 1 :(得分:0)

我认为这是经典的缓冲标准输出。你可以打电话

fflush(stdout);

在循环结束时确保将所有内容发送到屏幕。

你是如何编写printf版本的?