当前位置: 首页 > news >正文

不同编码格式(Unicode、多字节字符)vs环境下使用printf、scanf应注意事项

事件起因:
因需要格式化一个字符串,格式化字符串的方式方法很多,特别在MFC环境下,有CString的Format,有sprintf等,由于我们需要使用安全版本,所以选择了sprintf_s,本次由于是使用dll模块,所以新建了一个mfc测试程序测试我们的sprintf_s,测试通过后,再修改到dll模块里,然后将模块发送出去,结果客户方说不行,调了1个来小时,发现是编码格式问题。
解决方案:
由于客户运行环境是Unicode环境,所以应该使用swprintf_s函数来代替。

一般多字节环境我们平时使用较多,比较熟悉,这里不做介绍,这里主要介绍下在Unicode环境下使用printf和scanf函数。

一、_stprintf_s

  • 需要头文件:<TCHAR.H>
  • MSDN上对_stprintf_s函数的定义如图:
    在这里插入图片描述
    头文件:
    在这里插入图片描述
    对应头文件里代码为:
#ifdef UNICODE
#define _stprintf_s     swprintf_s
#else
#define _stprintf_s     sprintf_s

在这里插入图片描述
其中:

  • 前面的t表示编码,后面的_s表示检查内存溢出,前面的_表示非标准库函数。
  • 从上我们可以看出,_stprintf _s和_stscanf_s是为适应不同编码而定义的两个宏,在不同的编码环境下他们所表示的函数是不同的。
  • _s是security 的意思,具体含义参见后面的Security Remarks部分。
//ANSI 版本
int sprintf_s( char *buffer, size_t sizeOfBuffer, const char*format [, argument] ...); 
//UNICODE版本
int swprintf _s(wchar_t *buffer, size_t sizeOfBuffer, const wchar_t *format[,argument]J..); 

这个函数的主要作用是将若干个argument按照format格式存到buffer 中。

  • buffer:输出的字符
  • sizeOfBuffer: buffer 的长度,以能存放的字符数计算,而不是已占用的字节数计算。这很重要。一个UNICODE字符占用2个字节。
  • format:格式字符串,比如%s
  • argument:可选参数

二、_stscanf_s

对应头文件里代码为:

#ifdef UNICODE
#define _stscanf_s     swscanf_s
#else
#define _stscanf_s     sscanf_s
//ANSI 版本
int sscanf_s( const char *buffer, const char*format [, argument ] ... );
//UNICODE版本
int swscanf_s( const wchar_t *buffer, const wchar_t *format [, argument ] ...);

这个函数的主要作用是从 buffer 中读取指定格式( format)的字符到相应的argument 中。参数同上。
几个需要注意的细节:

  • 为了让编译器识别Unicode字符串,必须以在前面加一个“L”,定义宽字节类型方法如下:L“ABC”,表示字符串“ABC”是用UNICODE编码的。
  • char与 wchar t的区别: char中存放的是单字节型的字符,wchar_t中存放的是双字节型的字符,TCHAR在定义了_UNICODE时等同于wchar_t,在未定义
    _UNICODE时等同于char。

总结:

在我们使用过程中,尽量使用宏定义函数,而不用收编码环境影响。

相关文章:

  • 使用Express获取jquery数据 使用模块化 共享自己的数据库
  • Python算法:决策树分类
  • IDEA插件开发-学习
  • python工具方法35 实现SWA,再一次提升模型的性能
  • mysql查询优化实战:查询用时一分半降到三毫秒
  • 你用什么方法做副业赚钱?
  • 十五:Fiddler抓包教程(15)-Fiddler弱网测试
  • 【最长公共子序列】两行字符串,不交叉相连,最多连线
  • 终端I/O.
  • MySQL触发器简介
  • 计算机SSM毕设推荐 40个高质量软件工程毕设项目分享【源码+论文】(四)
  • C语言利用函数解决问题:1.实现reverse函数完成数组元素的逆置;2.将两个数组的元素进行互换;3.统计二进制中1的个数
  • Html:网站设计的内容概览简介、网页设计流程/工具/内容组成、脚本代码之详细攻略
  • 网络安全笔记 -- XXEXML(利用、检测、绕过)
  • c语言小项目(静态通讯录)
  • 30秒的PHP代码片段(1)数组 - Array
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • CAP 一致性协议及应用解析
  • classpath对获取配置文件的影响
  • es6
  • JavaScript创建对象的四种方式
  • JavaScript设计模式之工厂模式
  • LeetCode算法系列_0891_子序列宽度之和
  • Linux下的乱码问题
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • Next.js之基础概念(二)
  • node-glob通配符
  • python大佬养成计划----difflib模块
  • SpringBoot几种定时任务的实现方式
  • SQLServer之创建显式事务
  • windows-nginx-https-本地配置
  • 阿里中间件开源组件:Sentinel 0.2.0正式发布
  • 编写高质量JavaScript代码之并发
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 大整数乘法-表格法
  • 前端技术周刊 2019-02-11 Serverless
  • 前嗅ForeSpider采集配置界面介绍
  • 入口文件开始,分析Vue源码实现
  • 写代码的正确姿势
  • 用简单代码看卷积组块发展
  • 原创:新手布局福音!微信小程序使用flex的一些基础样式属性(一)
  • 运行时添加log4j2的appender
  • 《码出高效》学习笔记与书中错误记录
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • "无招胜有招"nbsp;史上最全的互…
  • # Panda3d 碰撞检测系统介绍
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • $$$$GB2312-80区位编码表$$$$
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (4.10~4.16)
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (附源码)ssm高校社团管理系统 毕业设计 234162