/*************************************************************************
> File Name: va_list.c
> Author: zshh0604
> Mail: zshh0604@.com
> Created Time: 2014年10月14日 星期二 15时16分09秒
************************************************************************/
#include<stdio.h>
/***
在 c中使用可变參数,

c语言中提供一个va_list类型要存储函数的可变參数。

1.在c语言中定义函数的可变參数方法例如以下:

一:该參数必须在最后。
二:最后一个參数必须声明可变參数的类型。例如以下
三:能够參数是使用三点表示。

四:在函数调用的使用通过fmt这个字符參数进行參数类型和參数个数的设定。如:"%s%d%c%f"

void test(char *fmt,...);

2.假设使用可变參数。

c提供一个例如以下一组函数:
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);
对可变參数进行操作。函数原型。

void va_start(va_list ap,last);

函数功能:
将ap依次指向可变參数。
函数參数:
ap:会依次指向每个可变參数。

last:是fmt,它的作用是,规定了參数可变參数的个数。和类型。
函数返回值:
没有返回值。


在调用该组函数之前必须先调用va_start()函数。

通过fmt格式化字符中的格式。来一次获取该參数的值。


char *s;
int d;
char c;
while(*fmt)
{
switch(*fmt++)
{
case 's':
s = va_arg(ap, char *);
break;
case 'd':
d = va_arg(ap, int);
break;
case 'c':
c = va_arg(ap, char);
break;
}
}
va_end(ap);
在函数结束前,必须调用va_end()函数。


使用vsnprintf()直接使用ap.

vsnprintf():函数原型例如以下:
int vsnprintf(char *str, size_t size, const char *format, va_list ap);

该方法使用例如以下:

// va_list 的作用:
// 头文件<stdarg.h>提供了遍历未知数据和类型的函数參数表的功能。
// 那么,在函数f内声明一个类型为va_list的变量ap.它将依次指向每个实际的參数。
//
// va_list ap;
//
// 在訪问不论什么未命名的參数前,必须使用va_start宏初始化ap一次。

//
// va_start(va_list ap,lastarg);
//
// 此后每次运行宏va_arg都将产生一个与下一个未命令的參数具有同样类型和数值的值。

// 它同一时候还改动ap,以使得下一次运行va_arg时返回下一个參数。
//
// 类型 va_arg(va_list ap,类型);
//
// void ve_end(va_list ap);
//
// 在全部处理的參数处理完成之后。且在退出f之前。必须调用宏va_end一次。

//
// void va_end(va_list ap);


**/

/*************************************************************************
> File Name: snprintf.c
> Author: zshh0604
> Mail: zshh0604@.com
> Created Time: 2014年10月14日 星期二 13时21分13秒
************************************************************************/
#include<stdlib.h>
#include<stdio.h>
#include<stdarg.h>
char * make_message(const char *fmt, ...)
{

int n; /* 用来记录vsnprintf()的返回之。
假设这个值小于等于-1,寿命。分配的空间不够。

假设这个值大于-1,可是n不小于size,那么应该把该值加1,(size+1),否则将空间加大一倍 ***/

int size = 100; /* Guess we need no more than 100 bytes. */
char *p, *np;
va_list ap;


if ((p = malloc(size)) == NULL)
return NULL;
while (1) {
/* Try to print in the allocated space. */

va_start(ap, fmt); //通过这个函数,使得ap指向可变參数中每个參数。
n = vsnprintf(p, size, fmt, ap); //将ap指向的參数格式化到p中。
p的最大大小为size.依照fmt格式打印。

va_end(ap); //使用结束之后,调用va_end(ap);函数。


/* If that worked, return the string. */

if (n > -1 && n < size)
return p;

/* Else try again with more space. */

if (n > -1) /* glibc 2.1 */
size = n+1; /* precisely what is needed */
else /* glibc 2.0 */
size *= 2; /* twice the old size */

if ((np = realloc (p, size)) == NULL) {

free(p);
return NULL;
} else {
p = np;
}
}
}