_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

[C++] 纯文本查看 复制代码
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))的更多相关文章

  1. C++ Unicode SBCS 函数对照表

    C++ Unicode SBCS 函数对照表,以备日后查阅 Generic SBCS UNICODE TCHAR char wchar_t _TEOF EOF WEOF _TINT int wint_ ...

  2. C++ Unicode SBCS 函数对照表,以备日后查阅(很全)

    C++ Unicode SBCS 函数对照表,以备日后查阅 Generic SBCS UNICODE TCHAR char wchar_t _TEOF EOF WEOF _TINT int wint_ ...

  3. printf打印输出null问题的跟踪

    最近在工作中,遇到一处 printf输出有null的情况,在此记录一下,问题分析的过程. 测试代码很简单,本机为64位操作系统: #include <stdio.h> #include & ...

  4. ANSI 和 UNICODE 的函数对应表

    ANSI        UNICODE           通用(char.h)    (wchar.h)        (tchar.h) char         wchar_t         ...

  5. 【C++】wchar、char格式化符输出

    VC.BCB.MinGW Linux下的GCC.C99标准 printf wprintf printf wprintf s char wchar_t char S wchar_t char * hs ...

  6. VC++关于UNICODE版本的开发

    关于UNICODE版本的开发 代码转换方案 概述 在VC6.0中,相应的有一些宏来代替ANSI的函数.宏或数据类型,这些宏在ANSI编译条件中处理字符串为单字节,而在UNICODE中处理字符串为双字节 ...

  7. c++ wchar_t

    ·C语言相关 对应于char, C语言中也有宽字符内型wchar_t.wchar_t被定义为: typedef unsigned short wchar_t ;显然它是16位的.wchar_t类型的常 ...

  8. C++/VC中ANSI与UNICODE中字符定义和函数对照表

    这样查起来方便多了 ANSI UNICODE 通用 说明 数据类型 (char.h) (wchar.h) (tchar.h)   char wchar_t TCHAR   char * wchar_t ...

  9. 使你的C/C++代码支持Unicode(CRT字符串处理的所有API列表,甚至有WEOF字符存在)

    悉Microsoft支持Unicode的方式. 它的主要目的是方便你查询相关的数据类型和函数,以及修正相应的拼写错误. I18nGuy 主页 XenCraft (Unicode 咨询公司) Engli ...

随机推荐

  1. winform获取文件路径

    1.取得控制台应用程序的根目录方法     方法1.Environment.CurrentDirectory 取得或设置当前工作目录的完整限定路径     方法2.AppDomain.CurrentD ...

  2. XE8_TPaintBox画

    1. procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas); var bitmap :TBitMap; pt1, pt2 ...

  3. Struts2学习(1)

    struts2概述 1.struts2框架应用javaee三层结构中web层框架. 2.strut2框架在struts1和webwork基础之上发展全新的框架. 3.struts2解决的问题: 4.版 ...

  4. python基础6 - while 循环与转义字符

    8. while 循环基本使用 8.1 while 语句基本语法 初始条件设置 —— 通常是重复执行的 计数器 while 条件(判断 计数器 是否达到 目标次数): 条件满足时,做的事情1 条件满足 ...

  5. 51nod 1672 贪心/队列

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1672 1672 区间交 基准时间限制:1 秒 空间限制:131072 K ...

  6. hdu 3410 单调栈

    http://acm.hdu.edu.cn/showproblem.php?pid=3410 Passing the Message Time Limit: 2000/1000 MS (Java/Ot ...

  7. mysql插入一万条数据

    定义一个存储过程 mysql> delimiter $$ mysql> create procedure ptest()    -> begin    -> declare p ...

  8. 浅谈MariaDB Galera Cluster架构

    MariaDB          MariaDB 是由原来 MySQL 的作者Michael Widenius创办的公司所开发的免费开源的数据库服务器,MariaDB是同一MySQL版本的二进制替代品 ...

  9. kylin_学习_02_kylin使用教程

    一. 二.参考资料 1.kylin从入门到实战:实际案例

  10. golang的项目结构 相关知识

    ### 项目结构 ``` ├── bin │   ├── login │   └── main ├── pkg │   └── darwin_amd64 │   └── login │   └── a ...