_tprintf(), printf(),wprintf() 与控制字符 %s 和 %S(Unicoe与GB2312))
_tprintf() 是 printf() 和 wprintf() 的通用类型;如果定义了 _unicode,那么 _tprintf() 就会转换为 wprintf(),否则为 printf() 。
在这 3 个函数中有两个字符串控制输出字符为 %s 和 %S 。使用它们时,有如下区别:
%s
当使用 printf() 时,按照单字符格式输出字符串。
当使用 wprintf() 时,按照宽字符(两字节)格式输出字符串。
%S
当使用 printf() 时,按照宽字符格式输出字符串。
当使用 wprintf() 时,按照单字符格式输出字符串。
这里,所谓的 “单字符” 格式,就是指按照字节的原始样式输出,而 “宽字符” 则是按照 Unicode 码双字节的样式输出。举一个例子,当按照
“单字符” 样式输出时,如果你的系统是简体中文,采用 GB2312 编码,那么如果输出的连续两个字节组合起来刚好可以形成一个合法的 GB2312
编码,那么它就显示为一个汉字。如果是按照“宽字符”样式输出,一次输出两个字节,且假设这两个字节的 Unicode 码刚好若能正常转换为相应的
GB2312 码,且在程序里使用了 setlocale() 函数将程序的 locale 设为和系统默认 locale 一致时,那么输出的
Unicode 码则可以被自动转换为 GB2312 码,这时也可以正常显示出汉字。
下面举例演示上述情况。
程序-1:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
int _tmain(int argc, _TCHAR* argv[]){ CHAR buffer[20] = {}; buffer[0] = 0xcc; buffer[1] = 0x96; /* “雌” 的 Unicode 码*/ buffer[2] = 0xb4; buffer[3] = 0xdf; /*“催” 的 GB2312 码*/ buffer[4] = '\0'; printf ("\n--%s", buffer); printf ("\n==%S", buffer); wprintf (L"\n-=%S", buffer); wprintf (L"\n=-%s", buffer); return 0; |
首先,0x96CC 是 “雌” 字的 Unicode 码,该字的 GB2312 码为 0xB4C6 。0xB4DF 是 “催” 字的 GB2312 码。
运行上面程序:
D:\WindowsAPP\setfp\Debug>setfp.exe
--號催
==
-=號催
=-??
分析上面的输出结果。首先我们使用 printf() 并以 %s 的格式打印出数组 buffer[]
里的内容,上面说过 %s 是以单字符格式输出的,换句话来说,我们这里顺序输出了 0xcc, 0x96, 0xb4, 0xdf 这 4
个字节。因为 GB2312 的编码也是两个两个字节编码的,而我们的命令行里使用的编码也是 GB2312,因此前面的 0xcc 和 0x96
所组成的 0xcc96 并不在 GB2312 码表内(GB2312 码的低字节不小于 0xA0),所以它不能显示为 GB2312
里所列的常用汉字。而接下来的一组 0xb4df 就可以正常的解析为汉字 “催” 字。
那么当我们用 printf() 并以 %S 格式输出时(这里只输出了 "==" 而后面内容不可见),尽管上面的 0xCC96 符合汉字 "雌“
编码,但 C 语言默认的 locale 并不支持汉字的显示,所以要先用 setlocale() 函数进行 locale 的设定,使程序所用
lacale 和系统默认的一致,这样 Unicode 码就能被正常解析为相应的 GB2312
码,从而正确显示出汉字来。这个情况会在程序2里做演示。
第 3 个行我们用 wsprintf() 并以 %S 的格式控制输出,上面说过,此时 wprintf() 是按照 ”单字符“ 格式输出的,因此和 "printf() + %s" 的情况一样。
第 4 行我们使用 wsprintf() 并以 %s 的格式控制输出,此时 wprintf() 是按照 ”宽字符“
样式输出的,由于我们这里没有使用 setlocale() 的缘故,0xcc96 无法显示出汉字,而最后的组合 0xb4df
这个码(注意,此处已经被认为是 Unicode 形式) 并没有相应的汉字对应,况且也没有实现 setlocale() ,那自然是无法识别。
下面的程序对上面的 示例-1 稍作修改(示例-2),即加上 setlocale() 函数后,再运行看下输出:
D:\WindowsAPP\setfp\Debug>setfp.exe
--號催
==雌
-=號催
=-雌?
这时候,我们看到第一行的 "printf() + %s" 的输出和 示例-1 的情况一样,由此可见,setlocale() 并不会影响单字节输出时对 GB2312 码的转换,因为它本身就是要求对输出的字节按照 GB2312 码来解析的。
现在在第 2 行里,我们看到,"printf() + %S" 已经可以输出汉字 ”雌“ 了,这是因为 setlocale() 可以使
Unicode 码可以转换为 GB2312 的缘故,而后面的 0xb4df 被当做 Unicode 码看待,因而没法转换为合适的 GB2312
码,因此没法显示。
第 3 行的输出和第 示例-1 中的输出及道理一样。
第 4 行是以 "wprintf() + %s" 输出,这时 wprintf() 以 ”宽字符“ 样式输出,因此 ”雌” 字可以正常显示,同理后面的字符无法显示。
_tprintf(), printf(),wprintf() 与控制字符 %s 和 %S(Unicoe与GB2312))的更多相关文章
- C++ Unicode SBCS 函数对照表
C++ Unicode SBCS 函数对照表,以备日后查阅 Generic SBCS UNICODE TCHAR char wchar_t _TEOF EOF WEOF _TINT int wint_ ...
- C++ Unicode SBCS 函数对照表,以备日后查阅(很全)
C++ Unicode SBCS 函数对照表,以备日后查阅 Generic SBCS UNICODE TCHAR char wchar_t _TEOF EOF WEOF _TINT int wint_ ...
- printf打印输出null问题的跟踪
最近在工作中,遇到一处 printf输出有null的情况,在此记录一下,问题分析的过程. 测试代码很简单,本机为64位操作系统: #include <stdio.h> #include & ...
- ANSI 和 UNICODE 的函数对应表
ANSI UNICODE 通用(char.h) (wchar.h) (tchar.h) char wchar_t ...
- 【C++】wchar、char格式化符输出
VC.BCB.MinGW Linux下的GCC.C99标准 printf wprintf printf wprintf s char wchar_t char S wchar_t char * hs ...
- VC++关于UNICODE版本的开发
关于UNICODE版本的开发 代码转换方案 概述 在VC6.0中,相应的有一些宏来代替ANSI的函数.宏或数据类型,这些宏在ANSI编译条件中处理字符串为单字节,而在UNICODE中处理字符串为双字节 ...
- c++ wchar_t
·C语言相关 对应于char, C语言中也有宽字符内型wchar_t.wchar_t被定义为: typedef unsigned short wchar_t ;显然它是16位的.wchar_t类型的常 ...
- C++/VC中ANSI与UNICODE中字符定义和函数对照表
这样查起来方便多了 ANSI UNICODE 通用 说明 数据类型 (char.h) (wchar.h) (tchar.h) char wchar_t TCHAR char * wchar_t ...
- 使你的C/C++代码支持Unicode(CRT字符串处理的所有API列表,甚至有WEOF字符存在)
悉Microsoft支持Unicode的方式. 它的主要目的是方便你查询相关的数据类型和函数,以及修正相应的拼写错误. I18nGuy 主页 XenCraft (Unicode 咨询公司) Engli ...
随机推荐
- 汇编笔记 RETF
assume cs:code stack segment db 16 dup(0) stack ends code segment start: mov ax,stack;将定义字形数据送入AX mo ...
- python练习_sed替换
python练习_sed替换 需求: 做一个sed替换小程序,实现在windows下可以与实现linux中sed替换的功能 支持正则(re模块) 以下代码实现的功能与思路: 功能: (1)支持文件内容 ...
- jmeter ant 运行 提示Error occurred during initialization of VM
运行ant提示错误 网上找到的方法 将set HEAP= -Xms512m -Xmx1024m 改成set HEAP= -Xms512m -Xmx512m 保存后运行成功
- 天地图OGC WMTS服务规则
图层名称 服务地址 投影类型 矢量底图 http://t0.tianditu.gov.cn/vec_c/wmts?tk=您的密钥 经纬度投影 http://t0.tianditu.gov.cn/vec ...
- hdu5692 dfs序线段树
这是补的知识点,按先序遍历的顺序建立dfs序,用左右两个值代表整个区间,因为dfs序最重要的特点就是子树的区间是连续的 建立线段树时,需要用重新标过的 下标来建立 #pragma comment(li ...
- Android开发中dp、dpi、px的区别(转)
一.基本概念 - dp:安卓中的相对大小 - dpi:(dot per inch)每英寸像素多少 - px:像素点 二.详细说明 1.px和dpi - px: 平常所说的1920×1080只是像素数量 ...
- ZeroClipboard 简单应用
ZeroClipboard.config({ swfPath: "/scripts/ZeroClipboard.swf" }); var client = new ZeroClip ...
- DocString
文档字符串:写注释专用的, 在函数的第一个逻辑行的字符串是这个函数的 文档字符串 .注意,DocStrings也适用于模块和类,我们会在后面相应的章节学习它们. 文档字符串的惯例是一个多行字符串,它的 ...
- URL OpenDocument
以前用在DASHBOARD 使用URL传参 到webi 报表.还是很多不理解,现在明白多了.于是做个较为详细的记录.尽管dashboard 很快就被淘汰了.也许没什么用.看看也好. 之前的报表,传参都 ...
- gulp插件之-----转化es6代码到es5 取消严格模式 remove "use strict" directive
Installation npm install babel-plugin-transform-remove-strict-mode && yarn add babel-plugin- ...