C 使用wprintf,_tprintf 打印简体中文的方法 【Locale.h】{
如果将程序改写如下,则输出的结果就不一样了
#include <locale>
包含头文件先
paName :b2e2 cad4 d6d0 …… 应该是CHS编码(也就是代码页936)
-------------------
以上是网上找到的解决方法
转自:http://www.cnblogs.com/niuniu502/archive/2009/02/17/1392636.html
3、printf和wprintf
加上这两位C语言中的老兄,问题更加复杂。考虑如下语句(注意s的大小写):
printf("%s", "multibyte中文\n"); // ④
printf("%S", L"unicode中文\n"); // ⑤
wprintf(L"%S", "multibyte中文\n"); // ⑥
wprintf(L"%s", L"unicode中文\n"); // ⑦
缺省情况下,⑤、⑦两条语句不能输出中文,这两条语句中字符串的形式是unicode形式的。如果在所有输出语句之前加上如下语句将C语言的全局locale设置为本地语言(C语言中只有全局locale)就可以正常输出了:
setlocale(LC_CTYPE, ""); // ⑧
但这会导致cout和wcout不能输出中文(汗,的确麻烦),将C语言的全局locale恢复后cout和wcout就正常了,如下所示:
setlocale(LC_CTYPE, "C"); // ⑨
但恢复后,printf和wprintf输出Unicode文本又不正常了(输出MultiByte文本总是正常的)。总不能每写一个 printf/wprintf就设置一次然后再恢复一次吧?所以,建议不要混用iostream和printf/wprintf,实在要混用,那就让 printf/wprintf只输出MultiByte字符串,这样不需要调用setlocale(),也就不会影响到cout和wcout。
总结
总之,用iostream、printf/wprintf输出中文,有点麻烦。概括起来要点如下:
如果要用wcout,需要在使用之前按语句①将其locale设置为本地语言;如果要用ofstream或wofstream,要在打开文件之前按语句②将全局locale设为本地语言并保存初始的全局locale。然后在打开文件之后,按语句③将全局locale恢复为初始值;不要混用iostream和printf/wprintf。如果要混用,只用printf/wprintf输出MultiByte字符串;单独使用printf/wprintf时,如果要输出Unicode字符串,需要按语句⑧设置C语言的全局locale。如果只输出MultiByte字符串,则不需设置。
为什么 wprintf 无法打印中文?
大学时就遇到这个问题,觉得很奇怪,为什么明明 Windows NT 系列内核都是使用 Unicode 的,而且在中文系统下跑,怎么反而无法输出汉字?虽然那时候鼓浪听涛上有前辈给出了提示,但还是不明白怎么会有这么 BT 的 CRT……
最近看了《C99 规范》才明白了,原来这是“规范”规定的(C99 这样规定,C89 应该也有吧,谁证实一下?):
At program startup, the equivalent of
setlocale(LC_ALL, "C");
is executed.
所以,setlocale(LC_CTYPE, NULL); 会返回一个 "C"。
常规的解决方法是在程序入口处加下面这句代码:
setlocale(LC_CTYPE, "chs");
但这样写要是用户在繁体版系统下运行岂不是出问题了,枉费了 Unicode 的好处,我发现用下面两个更好:
TCHAR szACP[16];
wsprintf(szACP, _T(".%d"), GetACP());
_tsetlocale(LC_CTYPE, szACP);
setlocale(LC_CTYPE, "");// 这个方案有待测试,谁帮我在英文版、繁体中文版上测一下?
个人不太相信 CRT,不过也没办法,流行嘛……
wsprintf
函数作用:
函数wsprintf()将一系列的字符和数值输入到缓冲区。
输出缓冲区里的的值取决于格式说明符(即"%")。
如果写入的是文字,此函数给写入的文字的末尾追加一个'\0'。
函数的返回值是写入的长度,但不包括最后的'\0'。
语法:
int wsprintf(
LPTSTR lpOut, // 输出缓冲区,最大为1024字节
LPCTSTR lpFmt, // 格式字符串
...) // 需输出的参数;
;多少个参数都可以的,最起码前两个必须有
我们在接触C语言的时候还接触过一个sprintf()的函数,
用法和wsprintf()基本一样,区别在于:
wsprintf()包含在头文件windows.h中
sprintf()包含在头文件stdio.h中。
wsprintf 其实分为 wsprintfA 和 wsprintfW,前者对应 sprintf,后者对应 wsprintf。
wsprintf 有 1024 字符限制,而且不支持浮点数。
所以注意了,该函数不支持浮点数的输入输出
关于%s和%ls的区别
我搜到了一篇帖子(很伤感,我再此发现在CS领域,最靠的住的资料总是英文的),里面对各种格式转换符有详细的解释,愿意看原文的同学直接忽略本段文字.......
http://www-ccs.ucsd.edu/c/lib_prin.html
首先,%ls和%s的区别很简单,%ls意味着将对应的参数会被当作基于宽字符的字符串(wide chraracter string )看待,而%s则意味着对应的参数会被当作普通字符串(multi-byte string)看待。
其次,不要因为上面一句话而错误的认为%s只用于printf,而%ls只用于wprintf 。实际上,(printf, wprintf) 和(%s,%ls)这两个元组之间是相互独立的,也就是说它们之间的四种组合都是可以的。
再次,printf用于byte stream,即输出流中的每个字符颤1 byte;而wprintf则用于wide stream,输出流中的每个字符不止 1 byte。
说了一堆废话,还是结合实例来看看%ls和%s的区别吧
例子1 printf + %s + wstr
whodare@whodare:$ . / a. out
- N
哈,这个郁闷的"-N"又一次出现!为什么会出现呢?让我来分析一下printf在执行时所完成的操作吧。
这里用了%s, printf 就会将对应的参数wstr视为普通字符串(尽管我们清楚他是个wcs而不是mbs);另一方面,我们已经看到了wstr[ ]的内存布局,其前3 byte为 0x2d ,0x4e,0x00。我们都知道C中的字符串以'\0'为结束标志,因此printf只会处理wstr[ ]中的前三个byte,而查一查ASCII表,0x2d对应字符'-',0x4e对应字符'N',所以我们会看到”-N"这个诡异的输出。
例子2 printf + %ls + wstr
whodare@whodare:$ . / a. out
中文
使用了%ls,printf会将对应的参数视为宽字符串(wcs),而printf又对应byte stream,因此这里要对宽字符(wcs)进行转换,变成普通的字符串(mbs)。这里的转换是printf通过对每个宽字符隐式的调用wcrtomb ()这个标准库函数完成的。按么,wcrtomb()这个函数进行是按照什么规则进行转换的?这就是setlocale()的作用所在了,wcrtomb 会依据程序员设定的locale,将wcha_t中存放的码值,转换为相应的的多字节编码。
回到例子中,我的机器的locale为zh_CN.UTF-8,对应的编码为UTF-8,因此wstr[ ]中存放的Unicode码值会转换为UTF-8编码的形式输出到标准输出流中,这样采用UTF-8编码的console就能正确识别受到的字节流并显示出"中文"
例子3 wprintf + %s +wstr (最初的代码!)
whodare@whodare:$ . / a. out
- N
使用了%s,wprintf会将对应的参数视为普通字符串mbs,尽管我们还是很清楚它其实是个wcs。 wprintf 使用的是wide stream,因此需要将所给的mbs参数转换为wcs再由wprintf完成输出;这个转换是由wprintf隐式的对mbs不断调用mbrtowc来完成,转换规则依然是和locale相关的。
我们知道wstr的内存布局为:
0x2d 0x4e 0x00 0x00 0x87 0x65 0x00 0x00
0x00 0x00 0x00 0x00
该"mbs"的转换结果为 L‘0x2d' + L '0x4e' + L '0x00' ,最终输出结果又是讨厌的"-N"
例子4 wprintf + %ls+ wstr
whodare@whodare:$ . / a. out
中文
使用了%ls,wprintf会将对应参数视为宽字符串wcs,这次终于没有搞错。因此wprintf会顺利的将给定的宽字符串写入标准输出流,最终正确显示"中文"
看完这4个例子,你对wprintf、printf和%ls 、%s的使用还有疑惑么?
四、小结
1。要清楚%ls和%s的意义在于指明所期待的参数是何种字符串,而printf和wprintf的区别在于所使用的是不同类型的stream
2。貌似在linux下输出“中文"的正确方法是 wprintf( "%ls\n",L"中文") ,而引文中作者在Windows成功操作的wprintf("%s\n", L"中文")在linux无法正确工作,至于为何wprintf这个标准库函数在两个系统下有不同表现,我是无心再向下深挖了,难道这又是VC一处不符合标准的地方?.......
3 。貌似还有一个%S,单独用于表示对应参数是宽字符串
谁能告诉我该问题的答案,不盛感激.......
参考:
1.http://blog.csdn.net/whitehack/archive/2011/01/03/6113908.aspx
2.http://blog.csdn.net/dawei_sun/archive/2008/12/17/3541351.aspx
3.http://hi.baidu.com/umu618/blog/item/77f3dac8e6ac5f117f3e6f0e
4.http://baike.baidu.com/view/849487.htm
5.http://www.360doc.com/content/08/1203/15/28217_2044833.shtml