typedef char * va_list;
va_list 的是一个字符指针,可以理解为指向当前参数的一个指针,取参必须通过这个指针进行。
1、va_list 用来声明一个表示参数表中各个参数的变量。
2、va_start 初始化一个指针来指向变长参数列表的头一个变量(注意,…只能出现在参数表的最后)
3、va_arg每次调用时都会返回当前指针指向的变量,并将指针挪至下一个位置,
参数的类型需要在这个调用的第二个参数来指定,va_arg也是根据这个参数来判断偏移的距离。4、va_end需要在函数最后调用,来进行一些清理工作。
void my_puts(char *s)
{
if(s == NULL)
{
printf("my_puts err!\n");
exit(1);
}
while(*s != '\0')
{
putchar(*s);
s++;
}
}
int my_printf(const char *str,...)
{
if(str == NULL)
{
printf("my_printf errr!\n");
exit(1);
}
va_list ap;
va_start(ap,str);
char buf[128]={0};
int count = 0;
char ch = ' ';
const char *start = str;
char *s = NULL;
int value;
while(*start != '\0')
{
if(*start == '%')
{
start++;
switch(*start)
{
case 's':
s = va_arg(ap,char *);
my_puts(s);
count += strlen(s);
break;
case 'c':
ch = va_arg(ap,char);
putchar(ch);
count++;
break;
case 'd':
value = va_arg(ap,int);
#ifdef WIN32
_itoa_s(value,buf,10);
#else
sprintf_s(buf,"%d",value);
#endif
my_puts(buf);
count += strlen(buf);
break;
case 'o':
value = va_arg(ap,int);
sprintf_s(buf,"%o",value);
my_puts(buf);
count += strlen(buf);
break;
case 'x':
value = va_arg(ap,int);
sprintf_s(buf,"%x",value);
my_puts(buf);
count += strlen(buf);
break;
default:
break;
}
start++;
}
if(*start == '\\')
{
start++;
if(*start =='n')
{
puts(NULL);
}
if(*start == 't')
{
putchar(' ');
putchar(' ');
putchar(' ');
putchar(' ');
}
start++;
}
putchar(*start);
start++;
count++;
}
va_end(ap);
return count;
}