snprintf()可以认为是sprintf()的升级版,但比sprintf()多了一个参数,能够控制要写入的字符串的长度,更加安全,只要稍加留意,不会造成缓冲区的溢出,所以一般我们使用snprintf更多。
一. snprintf函数功能及参数介绍
#include <stdio.h>
int snprintf(char *str,
size_t size
, char * format [, argument, …]);功能:将可变参数 “…” 按照format的格式格式化为字符串,然后再将其拷贝至str中。
参数:
- str: 最终格式化字符串所存储的buff
- size: buff缓存区的长度,这里包括字符串结尾符‘\0’(注意:‘\0’是自动添加的,不管后面的自字符串是否包含’\0’),即可以输出到str的有效字符的大小为:size - 1
- format: 可变参数,类似于printf中的”%d”格式
返回值:当调用失败时返回值为负数,当调用成功时返回值为格式化后的字符串的总长度(不包括\0),这个字符串有可能被截断(因为有可能buf长度不够放下整个字符串)。
看了这个可能也不清楚到底怎么用,没关系,看下边的例子就明白了:
#include <stdio.h>
int main()
{
int a = 1;
char buf[32] = "Nike";
char buf1[32] = {0};
snprintf(buf1, sizeof(buf1)-1, "hello, I am %s. [%d]", buf, a);
printf("%s\n", buf1);
return 0;
}
运行结果:
二. 一些注意点
1. 如果格式化后的字符串长度 < size,则将此字符串全部复制到str中,并给其后添加一个字符串结束符('\0');
2. 如果格式化后的字符串长度 >= size,则只将其中的(size-1)个字符复制到str中,并给其后添加一个字符串结束符('\0'),返回值为欲写入的字符串长度。(因为snprintf在末尾会自动加个'\0',得留一个位置给它)。
#include <stdio.h>
int main()
{
int a = 1;
char buf[10] = "Nike";
char buf1[10] = {0};
snprintf(buf1, 5, "%s.", buf);
printf("%s\n", buf1);
return 0;
}
结果:
若将 snprintf(buf1, 5, "%s.", buf); 改成 snprintf(buf1, 6, "%s.", buf);
结果:
3. snprintf会在结尾加上\0,不管buf空间够不够用,所以不必担心缓冲区溢出。
4. 如果是连续往一个缓存中输出字符串,每次函数返回之后,需要用snprintf的返回值、之前输出的字符长度之和与缓存的长度进行比较,以免出现缓存overflow。因此在进行字符串格式化输出到缓存的操作时,尽量使用snprintf,少使用sprintf,否则可能会出现很多奇怪的bug。
if ( n < 0) : snprintf出错。
if ( n >0 && n < sizeof(buf) ) : snprintf成功,并且格式化了完整的字符串。
if ( n >= sizeof(buf) ) : snprintf成功,但要格式化的字符串被截断了。