C语言的自学渐渐接近尾声,今天学到了标准库中的stdarg.h头,里面关联了stdio.h头里面的一类函数:v...printf函数,里面举的例子看了之后还是不太明白,google了一下依旧不是很懂,所以自行测试了一下,以下是过程:

这一类函数书中列举了四个,原型分别有:

int vfprintf(FILE *restrict stream, const char * restrict format, va_list arg);

int vprintf(const char * restrict format, va_list arg);

int vsnprintf(char * restrict s, size_t n, const char * restrict format, va_list arg);

int vsprintf(char * restrict s, const char * restrict format, va_list arg);

书中用vfprintf函数举例:

假设程序需要不时地显示出错消息,而且我们希望每条消息都以以下格式的前缀开始:

** Error n:

这里的n在显示第一条出错消息的时候是1,以后每显示一条错误消息增加1。为了使产生出错消息更加容易,我们将编写一个名为errorf的函数。此函数类似于printf函数,但是它总在输出的开始添加了** Error n:,并且总是向stderr而不是stdout输出。errorf函数将调用vfprintf函数来完成大部分实际输出工作。下面是errorf函数可能的写法:

int errorf(const char *format, ...)
{
static int num_errors = ;
int n;
va_list ap; num_errors++;
fprintf(stderr, "** Error %d: ", num_errors);
va_start(ap, format);
n = vfprintf(stderr, format, ap);
va_end(ap);
fprintf(stderr, "\n");
return n;
}

看完例子之后我依然不知道这个函数究竟有什么作用,于是我google了一下,发现了一个网站举了这样一个例子:

/* vfprintf example */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h> /* functions */
void inputError(char *function, char *format, ...); /* main */
int main(void) {
int sex, age; /* 输入性别 */
puts("请输入性別:(1:男性 2:女性)");
scanf("%d", &sex);
if ( sex != && sex != ) {
inputError("main", "性别是1或2!(输入值: %d)\n", sex);
return EXIT_FAILURE;
} /* 输入年龄 */
puts("请输入年龄:");
scanf("%d", &age);
if ( age < || age > ) {
inputError("main", "年龄范围[0,150]!(输入值: %d)\n", age);
return EXIT_FAILURE;
} return EXIT_SUCCESS;
} /**
* @brief 错误处理
* @param[IN] function 函数名
* @param[IN] format 格式化字符串
* @param[IN] ... 可变长参数
*/
void inputError(char *function, char *format, ...) {
va_list arg;
va_start(arg, format); fprintf(stderr, "发生错误的函数: %s\n", function); /* 显示错误信息 */
vfprintf(stderr, format, arg); va_end(arg);
}

执行结果:

请输入性別:(1:男性 2:女性)

3

发生错误的函数: main

性别是1或2!(输入值: 3)

我看完例子之后有点模模糊糊的感觉了,难道说这类函数是将调用它们的函数的可变参数列表转化为自己的可变参数列表,然后通过格式匹配将这些参数输出到流中的?

于是我自己写了个小函数测试一下:

#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h> int func(char *str, ...)
{
int n;
va_list ap; va_start(ap, str);
n = vfprintf(stdout,str,ap);
va_end(ap);
return n;
} int main(void)
{
func("%d%d\n",,);
return ;
}

执行的结果为:

21

果然验证了我的想法,看来这一类函数的用法就是利用va_list记录可变参数位置的特性,将母函数的可变参数列表通过va_list变量转化给v...printf函数的,也就是说跟...printf类的函数是一样的,只不过把...printf类函数的可变参数列表省略,替换成从va_list变量调用而已!

C语言中 v...printf类函数的用法的更多相关文章

  1. C++语言中std::array的神奇用法总结,你需要知道!

    摘要:在这篇文章里,将从各个角度介绍下std::array的用法,希望能带来一些启发. td::array是在C++11标准中增加的STL容器,它的设计目的是提供与原生数组类似的功能与性能.也正因此, ...

  2. C++中cout输出字符串和字符串型指针地址值的方法以及C语言中的printf用法比较

    #include <iostream> using namespace std; #include <stdio.h> int main() { char *pstr = &q ...

  3. c语言中external,static关键字用法

    static用法: 在C中,static主要定义全局静态变量.定义局部静态变量.定义静态函数. 1.定义全局静态变量:在全局变量前面加上关键字static,该全局变量变成了全局静态变量.全局静态变量有 ...

  4. C语言中的printf函数的输入输出问题

    这个问题是个很基础,但是我一直不知道的问题,是同学问了之后才知道的,长知识了. 这里要注意的是,printf函数是从右向左计算,从左向右输出. 距离如下: #include <stdio.h&g ...

  5. C语言中mktime函数功能及用法

    今天联系写一个日历的程序,需要算出月份中的第一天是星期几,用到了mktime()这个函数,感觉这个函数挺有用的,分享给大家. 原型:time_t mktime(struct tm *) 其中的tm结构 ...

  6. [原创]c语言中const与指针的用法

    最近一直在准备笔试,补补大一大二欠下的课.复习c语言时碰见这么个题:   1 2 3 4 5 int a=248, b=4; int const c=21; const int *d=&a;  ...

  7. C语言中printf与i++,C++中的cout

    一,printf与i++ 1,C语言中的printf是自右向左输出,. 2,而i++与++i不同的 i++首先取得i的值,下一行时候i = i + 1: ++i,首先i = i + 1,再取得i的值. ...

  8. C语言中malloc()和calloc()c函数用法

    C语言中malloc()和calloc()c函数用法   函数malloc()和calloc()都可以用来动态分配内存空间,但两者稍有区别. malloc()函数有一个参数,即要分配的内存空间的大小: ...

  9. 在不同语言中static的用法

    static (计算机高级语言) 编辑 像在VB,C#,C,C++,Java,PHP中我们可以看到static作为关键字和函数出现,在其他的高级计算机语言如FORTRAN.ALGOL.COBOL.BA ...

随机推荐

  1. Java 按字节获得字符串(中文)长度

    引自:http://songjianyong.iteye.com/blog/1552973 package cn.com.songjy.test; import java.io.Unsupported ...

  2. WinCE启动次数的记录

    最近一周一直在忙于测试NAND文件系统的稳定性和可靠性,今天终于有所进展.测试组所有同事齐上阵,加上小高和我,测试了一天,都未发现问题.虽然还不能保证完全OK,但至少有所改善了. 测试组今天主要做了文 ...

  3. AutoResetEvent

    private static readonly AutoResetEvent autoResetEvent = new AutoResetEvent(false); private static vo ...

  4. Android开发之异步通信Handler机制

    郭大神的:http://blog.csdn.net/guolin_blog/article/details/9991569 http://www.jianshu.com/p/08cb3665972f ...

  5. Codeforces Round #248 (Div. 2) C. Ryouko's Memory Note (vector 替换)

    题目链接 题意:给m个数字, 这些数字都不大于 n,  sum的值为相邻两个数字 差的绝对值.求这n个数字里把一个数字 用 其中另一个数字代替以后, 最小的sum值. 分析:刚开始以为两个for 最坏 ...

  6. noi2002银河英雄传说(并查集)

    首先表示对C++读入读出问题复杂程度的敬畏,看了好多没讲明白的,本题用cin竟然过不了评测,搞scanf的读入搞了好久.... 本题确实是一道经典的并查集题型,不多讲,拿来练练手用的(其中经历很惨) ...

  7. ASIFormDataRequest实现post的代码示例

    用jquery实现的Post方法可能如下 var param = $.param({ data: JSON.stringify({"from":"234",&q ...

  8. BMP图像格式

    BMP(全称Bitmap)是Window操作系统中的标准图像文件格式,可以分成两类:设备相关位图(DDB)和设备无关位图(DIB),使用非常广.它采用位映射存储格式,除了图像深度可选以外,不采用其他任 ...

  9. BOM浏览器对象模型和API速查

    什么是BOMBOM是Browser Object Model的缩写,简称浏览器对象模型BOM提供了独立于内容而与浏览器窗口进行交互的对象由于BOM主要用于管理窗口与窗口之间的通讯,因此其核心对象是wi ...

  10. poj 2773 Happy 2006

    // 题意 :给你两个数 m(10^6),k(10^8) 求第k个和m互质的数是什么这题主要需要知道这样的结论gcd(x,n)=1 <==> gcd(x+n,n)=1证明 假设 gcd(x ...