snprintf函数
snprintf()函数用于将格式化的数据写入字符串,其原型为:
int snprintf(char *str, int size, char * format [, argument, ...]);
- str为要写入的目标字符串;
- size为能写入的字符的最大数目,超过n会被截断,包括’\0’符,所以能最大写入的其实是size-1个字符;
- format为格式化字符串,使用方式与printf()函数相同;
- argument为变量,可为多个,取决于format,这里的使用方式与printf相同。
返回值:
- 如果格式化后的字符串长度小于等于 size,则会把字符串全部复制到 str 中,并给其后添加一个字符串结束符 \0;
- 如果格式化后的字符串长度大于 size,超过 size 的部分会被截断,只将其中的 (size-1) 个字符复制到 str 中,并给其后添加一个字符串结束符 \0,返回值为欲写入的字符串长度。
对于snprintf有一个不安全的地方就是它的返回值:当要写入的argument的长度大于str的长度时,返回值不是str的长度,而是argument的长度。
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[5] = {0};
int ret_len = 0;
char* arg = "hello world";
ret_len = snprintf(str, sizeof(str), "%s", arg);
printf("str = %s\nret_len = %d\n", str, ret_len);
return 0;
}
输出结果:
返回的长度是11而不是4,不注意的话,下边的使用可能有问题。所以我们需要对返回值进行封装。
int my_snprintf(char* buf, int max, char* fmt, ...)
{
int len;
va_list argp;
if (buf == NULL){
return -1;
}
//用来判断buf长度是否已经用完
if (max <= 1){
printf("buf_len not enough\n");
return -1;
}
va_start(argp, fmt);
len = vsnprintf(buf, max, fmt, argp);
//用来限定返回值是我们实际写入的字节数
len = len > max - 1 ? max - 1 : len;
va_end(argp);
return len;
}
这上面用到了可变参数,首先我们需要先了解可变参数的原理。推荐一篇文章讲的挺清楚的,不懂这个可变参数原理的大家可以去下面那个链接去看。
可变参数原理
原看到这篇文章的小伙伴都能搞懂!!!