实现类似printf这样的函数

来源:http://www.vimer.cn/2009/12/cc%E5%AE%9E%E7%8E%B0%E5%A4%9A%E5%8F%82%E6%95%B0%E5%87%BD%E6%95%B0%E7%BC%96%E7%A8%8B.html

在C/C++中,我们经常会需要实现类似printf这样的函数,即函数的参数个数是不定的,这个时候就需要用到我们这篇文章讲到的方法啦。
首先,我们要知道这种函数,如何来定义。比如我想实现一个函数能够支持 fun("%d",1);
那么这个函数的定义实际上如下:

void fun(const char *fmt, ...);

其中...的意思是说参数无法一一列出,所以用...代替,至于怎么解,我们稍后再说。
比较特殊的一点是,如果你希望将上面的函数定义成一个宏,那么这个宏可以这样写:

#define FUN(fmt, args...)    fun(fmt, ##args)

又假设你希望宏能够自动加上换行符,那么可以这样写:

#define FUN(fmt, args...)    fun(fmt"\n", ##args)

OK,那么函数定义的问题我们就解决啦,但是怎么来解呢?
C里面提供了va_start,va_arg,va_end这样几个函数,解释如下:
va_start使argp指向第一个可选参数。va_arg返回参数列表中的当前参数并使argp指向参数列表中的下一个参数。va_end把argp指针清为NULL。函数体内可以多次遍历这些参数,但是都必须以va_start开始,并以va_end结尾。
可能只是这样说并不是很清楚,我们举个例子。
1、假设我们现在想要fun实现和printf一样的功能,那么实际上,我们是不需要把所有解析出来的,我们只有把参数原样传给printf即可,代码如下:

void fun(const char* fmt,...){    va_list ap;    va_start(ap, fmt);//将ap指向fmt后的第一个参数    vfprintf(stderr,fmt,ap);    va_end(ap);//将ap置为NULL}

2、假设我们现在是要将传入的参数都取出来,那么我们就要用到va_arg了,代码如下:

void fun(const char* fmt,...){    va_list ap;    va_start(ap, fmt);//将ap指向fmt后的第一个参数    int value = va_arg(ap,int);//前提是我们知道第一个参数是int型;指针指向下一个参数     printf("value[%d]\n",value);    va_end(ap);//将ap置为NULL}

其实到这里大家也就不难发现,我们如何能遍历所有的参数了,只要规定好最后一个参数为一个特殊字符,比如说-1,然后判断到这个值就停止就行

void fun(const char* fmt,...){    va_list ap;    va_start(ap, fmt);//将ap指向fmt后的第一个参数    int value;    do{        value = va_arg(ap,int);//前提是我们知道第一个参数是int型;指针指向下一个参数         printf("value[%d]\n",value);    }while(value!=-1);    va_end(ap);//将ap置为NULL}

OK,到此为止,可变参数的函数编写应该也就很明了啦~

 jpg 改 rar

时间: 2024-11-08 21:35:56

实现类似printf这样的函数的相关文章

c语言中scanf()、printf()函数

函数调用scanf(“%d”,  &weight) 包含两个参数:“%d” 和&weight.C用逗号来隔开函数调用中的多个参数: 但是printf()和scanf()函数比较特殊,其函数数目可以不受控制. 例如,我们可以使用1个.2个.3个甚至4个参数调用printf()函数.而程序需要知道参数的数目才能正常工作,这两个函数通过第一个参数确定后续参数的个数,方法是第一个参数字符串中的每个说明符对应了后面的一个参数. 以下语句包含两个格式说明符:%d 和%d printf(“%d cats

黑 马 程 序 员_视频学习总结<c语言>----02 printf和scanf函数、基本语句和运算、流程控制、函数、数组、字符串

---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- 一.printf函数 1.在使用peintf函数前必须加入#include <stdio.h>,使用它可以向标准输出设备(比如屏幕)输出数据,其中使用格式是 printf(“字符串”) :或者 printf(“字符串”, 格式符参数): 2.常用的格式符及其含义如图所示 3.格式符还可以添加输出宽度 二.scanf函数 1.在使用scanf函

js实现类似php中strtotime函数和timetostr的日期转换/互换功能

<script type="text/javascript">   //日期(格式:yyyy-mm-dd H:i:s) ---转换为以秒为单位的unix时间轴(格式:xxxxxx) 方法一:   //摘取天上星:http://blog.csdn.net/zqtsx   function strtotime1(datetime){        var tmp_datetime = datetime.replace(/:/g,'-');        tmp_datetime

[EXCEL]实现类似Switch case的函数功能

[EXCEL]实现类似Switch case的函数功能 如果你就10种商品的话还好说,再多就不划算了. 假设你"商品1"的价格是"价格1", 那你就在B1里入 =vlookup(A1,{"商品1","价格1";"商品2","价格2";"商品3","价格3";..."商品10","价格10"},2,0) 注意:

【转】stm32CubeMx上移植自己的printf()和scanf()函数

要想printf()和scanf() 函数工作,我们需要把printf()和scanf() 重新定向到串口中.重定向是指用户可以自己重写C 的库函数,当连接器检查到用户编写了与C 库函数相同名字的函数时,优先采用用户编写的函数,这样用户就可以实现对库的修改了.为了实现重定向printf()和scanf() 函数,我们需要分别重写fputc()和fgetc() 这两个C 标准库函数. 一.移植printf()函数,重定向C库函数printf到USART1 int fputc(int ch, FIL

C语言-数据类型、常量、变量、变量作用域、printf、scanf函数

4.数据类型介绍 数据:文本数据.音频.视频.图像.数字 C语言中有5大数据类型:基本类型.构造类型.空类型.指针类型.自定义类型 基本数据类型: 整型    长整型long int    整型int(4)    端整型short int 实型    单精度float(4)    双精度 double(8) 字符型   char(1) 内存: 1> 内存分配:4G存储大小:4*1024*1024*1024Byte; 内存的基本单元为一个字节(就是8bit) 2> 内存区域:栈 (存放局部变量)

printf和scanf函数

一.printf函数 这是在stdio.h中声明的一个函数,因此使用前必须加入#include <stdio.h>,使用它可以向标准输出设备(比如屏幕)输出数据 1.用法 (1)1> printf(字符串) printf("Hello, World!"); 输出结果是: (2)printf(字符串, 格式符参数) // 使用常量作参数 printf("My age is %d\n", 26); // 也可以使用变量 int age = 17; pr

PHP 字符串操作的 printf() 内置函数用法

php中指出打印输出的函数有很多 最常见的就是  echo  print()   printf()   spintf() 这几个了. echo 和 print() 功能相同,但是 print( )具有执行成功与否的返回值 (true 和 false). 使用函数 printf()  和 sprintf() 还可以实现一些更为复杂的格式化输出. 这两个的工作方式基本相同,只是printf() 函数是讲一个格式化的字符串输出到浏览器中,而 sprintf() 函数是返回一个格式化过的字符串. pri

sprintf与printf两个函数在PHP中的使用技巧

[转自e良师益友网]下面举出一个示例:四舍五入保留小数点后两位 解释下 %0.2f 的含义: % 表示起始字符 0 表示空位用0填满 2 表示小数点后必须占两位 f 表示转换成浮点数 转换字符 % 印出百分比符号,不转换. b 整数转成二进位. c 整数转成对应的 ASCII 字元. d 整数转成十进位. f 倍精确度数字转成浮点数. o 整数转成八进位. s 整数转成字串. x 整数转成小写十六进位. X 整数转成大写十六进位. printf与sprintf的区别 1.printf函数: in