如何编写自定义printf?

时间:2017-10-08 13:02:14

标签: c variadic-functions

我有问题。我尝试自定义printf(),但是当我编译此代码时,输​​出似乎没有像预测的那样出现。

#include <stdio.h>
#include <stdarg.h>
void print(char *, ...);

int main()
{
    char str[12]="World";
    char c='A';
    int i=100;
    print("Hello %s %c", str, c);
}

void print(char *c, ...)
{
    char *s;
    va_list lst;
    va_start(lst, c);
    while(*c!='\0')
    {
        if(*c!='%')
        {
            putchar(*c);
            c++;
            continue;
        }
        c++;
        switch(*c)
        {
        case 's': fputs(va_arg(lst, char *), stdout); break;
        case 'c': putchar(va_arg(lst, int)); break;
        }
    }    
}

似乎来的输出:Hello World 输出:Hello Worlds Ac 我无法弄清楚为什么,c&#39;出现。

1 个答案:

答案 0 :(得分:3)

在切换案例之后,您不会递增指针c,因此while循环会再次为您用作选项的字符运行。

只需在切换案例后添加c++,就像这样:

void print(char *c, ...)
{
    char *s;
    va_list lst;
    va_start(lst, c);
    while(*c!='\0')
    {
        if(*c!='%')
        {
            putchar(*c);
            c++;
            continue;
        }
        c++;
        switch(*c)
        {
            case 's': fputs(va_arg(lst, char *), stdout); break;
            case 'c': putchar(va_arg(lst, int)); break;
        }
        c++;
    }
}

进行此更改后,我建议找一些方法来处理字符串末尾出现%的情况,以避免遇到缓冲区溢出。例如,在切换之前,可能检查我们是否已达到空终止符,如果是,则跳出循环。

void print(char *c, ...)
{
    char *s;
    va_list lst;
    va_start(lst, c);
    while(*c != '\0')
    {
        if(*c != '%')
        {
            putchar(*c);
            c++;
            continue;
        }

        c++;

        if(*c == '\0')
        {
            break;
        }

        switch(*c)
        {
            case 's': fputs(va_arg(lst, char *), stdout); break;
            case 'c': putchar(va_arg(lst, int)); break;
        }
        c++;
    }
}