C语言中 v...printf类函数的用法
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类函数的用法的更多相关文章
- C++语言中std::array的神奇用法总结,你需要知道!
摘要:在这篇文章里,将从各个角度介绍下std::array的用法,希望能带来一些启发. td::array是在C++11标准中增加的STL容器,它的设计目的是提供与原生数组类似的功能与性能.也正因此, ...
- C++中cout输出字符串和字符串型指针地址值的方法以及C语言中的printf用法比较
#include <iostream> using namespace std; #include <stdio.h> int main() { char *pstr = &q ...
- c语言中external,static关键字用法
static用法: 在C中,static主要定义全局静态变量.定义局部静态变量.定义静态函数. 1.定义全局静态变量:在全局变量前面加上关键字static,该全局变量变成了全局静态变量.全局静态变量有 ...
- C语言中的printf函数的输入输出问题
这个问题是个很基础,但是我一直不知道的问题,是同学问了之后才知道的,长知识了. 这里要注意的是,printf函数是从右向左计算,从左向右输出. 距离如下: #include <stdio.h&g ...
- C语言中mktime函数功能及用法
今天联系写一个日历的程序,需要算出月份中的第一天是星期几,用到了mktime()这个函数,感觉这个函数挺有用的,分享给大家. 原型:time_t mktime(struct tm *) 其中的tm结构 ...
- [原创]c语言中const与指针的用法
最近一直在准备笔试,补补大一大二欠下的课.复习c语言时碰见这么个题: 1 2 3 4 5 int a=248, b=4; int const c=21; const int *d=&a; ...
- C语言中printf与i++,C++中的cout
一,printf与i++ 1,C语言中的printf是自右向左输出,. 2,而i++与++i不同的 i++首先取得i的值,下一行时候i = i + 1: ++i,首先i = i + 1,再取得i的值. ...
- C语言中malloc()和calloc()c函数用法
C语言中malloc()和calloc()c函数用法 函数malloc()和calloc()都可以用来动态分配内存空间,但两者稍有区别. malloc()函数有一个参数,即要分配的内存空间的大小: ...
- 在不同语言中static的用法
static (计算机高级语言) 编辑 像在VB,C#,C,C++,Java,PHP中我们可以看到static作为关键字和函数出现,在其他的高级计算机语言如FORTRAN.ALGOL.COBOL.BA ...
随机推荐
- 为什么重写equals方法还要重写hashcode方法?
我们都知道Java语言是完全面向对象的,在java中,所有的对象都是继承于Object类.Ojbect类中有两个方法equals.hashCode,这两个方法都是用来比较两个对象是否相等的. 在未重写 ...
- Orcle数据库编程:一
1.PL/SQL是一种块结构的语言,一个PL/SQL程序包含了一个或者多个逻辑块,逻辑块中可以声明变量,变量在使用之前必须先声明. declare mstu student%ROWTYPE;--定义参 ...
- Nmap扫描原理与用法
Nmap扫描原理与用法 1 Nmap介绍 Nmap扫描原理与用法PDF:下载地址 Nmap是一款开源免费的网络发现(Network Discovery)和安全审计(Security Audit ...
- 奇怪的transform bug
对一个元素使用transform:rotate 进行旋转,造成: 父元素的背景图位置偏移,往下降,背景图也会变模糊一些 造成重绘,导致该元素后面的兄弟元素受到影响,变得模糊,并且无法遮盖住父元素的背景 ...
- js 返回的数据类型 5类
对变量或值调用 typeof 运算符将返回下列值之一: undefined - 如果变量是 Undefined 类型的 boolean - 如果变量是 Boolean 类型的 number - 如果变 ...
- Android UI学习 - FrameLayou和布局优化(viewstub)
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://android.blog.51cto.com/268543/308090 Fram ...
- 配置hibernate根据实体类自动建表功能
Hibernate支持自动建表,在开发阶段很方便,可以保证hbm与数据库表结构的自动同步. 如何使用呢?很简单,只要在hibernate.cfg.xml里加上如下代码 Xml代码<propert ...
- bzoj1499: [NOI2005]瑰丽华尔兹
dp. 首先我们可以看到每个时间段只能往一个方向转移最多t步(t为时间段的长度),所以我们可以按时间段dp.因为这个前后值互不影响,也不用占用这一维空间就可以省去. 然后每个时间段内是一列一列(行) ...
- UVa 11526 H(n)
题意: long long H(int n){ long long res = 0; for( int i = 1; i <= n; i=i+1 ){ res = (res + n/i); } ...
- HDU 1686 (KMP模式串出现的次数) Oulipo
题意: 求模式串W在母串T中出现的次数,各个匹配串中允许有重叠的部分. 分析: 一开始想不清楚当一次匹配完成时该怎么办,我还SB地让i回溯到某个位置上去. 后来仔细想想,完全不用,直接让模式串向前滑动 ...