Chinaunix首页 | 论坛 | 博客
  • 博客访问: 8053163
  • 博文数量: 594
  • 博客积分: 13065
  • 博客等级: 上将
  • 技术积分: 10324
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-26 16:44
个人简介

推荐: blog.csdn.net/aquester https://github.com/eyjian https://www.cnblogs.com/aquester http://blog.chinaunix.net/uid/20682147.html

文章分类

全部博文(594)

分类: C/C++

2014-12-24 10:27:24

理解snprintf()函数.pdf

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

 

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

#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;

}

 

以上代码运行结果为:

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()返回值大小等于或大于它的第二个参数值大小时,即发生了截断。

 

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

// 函数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;

}

 

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

// 最多支持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;

}

 

 

阅读(15416) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~