自己实现myprintf函数

来源:互联网 发布:js 获取滚动条位置 编辑:程序博客网 时间:2024/06/05 04:00
#include <stdio.h>#include <stdarg.h>void printint(int dec){    if(0 == dec)    {        return;    }    printint(dec / 10);    putchar(dec % 10 + '0');}void printstr(char *str){    while(*str)    {        putchar(*str);        str++;    }}void printfloat(float flt){    int tempint = (int)flt;    int tempflt = (int)(100000 *(flt - tempint));    if(tempflt % 10 > 5)    {        tempflt = tempflt /10 + 1;    }    else    {        tempflt = tempflt / 10;    }    printint(tempint);    putchar('.');    printint(tempflt);}void myprintf(const char *format,...){    va_list ap;    va_start(ap,format);    while(*format)    {        if(*format != '%'){    putchar(*format);    format++;}else{    format++;    switch(*format)    {        case 'c':{    char val_ch = va_arg(ap,int);    putchar(val_ch);    format++;    break;}case 'd':{    int val_int = va_arg(ap,int);    printint(val_int);    format++;    break;}case 's':{    char * val_str = va_arg(ap,char *);                    printstr(val_str);    format++;    break;}case 'f':{    float val_flt = va_arg(ap,double);    printfloat(val_flt);    format++;    break;}default :{    putchar(*format);    format++;}    }}    }    va_end(ap);     }
va_start()宏初始化ap以供va_arg()和va_end()随后使用,并且必须在他们前面定义。参数last是可变参数列表之前的最后一个参数的名称,调用函数知道其类型的最后一个参数。因为这个参数的地址可能在va_start()宏中使用,它不应该被声明为寄存器变量,或者作为函数或数组类型。 va_start()宏初始化va_list型的变量ap,ap是存储参数地址的指针。因为得到参数的地址后,再结合参数的类型,就能得到参数的值。


      va_arg()宏扩展为具有调用中的下一个参数的类型和值的表达式。 参数ap是由va_start()初始化的va_list ap。 每次调用va_arg()都会修改ap,以便下一次调用返回下一个参数。参数类型是指定的类型名称,以便可以通过向类型中添加*来获取指向具有指定类型的对象的指针的类型。在va_start()宏之后第一次使用va_arg()宏将返回最后一个参数。 连续调用返回其余参数的值。如果没有下一个参数,或者如果类型与实际下一个参数的类型不兼容,则会出现随机错误。如果ap被传递给使用va_arg(ap,type)的函数,则ap的值在该函数返回后是未定义的。
 
依次使用va_arg宏使得ap返回可变参数的地址,得到这个地址后,结合参数的类型,就可以得到参数的值。

0 0