理解snprintf()函数

简介: 理解snprintf()函数.pdf 在编程中,需要关注snprintf()的两个问题:一是它的返回值,二是它的第二个参数。   看看下面这段代码的运行结果: #include  #...
img_e25d4fb2f8de1caf41a735ec53088516.png理解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 (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;

}

 

 

相关文章
|
设计模式 Java 编译器
面向对象编程中的继承与多态:深入理解父类引用指向子类实例
面向对象编程中的继承与多态:深入理解父类引用指向子类实例
|
6月前
|
存储 传感器 编解码
2025年云真机与购买真机成本对比及平台选型指南
文章围绕2025年云真机与购买真机展开,对比两者成本,指出云真机在初期投入、维护和机型覆盖上优于传统购买,适合中小团队;购买真机在数据安全等方面有优势但TCO高。还介绍云真机平台选型要点,分析主流平台优劣势,以及购买真机适用场景,解答常见选型问题。
|
12月前
|
数据采集 存储 API
Python爬虫结合API接口批量获取PDF文件
Python爬虫结合API接口批量获取PDF文件
|
存储 编译器 C++
【c++】多态(多态的概念及实现、虚函数重写、纯虚函数和抽象类、虚函数表、多态的实现过程)
本文介绍了面向对象编程中的多态特性,涵盖其概念、实现条件及原理。多态指“一个接口,多种实现”,通过基类指针或引用来调用不同派生类的重写虚函数,实现运行时多态。文中详细解释了虚函数、虚函数表(vtable)、纯虚函数与抽象类的概念,并通过代码示例展示了多态的具体应用。此外,还讨论了动态绑定和静态绑定的区别,帮助读者深入理解多态机制。最后总结了多态在编程中的重要性和应用场景。 文章结构清晰,从基础到深入,适合初学者和有一定基础的开发者学习。如果你觉得内容有帮助,请点赞支持。 ❤❤❤
1599 1
|
人工智能 Java 开发者
豆包MarsCode “一键Apply”功能测评:编程效率革新利器
豆包MarsCode的“一键Apply”功能旨在提升开发者编程效率,通过AI自动生成和应用代码,简化重复操作、精准修复错误、助力新项目开发及快速生成注释。安装插件后,在VSCode中与AI对话生成代码并点击Apply按钮即可完成应用,过程流畅高效。适用于C++、Java、Python等多语言环境,极大节省开发时间,降低手动操作风险。无论是资深开发者还是新手,都能从中受益,显著提升编程体验。
1418 9
|
网络协议 算法 网络性能优化
|
监控 网络协议 JavaScript
tcping和ping命令
【8月更文挑战第2天】`tcping` 是一款基于 TCP 协议的网络测试工具,不同于传统的 `ping` 命令使用 ICMP 协议,`tcping` 通过尝试与目标主机的特定端口建立 TCP 连接来检查网络连通性和端口状态。这使其在一些禁用了 ICMP 的网络环境中特别有用。`
2187 3
tcping和ping命令
|
SQL 机器学习/深度学习 XML
mybatis-plus分页查询详解
mybatis-plus分页查询详解
11797 0
mybatis-plus分页查询详解
|
安全 关系型数据库 MySQL
"深度解析:MySQL密码修改与远程登录配置全攻略,保障数据库安全与灵活访问"
【8月更文挑战第9天】MySQL是广受青睐的开源关系型数据库系统,其安全性和易用性对DBA和开发者至关重要。本文通过实例解析MySQL中用户密码更新及远程登录配置,确保数据库安全访问与高效管理。首先介绍如何分步修改密码,包括登录MySQL、选择数据库、使用`ALTER USER`命令更新密码,并刷新权限。接着,指导如何配置远程访问,涉及调整MySQL监听地址、授权用户远程登录、检查网络设置及测试远程连接。遵循这些步骤,可强化数据库安全性并实现灵活管理。
1079 0
|
监控 安全 中间件
Python 日志处理详解:从基础到实战
【2月更文挑战第5天】Python 日志处理详解:从基础到实战