_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() 以 ”寬字符“ 樣式輸出,因此 ”雌” 字可以正常顯示,同理后面的字符無法顯示。
