printf,sprintf,snprintf VS vprintf,vsprintf,vsnprintf 对比 以及文件写入函数fprintf 和 vfprintf函数的用法

1.printf,sprintf,snprintf区别

他们都是 可变参数 输出函数

前3个printf,sprintf,snprintf是c语言的输出函数,对比使用c++ 的cout有时候更加灵活,也方便调试代码,用法如下

#include <iostream>
#include<cstdio>
using namespace std;
int main()
{
    char buffer[100] = "";  //存放格式化输入的内容
    char str[] = "hello";   //格式化输出参数1
    int a = 100;            //格式化输出参数2

    //下面的size都等于格式化输出的大小,输出如注释所示//size不包括\0
    int size = printf("200 %s %d\n", str, a); //直接输出 200 hello 100

    size = sprintf(buffer, "200-%s-%d", str, a);
    cout << "buffer = " << buffer << "  size = " << size << endl;//buffer = 200-hello-100  size = 13

    size = snprintf(buffer, sizeof(buffer), "200-%s-%d", str, a);
    cout << "buffer = " << buffer << "  size = " << size << endl;//buffer = 200-hello-100  size = 13
    return 0;
}
函数原型如下:
int printf(const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);

其中,sprintf和snprintf的区别在于

如上面的例子,sprintf的buffer最多只能容纳99个输入+'\0',共100size,超过就会报错,所以是不安全的函数

snprintf可以指定大小,格式化输入时超过buffer大小的内容将会被截断,如上,有超过不会报错,有超过100size的输入,那么buffer会接收99个输入+一个'\0'共100个,其余被截截取,这样的缺点就是你得不到直接的反馈,且此时返回的size是截断之前的size,故不能用返回值来判断是否被截断过。

如下所示:

//
#include <iostream>
#include<cstdio>
using namespace std;
int main()
{
    char buffer[5] = "";  //存放格式化输入的内容
    char str[] = "hello";   //格式化输出参数1
    int a = 100;            //格式化输出参数2
    int size = snprintf(buffer, sizeof(buffer), "200-%s-%d", str, a);//真实的size = 13,不包括\0
    cout << buffer << "\nsize = " << size << endl;//buffer = 200-hello-100  size = 13
    return 0;
}

输出 

可以看到,输出200-,4个字符,buffer.size=5,但返回的size却是13

说明

1.自动添加\0占用Buffer的一个位置,2.返回值不可判断是否被截断

3.虽然这是安全的函数,不会报错,但是也要小心输出内容被截断的隐蔽性

2. vprintf,vsprintf,vsnprintf 的区别

都是 不可变参数 输出函数一般用在自己写的输出函数,包含头文件stdarg.h如下示例

一般写法如下:

1.函数原型
int vprintf(const char *format, va_list ap);
int vsprintf(char *str, const char *format, va_list ap);
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
//示例
#include <iostream>
#include <stdarg.h>
using namespace std;
void myPrint(const char* format, ...)//不知道有几个参数,用...表示
{
    va_list ap;//把未知参数按照链表存储
    va_start(ap, format);//调用va_start找到第一个参数的位置
    //1.直接输出
    int size= vprintf(format, ap);//返回的是格式化输出的size
    cout<<"  ret = "<< size<< endl;//用完后ap指向的位置不再是第一个参数的位置,下面再次调用调用时需要再一次va_start(ap,format);
    //2.存到buffer里面
    char buffer[1024] = "";
    va_start(ap, format);//重新定位第一个参数的位置,否则就会报错找不到参数
    cout <<"size = " << vsprintf(buffer, format, ap) <<"  buffer = " <<buffer << endl;//不安全,超出buffer大小就会报错
    //3.加n和不加n的区别类似sprintf和snprintf
    va_start(ap, format);
    cout <<"size = "<< vsnprintf(buffer, sizeof(buffer), format, ap)<<"  buffer = "<<buffer << endl;//安全,一旦超出后面的内容就会丢掉,不会报错,没有提示,可以看size大小
    va_end(ap);
}

int main()
{
    char str[] = "love";
    int a = 520;
    myPrint("hello world ! %s -- %d", str, a);//这里可以输入多个参数
}

 输出如下:

3.fprintf和vfprintf的用法

这两个都是操作文件的函数,往文件写入内容,如写入log日志文件中,如下所示

#include <stdio.h>
#include <cstdarg>
void log(FILE* pFile,const char* format, ...) //...表示不确定的输入参数
{
	va_list ap;
	va_start(ap, format);
	vfprintf(pFile, format, ap);
	va_end(ap);
}
int main()
{
	FILE* pFile = fopen("test.txt", "w+");
	char str[] = "love";
	int a = 520;
    //方法1,直接写入
	fprintf(pFile, "hello %s %d ", str, a); //往当前目录创建并写入 hello love 520到 test.txt中  

    //方法2,使用vsprintf写入
	log(pFile, "hello %s %d haha", str, a);//hello love 520 haha 追加写入

	//最后文件内容为 hello love 520 hello love 520 haha
	fclose(pFile);
	return 0;
}

  • 15
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值