C\C++_格式化_可变参va_list

本文详细介绍了C语言中如何使用`va_list`实现变长参数列表,通过实例展示了如何创建简化版的`printf`函数。同时,讲解了`vsprintf`和`vsprintf_s`两个格式化输出函数的应用,分别用于将格式化的输出写入字符串。通过这些示例,读者可以深入理解C语言中变长参数的处理和使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. va_list变量介绍

  1. 使用前需引用头文件<stdarg.h>
  2. va_list 类型本质是typedef char * va_list
  3. va_list类型声明一个变量(char * ),假设这里声明va_list pArgs,该字符指针变量将依次指向后续待传入的各参数(无名参数…)
  4. 宏va_start将pArgs初始化为指向第一个无名参数(无名参数…),在使用pArgs之前,必须用该宏调用一次。函数参数表中至少包括一个有名参数 (const char *pszFormat,…)
  5. 每次调用va_arg,该宏都将会返回当前pArgs指向的参数,并将pArgs指向下一个参数,va_arg使用一个类型名来决定返回的对象类型、指针移动的步长。
  6. 最后,必须在函数返回之前调用va_end,来完成一些必要的清理工作

1.1 基于上面的介绍,实现一个简化版本printf函数

#include <stdarg.h>
/* minprintf: minimal printf with variable argument list */
//这里只实现了打印%d,%f,%s
void minprintf(char *fmt, ...)
{
	va_list pArgs; 	/* 依次指向每个未命名参数... */
	char *p, *sval;
	int ival;
	double dval;
	va_start(pArgs, fmt); /* 初始化pArgs,使pArgs指向第一个未命名参数*/
	for (p = fmt; *p; p++) 
	{
		if (*p != '%') 
		{
			putchar(*p);
			continue;
		}
		switch (*++p) 		//先进行++操作,为了取到%符号后面的字符d,f,s等
		{
		case 'd':
			ival = va_arg(pArgs, int);
			printf("%d", ival);
			break;
		case 'f':
			dval = va_arg(pArgs, double);
			printf("%f", dval);
			break;
		case 's':
			for (sval = va_arg(pArgs, char *); *sval; sval++)
				putchar(*sval);
			break;
		default:
			putchar(*p);
			break;
		}
	}
	va_end(pArgs); /* 完成后,清理工作 */
}

2. 其它涉及va_list函数的应用

2.1 vsprintf格式化函数的应用

/**************************************************************************************************
C 库函数 int vsprintf(char *str, const char *format, va_list arg) 使用参数列表发送格式化输出到字符串。
*****************************************************************************************************/
int PrintMessage(char *format,...)
{
	int nRet = 0;
	char buf[80] = { 0 };

	va_list pArgs;
	va_start(pArgs, format);				//字符指针pArgs指向参数列表第一个未名参数(即format格式化所对应的...实际参数)
	nRet = vsprintf(buf, format, pArgs);	//格式化到buf中
	va_end(pArgs);							//清理工作
	
	printf("%s\n", buf);
	return nRet;
}

void main(void)
{
	int i = 10;
	float f = 20.4;
	char *str = "hello world";
	PrintMessage("i = %d; f = %f; str = %s", i, f, str);
}

2.2 vsprintf_s格式化函数的应用

/**************************************************************************************************
int vsprintf_s(char * _DstBuf, size_t _SizeInBytes, const char * _Format, va_list _ArgList);
*****************************************************************************************************/
void PrintMessage_s(const char *pszFormat,...)
{
	char buf[512] = { 0 };
	va_list pArgs;
	va_start(pArgs, pszFormat);						  //初始化,pArgs指向有参列表...的第一个未名参数
	vsprintf_s(buf, sizeof(buf), pszFormat, pArgs);   //格式化到buf中
	va_end(pArgs);									  //格式化完成后,清理工作

	printf("%s\n", buf);
}

void main(void)
{
	int a = 10;
	float f = 30.5;
	char *str = "hello world";
	PrintMessage_s("a = %#x, f = %f, str = %s\n", a, f, str);
}

3. 参考文献

菜鸟教程C库函数—vsprintf
《The_c_Programming_Language》第二版中文版_第7章 输入与输出_7.3变长参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值