转自:http://blog.csdn.net/raito__/article/details/48860119

printf() 在控制台应用程序中最为常用,使用也很简单。其参数为格式化字符串。

函数原型:printf(const char *format,[argument]);

例如:

[cpp] view plaincopy
  1. int a=1,b=2;
  2. printf("a=%d,b=%d",a,b);

输出:

[cpp] view plaincopy
  1. a=1,b=2

sprintf() 用于将输出存到字符缓冲中。

函数原型:sprintf(char *buffer, const char *format, [argument]);

例如:

[cpp] view plaincopy
  1. int a=1,b=2;
  2. char s[10];
  3. sprintf(s,"a=%d,b=%d",1,2);
  4. puts(s);

输出:

[cpp] view plaincopy
  1. a=1,b=2

vsprintf() 与sprintf() 功能类似。

需要引入相关头文件 #include <stdarg.h>

函数原型: vsprintf(char *buffer, char *format, va_list param);

例如:

[cpp] view plaincopy
  1. void Myprintf(const char* fmt,...);
  2. int a=1,b=2;
  3. char s[10];
  4. Myprintf("a=%d,b=%d",a,b);
  5. void Myprintf(const char* fmt,...)
  6. {
  7. char s[10];
  8. va_start(ap, fmt);
  9. vsprintf(s,fmt,ap);
  10. va_end(ap);
  11. puts(s);
  12. }

输出:

[cpp] view plaincopy
  1. a=1,b=2

因此可以用 vsprintf() 来实现 sprintf()。

其中 va_start、va_end、va_list 是什么东东一会儿再解释,先往下看。

既然sprintf() 与 vsprintf() 功能类似,为什么不统一下,而且 vsprintf() 用法如此麻烦呢?

假设你想封装一个子函数 Myprintf() ,其功能是将格式化字符串输出两遍,若用 sprintf() 实现:

(错误的)代码:

[cpp] view plaincopy
  1. void Myprintf(const char* fmt,...)
  2. {
  3. char s[10];
  4. sprintf(s,fmt);
  5. puts(s);
  6. puts(s);
  7. }

当你尝试这么调用该函数时:

[cpp] view plaincopy
  1. int a=1,b=2;
  2. Myprintf("a=%d,b=%d",a,b);

输出:

[cpp] view plaincopy
  1. a=?,b=?
  2. a=?,b=?

我也不知道它会输出几,但一定不会是 a=1,b=2 。

这显然是错误的!

为什么呢?

当你这么调用 Myprintf() 时,其中的sprintf() 实际上是这样的:

sprintf(s,"a=%d,b=%d")

而不是:

sprintf(s,"a=%d,b=%d",a,b) !!

因为这么调用的话只能解析到第一个字符串而无法解析到后面的参数。

所以类似这种封装用 sprintf() 是无法实现的,使用 sprintf() 只能原始的为它输入所有的参数而不能以传参的方式给它。

若用 vsprintf()那么这个问题就可以迎刃而解。

函数如下:

[cpp] view plaincopy
  1. void Myprintf(const char* fmt,...)
  2. {
  3. char s[10];
  4. va_list ap;
  5. va_start(ap,fmt);
  6. vsprintf(s,fmt,ap);
  7. va_end(ap);
  8. puts(s);
  9. puts(s);
  10. }

当你这么调用时:

[cpp] view plaincopy
  1. Myprintf("a=%d,b=%d",a,b);

输出:

[cpp] view plaincopy
  1. a=1,b=2
  2. a=1,b=2

成功了!哇哈哈哈哈!!想想也是有点小激动!!!

现在来解释一下这个 vsprintf():

首先你要知道函数执行时,函数的参数是倒序压入栈中的,vsprintf() 为了能够解析你传给它的多个参数,你必须告诉它参数从哪里开始。

vadefs.h 头文件中这么定义 :typedef char * va_list,于是我们定义了一个 va_list ap 来保存参数起始地址。

va_start(ap,fmt) 就找出这个函数在栈中排列的一堆参数的起始地址,然后直接浏览栈中参数,并用 vsprintf() 实现格式化字符串的读取,最后 vs_end(ap) 释放ap,就像释放指针一样。通俗地说就是因为 vsprintf() 比 sprintf() 更加接近底层(栈),因此能实现这个目的,也是因此能用 vsprintf() 来实现 sprintf()。

打的手好酸~0.0 希望大家发现错误帮我指正,不幸感激!最后给懒得敲代码的童鞋附上这段演示代码:

[cpp] view plaincopy
  1. #include <stdarg.h>
  2. void Myprint(const char* fmt,...);
  3. int main()
  4. {
  5. int a=1,b=2;
  6. Myprintf("a=%d,b=%d",a,b);
  7. return 0;
  8. }
  9. void Myprintf(const char* fmt,...)
  10. {
  11. char s[10];
  12. va_list ap;
  13. va_start(ap,fmt);
  14. vsprintf(s,fmt,ap);
  15. va_end(ap);
  16. puts(s);
  17. puts(s);
  18. }

C语言printf()、sprintf()、vsprintf() 的区别与联系相关推荐

  1. printf,sprintf,vsprintf 区别【转】

    转自:http://blog.csdn.net/anye3000/article/details/6593551 有C语言写作历史的程序员往往特别喜欢printf 函数.即使可以使用更简单的命令(例如 ...

  2. [转]PHP echo, print, printf, sprintf函数的区别和使用

    1. echo函数: 输出函数,是命令,不能返回值.echo后面可以跟很多个参数,之间用分号隔开,如: echo $myvar1; echo 1,2,$myvar,"<b>bol ...

  3. C语言中的格式化打印printf/sprintf以及嵌入式printf重定向进行DEBUG

    一.printf描述 在C语言中,打印函数主要包括printf/sprintf/fprintf/snprintf等等,目的是将"给定的内容"按照"指定的格式"输 ...

  4. 武林c语言,c语言printf函数的使用

    看C语言程序的时候,往往会遇到printf函数输出,在此,武林小编我就总结一下c语言printf函数的使用,本文对c语言中printf函数的使用进行了详细的分析介绍,需要的朋友参考下. printf的 ...

  5. C语言printf函数详解

    本文已整合到C语言标准库深度解读 printf是绝大多数人接触的第一个C语言函数,但绝大多数人对printf的认识也就到了hello world为止了,很多人甚至看不懂这个函数的声明: int pri ...

  6. Java中print、printf、println的区别 详解

    Java中print.printf.println的区别详解 printf主要是继承了C语言的printf的一些特性,可以进行格式化输出 print就是一般的标准输出,但是不换行 println和pr ...

  7. printf, sprintf - 转换成指定格式的输出结果.

    名称: printf, sprintf - 转换成指定格式的输出结果. 语法: void printf( string format, ... ); string sprintf( string fo ...

  8. C语言 printf 函数 - C语言零基础入门教程

    目录 一.printf 函数简介 二.C 语言格式符/占位符 三.printf 函数实战 四.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> C 语言基础入门 ...

  9. C语言 memcpy 和 strcpy 函数区别 - C语言零基础入门教程

    目录 一.memcpy 函数/strcpy 函数简介 二.memcpy 函数/strcpy 函数实战 1.strcpy 函数属于字符串拷贝 2.memcpy 函数属于内存拷贝 三.猜你喜欢 零基础 C ...

  10. C语言 sizeof 和 strlen 函数区别 - C语言零基础入门教程

    目录 一.sizeof 函数与 strlen 函数区别 1.获取字符串长度 – 针对字符串 2.获取指针/数组长度 – 针对指针/数组 3.sizeof 获取内存大小 4.经典案例 二.猜你喜欢 零基 ...

最新文章

  1. [Java入门笔记] Java语言基础(四):流程控制
  2. window.print 固定表头不影响_Excel中的表头,你会处理吗
  3. B05_NumPy从数值范围创建数组(numpy.arange,numpy.linspace,numpy.logspace)
  4. weed mount 之后出现文件删除不掉
  5. Collection源码阅读
  6. Beyond Compare 4
  7. 反转链表python
  8. 任正非:鸿蒙最快1年可媲美iOS;首例Apple Card用户遭盗刷;Firefox 69.0.3 发布 | 极客头条...
  9. java使用bks双向认证_android客户端SSL单向双向认证
  10. RTX(2009)整合注意点
  11. word或excel打开很慢的处理办法
  12. 自制 APP Inventor 蓝牙接收数据接收模板 自制遥控小车App的必经之路~
  13. LINUX从零开始——ENGINEER(云计算应用管理)——Day3 [逻辑卷管理、RAID磁盘阵列、进程管理]
  14. phpcms extention.func.php数据的使用
  15. 五阶魔方公式java_五阶魔方花样有多漂亮,关键是有点难
  16. 以太坊编程涉及那些开发语言?
  17. html 图片右侧空白,CSS缩小窗口时,背景图出现右侧空白
  18. 利用DirectShow开发C#版的音频文件播放器(补充完善)
  19. linux重新mac,用 Linux 让旧 MacBook 重获新生
  20. python里面的爬虫爬取网页

热门文章

  1. jquery实现输入框动态增减的实例代码
  2. Web API 设计摘要
  3. OpenCV学习(22) opencv中使用kmeans算法
  4. PowerDesigner(九)-模型文档编辑器(生成项目文档)
  5. 【设计模式系列】行为型之责任链模式
  6. Linux串口打印信息工具,基于Qt实现Linux或Windows串口打印工具
  7. 应用程序进程启动过程
  8. flannel vxlan 实现原理【转】
  9. 对于超平面的理解[转载]
  10. 为啥浏览器中的对象和w3c不一样??