snprintf()函数探讨printf()/sprintf()/snprintf()区别

2024-05-13 07:08

本文主要是介绍snprintf()函数探讨printf()/sprintf()/snprintf()区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

snprintf()函数探讨

2012年09月06日 12:53:37

阅读数:14336

printf()/sprintf()/snprintf()区别 
先贴上其函数原型
printf( const char *format, ...)    格式化输出字符串,默认输出到终端-----stdout
sprintf(char *dest, const char *format,...)     格式化输出字符串到指定的缓冲区
snprintf(char *dest, size_t size,const char *format,...)     按指定的SIZE格式化输出字符串到指定的缓冲区

printf()函数在这就不再讨论,这里主要讨论sprintf()与snprintf()的用法及区别,

 
  1. #include "stdafx.h"

  2. #include <stdio.h>

  3. using namespace std;

  4. int _tmain(int argc, _TCHAR* argv[])

  5. {

  6. char *p1="China";

  7. char a[20];

  8. sprintf(a,"%s",p1);

  9. printf("%s\n",a);

  10. memset(a,0,sizeof(a));

  11. _snprintf(a,3,"%s",p1);

  12. printf("%s\n",a);

  13. printf("%d\n",strlen(a));

  14. return 0;

  15. }


结果输出:
China
Chi
3
分析:
sprintf(a,"%s",p1)  把p1字符串拷贝到数组a中('\0'也拷贝过去了)。
snprintf(a,3,"%s",p1)  拷贝P1中前3个字符到数组a中,并在末尾自动添加'\0'。
sprintf属于I/O库函数,snprintf函数并不是标准c/c++中规定的函数,但是在许多编译器中,厂商提供了其实现的版本。在gcc中,该函数名称就snprintf,而在VC中称为_snprintf。 如果你在VC中使用snprintf(),会提示此函数未声明,改成_snprintf()即可。

注意点:
1   sprintf是一个不安全函数,src串的长度应该小于dest缓冲区的大小,(如果src串的长度大于或等于dest缓冲区的大小,将会出现内存溢出。)
2   snprintf中源串长度应该小于目标dest缓冲区的大小,且size等于目标dest缓冲区的大小。(如果源串长度大于或等于目标dest缓冲区的大小,且size等于目标dest缓冲区的大小,则只会拷贝目标dest缓冲区的大小减1个字符,后加'\0';该情况下,如果size大于目标dest缓冲区的大小则溢出。)
3   snprintf ()函数返回值问题,   如果输出因为size的限制而被截断,返回值将是“如果有足够空间存储,所应能输出的字符数(不包括字符串结尾的'\0')”,这个值和size相等或者比size大!也就是说,如果可以写入的字符串是"0123456789ABCDEF"共16位,但是size限制了是10,这样 snprintf() 的返回值将会是16 而不是10!

 

snprintf()函数用于将格式化的数据写入字符串,其原型为:
    int snprintf(char *str, int n, char * format [, argument, ...]);


【参数】str为要写入的字符串;n为要写入的字符的最大数目,超过n会被截断;format为格式化字符串,与printf()函数相同;argument为变量。


【返回值】成功则返回参数str 字符串长度,失败则返回-1,错误原因存于errno 中。


snprintf()可以认为是sprintf()的升级版,比sprintf()多了一个参数,能够控制要写入的字符串的长度,更加安全,只要稍加留意,不会造成缓冲区的溢出。


snprintf()与sprintf()使用方法类似,请参考:C语言sprintf()函数


注意:snprintf()并不是标C中规定的函数,但是在许多编译器中,厂商提供了其实现的版本。


在GCC中,该函数名称就snprintf(),而在VC中称为_snprintf()。由于不是标准函数,没有一个统一的标准来规定该函数的行为,所以导致了各厂商间的实现版本可能会有差异。


差异发生在参数 n。在GCC中,参数n是要向str写入3个字符,包括'\0'字符;在VC中,参数n是要写入的字符串的总字符数。


在GCC中运行如下程序:
#include <stdio.h>
int main()
{
    char str[5];
    int ret = snprintf(str, 3, "%s", "abcdefg");
    printf("%d\n",ret);
    printf("%s",str);
    return 0;
}
输出:
7
ab


在VC中运行如下程序:
#include <stdio.h>
int main()
{
    char str[5];
    int ret = _snprintf(str,3,"%s","abcdefg");
    printf("%d\n",ret);
    printf("%s",str);
    return 0;
}
输出:
-1
abc

从输出结果可以知道:
GCC中的参数n表示向str中写入n个字符,包括'\0'字符,并且返回实际的字符串长度。
VC中的参数n表示会向str中写入n个字符,不包括'\0'字符,并且不会在字符串末尾添加'\0'符。当字符串长度超过参数n时,函数返回-1,以表示可能导致错误

这篇关于snprintf()函数探讨printf()/sprintf()/snprintf()区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/985016

相关文章

关于Mybatis和JDBC的使用及区别

《关于Mybatis和JDBC的使用及区别》:本文主要介绍关于Mybatis和JDBC的使用及区别,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、JDBC1.1、流程1.2、优缺点2、MyBATis2.1、执行流程2.2、使用2.3、实现方式1、XML配置文件

exfat和ntfs哪个好? U盘格式化选择NTFS与exFAT的详细区别对比

《exfat和ntfs哪个好?U盘格式化选择NTFS与exFAT的详细区别对比》exFAT和NTFS是两种常见的文件系统,它们各自具有独特的优势和适用场景,以下是关于exFAT和NTFS的详细对比... 无论你是刚入手了内置 SSD 还是便携式移动硬盘或 U 盘,都需要先将它格式化成电脑或设备能够识别的「文

什么是ReFS 文件系统? ntfs和refs的优缺点区别介绍

《什么是ReFS文件系统?ntfs和refs的优缺点区别介绍》最近有用户在Win11Insider的安装界面中发现,可以使用ReFS来格式化硬盘,这是不是意味着,ReFS有望在未来成为W... 数十年以来,Windows 系统一直将 NTFS 作为「内置硬盘」的默认文件系统。不过近些年来,微软还在研发一款名

Kotlin运算符重载函数及作用场景

《Kotlin运算符重载函数及作用场景》在Kotlin里,运算符重载函数允许为自定义类型重新定义现有的运算符(如+-…)行为,从而让自定义类型能像内置类型那样使用运算符,本文给大家介绍Kotlin运算... 目录基本语法作用场景类对象数据类型接口注意事项在 Kotlin 里,运算符重载函数允许为自定义类型重

Pandas中统计汇总可视化函数plot()的使用

《Pandas中统计汇总可视化函数plot()的使用》Pandas提供了许多强大的数据处理和分析功能,其中plot()函数就是其可视化功能的一个重要组成部分,本文主要介绍了Pandas中统计汇总可视化... 目录一、plot()函数简介二、plot()函数的基本用法三、plot()函数的参数详解四、使用pl

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

Python正则表达式语法及re模块中的常用函数详解

《Python正则表达式语法及re模块中的常用函数详解》这篇文章主要给大家介绍了关于Python正则表达式语法及re模块中常用函数的相关资料,正则表达式是一种强大的字符串处理工具,可以用于匹配、切分、... 目录概念、作用和步骤语法re模块中的常用函数总结 概念、作用和步骤概念: 本身也是一个字符串,其中

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的

售价599元起! 华为路由器X1/Pro发布 配置与区别一览

《售价599元起!华为路由器X1/Pro发布配置与区别一览》华为路由器X1/Pro发布,有朋友留言问华为路由X1和X1Pro怎么选择,关于这个问题,本期图文将对这二款路由器做了期参数对比,大家看... 华为路由 X1 系列已经正式发布并开启预售,将在 4 月 25 日 10:08 正式开售,两款产品分别为华