标准头文件<stdarg.h>
包含一组宏定义, 它们对如何遍历参数表进行了定义.
va_list ap; //参数指针
宏va_start
将ap初始化为指向第一个无名参数的指针,使用ap之前,va_start必须被调用一次.参数表至少包含一个有名参数,va_start将最后一个有名参数作为起点.
每次调用va_arg
,该函数都返回一个参数, 并将ap 指向下一个参数.
va_arg使用一个类型名来决定返回的对象类型, 指针移动的步长.
必须在函数返回之前调用va_end
完成一些清理工作.
minprintf
#include <stdio.h>
#include <stdarg.h>
/* minprintf: minimal printf with variable argument list */
void minprintf (char *fmt, ...)
{
va_list ap; /* points to each unnamed arg in turn */
char *p, *sval;
int ival;
double dval;
va_start(ap, fmt); /* make ap point to 1st unnamed arg */
for (p = fmt; *p; p++){
if (*p != '%') {
putchar (*p);
continue;
}
switch (*++p) {
case 'd':
ival = va_arg(ap, int);
printf("%d", ival);
break;
case 'f':
dval = va_arg(ap, double);
printf("%f", dval);
break;
case 's':
for (sval = va_arg(ap, char *); *sval; sval++)
putchar(*sval);
break;
default:
putchar(*p);
break;
}
}
va_end(ap); /* clean up when done */
}
int main ()
{
minprintf ("%d %s %f\n", 123, "today", 12);
return 0;
}
minscanf
scanf 函数忽略格式串中的空格和制表符.
注意,scanf 和 sscanf 函数的所有参数都必须是指针.
从string中读取.
int sscanf(char *string, char *format, arg1, arg2, ...)
#include <stdio.h>
#include <stdarg.h>
int minscanf (char *fmt, ...)
{
va_list ap;
int n, *ival;
double *dval;
char c, *p, *sval;
n = 0;
va_start(ap, fmt);
for (p = fmt; *p; p++){
if (*p != '%'){
c = getchar();
//if (c == '\n')
// c = getchar();
if(*p == c)
continue;
else {
break;
return n;
}
}
switch (*++p) {
case 'd':
ival = va_arg(ap, int *);
if (scanf("%d", ival))
n++;
else
return n;
break;
case 's':
sval = va_arg(ap, char *);
if (scanf("%s", sval))
n++;
else
return n;
break;
case 'l':
if (*++p == 'f'){
dval = va_arg(ap, double *);
if (scanf("%lf", dval))
n++;
else
return n;
}
default:
return n;
}
}
va_end(ap);
return n;
}
int main ()
{
int i;
char s[20];
double d;
int n = minscanf("%d/%s %lf", &i, s, &d);
printf("%d %s %.f\t%d\n", i, s, d, n);
return 0;
}