解决C++printf汉字问号。含_tprintf(),printf(),wprintf()
详解
printf() 控制台输出中⽂显⽰问号,英⽂和数字正常,解决如下:
包含locale.h,然后在输出前加上即可解决
setlocale(LC_ALL, "CHS");
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
_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:
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 码
运⾏上⾯程序得到如下结果:
--號催
==
-=號催
=-??
分析上⾯的输出结果。⾸先我们使⽤ printf() 并以 %s 的格式打印出数组 buffer[] ⾥的内容,上⾯说过 %s 是以单字符格式输出的,换句话来说,我们这⾥顺序输出了 0xcc, 0x96, 0xb4, 0xdf 这 4 个字节。因为 GB2312 的编码也是两个两个字节编码的,⽽我们的命令⾏⾥使⽤的编码也是 GB2312,因此前⾯的 0xcc 和 0x96 所组成的 0xcc96 并不在 GB2312 码表内(GB2312 码的低字节不⼩于 0xA0),所以它不能显⽰为 GB2312 ⾥所列的常⽤汉字。⽽接下来的⼀组 0xb4df 就可以正常的解析为汉字 “催” 字。
unicode汉字那么当我们⽤ 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 稍作修改,即加上 setlocale() 函数后,再运⾏看输出:
--號催
==雌
-=號催
=-雌?
这时候,我们看到第⼀⾏的 "printf() + %s" 的输出和 ⽰例-1 的情况⼀样,由此可见,setlocale() 并不会影响单字节输出时对 GB2312 码的转换,因为它本⾝就是要求对输出的字节按照 GB2312 码来解析的。
现在在第 2 ⾏⾥,我们看到,"printf() + %S" 已经可以输出汉字 ”雌“ 了,这是因为 setlocale() 可以使 Unicode 码可以转换为 GB2312 的缘故,⽽后⾯的 0xb4df 被当做 Unicode 码看待,因⽽没法转换为合适的 GB2312 码,因此没法显⽰。
第 3 ⾏的输出和第 ⽰例-1 中的输出及道理⼀样。
第 4 ⾏是以 "wprintf() + %s" 输出,这时 wprintf() 以 ”宽字符“ 样式输出,因此 ”雌” 字可以正常显⽰,同理后⾯的字符⽆法显⽰。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论