1、函数原型:
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
某度百科:
_vsnprintf是C语言库函数之一,属于可变参数。用于向字符串中打印数据、数据格式用户自定义。
头文件是#include <stdarg.h>。
函数功能:将可变参数格式化输出到一个字符数组。
2、参数说明
-
char *str [out],把生成的格式化的字符串存放在这里.指向存储结果C字符串的缓冲区的指针。
缓冲区应至少有n个字符的大小。 -
size_t size [in], str可接受的最大字符数 (非字节数,UNICODE一个字符两个字节),防止产生数组越界.生成的字符串的长度至多为n-1,为额外的终止空字符留下空间。size_t是一个无符号整数类型。
-
const char *format [in], 指定输出格式的字符串,它决定了你需要提供的可变参数的类型、个数和顺序。包含格式字符串的C字符串,其格式字符串与printf中的格式相同
-
va_list ap [in], va_list变量. va:variable-argument:可变参数,标识使用va_start初始化的变量参数列表的值。
va_list是在<cstdarg>中定义的特殊类型。 -
返回值:
如果n足够大,则会写入的字符数,不包括终止空字符。
如果发生编码错误,则返回负数。
注意,只有当这个返回值是非负值且小于n时,字符串才被完全写入。
3、vsnprintf和_vsnprintf(一个多了横杠)一样吗
vsnprintf和_vsnprintf用法应该差不多,是不是一样的,我也还没有结论,
但某度百科,有备注:
linux环境下是:vsnprintf
VC6环境下是:_vsnprintf
是不是一样这里我也不给出结论,下面只讲linux下的vsnprintf
4、查看资料
在linux下可以自己使用命令行查看使用方法
在linux下使用man vsnprintf回车可以看到右上角有个PRINTF(3),3可以知道这是个库函数(不是系统调用或者其他的,详细见附文,man的参数说明),并且可以知道vsnprintf的使用方法,摘抄如下:
SYNOPSIS
#include <stdio.h>
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);
#include <stdarg.h>
int vprintf(const char *format, va_list ap);
int vfprintf(FILE *stream, 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 <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
char * make_message(const char *fmt, ...)
{
int n;
int size = 100; /* Guess we need no more than 100 bytes */
char *p, *np;
va_list ap;
if ((p = malloc(size)) == NULL)
return NULL;
while (1) {
/* Try to print in the allocated space */
va_start(ap, fmt);
n = vsnprintf(p, size, fmt, ap);
va_end(ap);
/* Check error code */
if (n < 0)
return NULL;
/* If that worked, return the string */
if (n < size)
return p;
/* Else try again with more space */
size = n + 1; /* Precisely what is needed */
if ((np = realloc (p, size)) == NULL) {
free(p);
return NULL;
} else {
p = np;
}
}
}
4、网上查看其他资料
到网上其他博客查资料,可以知道vsnprintf一般用于可变参数的解析中,将可变参数格式化输出到一个字符数组。
通常和va_list 、va_start 、va_end 这几个联合使用。
man va_start可查到
#include <stdarg.h>
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);
va_list是一个宏,由va_start和va_end界定。
typedef char* va_list;
void va_start ( va_list ap, prev_param );
type va_arg ( va_list ap, type );
void va_end ( va_list ap );
其中,va_list 是一个字符指针,可以理解为指向当前参数的一个指针,取参必须通过这个指针进行。
<Step 1> 在调用参数表之前,应该定义一个 va_list 类型的变量,以供后用(假设这个 va_list 类型变量被定义为ap);
<Step 2> 然后对 ap 进行初始化,让它指向可变参数表里面的第一个参数。这是通过 va_start 来实现的,其第一个参数是 ap 本身,第二个参数last是变量前面最后一个参数的名称参数列表,即调用函数已知其类型的最后一个参数。因为此参数的地址可能会在va_start()中使用宏,则不应将其声明为寄存器变量或函数操作或数组类型。va_start()宏将初始化ap以供va_arg()和va_end()后续使用,并且必须首先调用。
<Step 3> 然后是获取参数,调用 va_arg。调用va_arg的例子见下面它的第一个参数是 ap,第二个参数是要获取的参数的指定类型,并返回这个指定类型的值,同时把 ap 的位置指向变参表的下一个变量位置;或者调用vsnprintf见上面。
<Step 4> 获取所有的参数之后,我们有必要将这个 ap 指针关掉,以免发生危险,方法是调用 va_end。它是将输入的参数 ap 置为 NULL,应该养成获取完参数表之后关闭指针的习惯。
int max(int n, ...) // 定参 n 表示后面变参数量,定界用,输入时切勿搞错
{
va_list ap; // 定义一个 va_list 指针来访问参数表
va_start(ap, n); // 初始化 ap,让它指向第一个变参
int maximum = -0x7FFFFFFF; // 这是一个最小的整数
int temp;
for(int i = 0; i < n; i++)
{
temp = va_arg(ap, int); // 获取一个 int 型参数,并且 ap 指向下一个参数
if (maximum < temp)
maximum = temp;
}
va_end(ap); // 善后工作,关闭 ap
return maximum;
}
// 在主函数中测试 max 函数的行为(C++ 格式,vc6.0)
int main()
{
cout << max(3, 10, 20, 30) << endl;
cout << max(6, 20, 40, 10, 50, 30, 40) << endl;
}
附:
linux可以通过man来查询一些函数的使用方法(巧记:小学老师教学生遇到问题找警察,linux下遇到问题还是需要找男人(man),哈哈哈)
man查看对应的一些数字代表的意义。
1、Standard commands (标准命令)
2、System calls (系统调用)
3、Library functions (库函数)
4、Special devices (设备说明)
5、File formats (文件格式)
6、Games and toys (游戏和娱乐)
7、Miscellaneous (杂项)
8、Administrative Commands (管理员命令)
9 其他(Linux特定的), 用来存放内核例行程序的文档
本文参考自以下互联网文章,如果有侵权请及时联系删除。
https://blog.csdn.net/swif_N_F/article/details/78712315
https://baike.baidu.com/item/_vsnprintf/5395011?fr=aladdin