前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >理解snprintf()函数

理解snprintf()函数

作者头像
一见
发布2018-08-10 17:35:01
1.9K0
发布2018-08-10 17:35:01
举报
文章被收录于专栏:蓝天

理解snprintf()函数.pdf

在编程中,需要关注snprintf()的两个问题:一是它的返回值,二是它的第二个参数。

看看下面这段代码的运行结果:

代码语言:javascript
复制
#include
#include
int main()
{
int ret;
char str[10];
printf("sizeof(str) = %d\n", sizeof(str));
ret = snprintf(str, sizeof(str), "%s", "abc");
printf("%d:%s => %d\n",strlen(str), str, ret);
ret = snprintf(str, sizeof(str), "%s", "1234567890");
printf("%d:%s => %d\n",strlen(str), str, ret);
ret = snprintf(str, sizeof(str), "%s", "1234567890X");
printf("%d:%s => %d\n",strlen(str), str, ret);
return 0;
}

以上代码运行结果为:

代码语言:javascript
复制
3:abc => 3         // 没有被截断,输出:abc
9:123456789 => 10  // 被截断了,没有输出:1234567890
9:123456789 => 11  // 同样被截断了,没有输出:1234567890X

要点:

1) snprintf()第2个参数的大小,要求包含结尾符'\0';

2) snprintf()的返回值,返回的是期望大小,但不包含结尾符'\0'。有点拗口,这是什么意思了?以示例来理解:

a) 当str为"abc"时,它期望的大小是3,"abc"的字符个数刚好是3;

b) 当str为"1234567890"时,它期望的大小是10,"1234567890"的字符个数刚好是10;

c) 当str为"1234567890X"时,它期望的大小是11,"1234567890X"的字符个数刚好是11。

以上示例,也可以看出:当snprintf()的返回值大小等于或大于它的第二个参数值大小时,即发生了截断。

有时候并不关是否有截断,但是需要知道实际的大小,可以复用如下的实现:

代码语言:javascript
复制
// 函数fix_vsnprintf()的返回值大小包含了结尾符'\0',其大小总是等于strlen(str)+1
int fix_vsnprintf(char *str, size_t size, const char *format, va_list ap)
{
int expected = vsnprintf(str, size, format, ap);
if (expected < static_cast(size))
return expected + 1; // 将结尾符也算进去
return static_cast(size);
}
int fix_snprintf(char *str, size_t size, const char *format, ...)
{
va_list ap;
va_start(ap, format);
int expected = fix_vsnprintf(str, size, format, ap);
va_end(ap);
return expected;
}

下面这个函数,在有些时候,也蛮方便的:

代码语言:javascript
复制
// 最多支持10240个ANSI字符,超过的会被截断,但调用者可能不清楚是否发生了截断@_@
std::string format_string(const char* format, ...)
{
va_list ap;
va_start(ap, format);
// size不包含结尾符,所以在分配内存时需要加一
size_t size = 1024;
char* buffer = new char[size + 1];
// vsnprintf中的第二参数大小是要求包含结尾符的
int expected = vsnprintf(buffer, size + 1, format, ap);
if (expected >= ((int)size)+1)
{
// 防止太长,撑死内存
if (expected > 10240)
expected = 10240;
// expected的大小不包含结尾符,所以在分配内存时需要加一
delete []buffer;
buffer = new char[expected + 1];
va_end(ap);
va_start(ap, format);
vsnprintf(buffer, static_cast(expected + 1), format, ap);
}
va_end(ap);
DeleteHelper dh(buffer, true); // 释放buffer所占内存
return buffer;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2014/12/24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档