iostream、printf/wprintf和中文輸出

使用C++標準庫的iostream,可以方便地將控制檯、文件、字符串以及其它可擴充的外部表示作爲流來處理,但要處理中文,卻會碰到很多問題。本人原來沒怎麼用過這個iostream,這幾天嘗試用這個寫點東西,一會兒不能輸出中文,一會兒不支持中文文件名的,搞得頭大。網上搜了搜,沒有發現適用於所有情況的解決方案。不過後來自己經過多次測試,基本解決了這些問題,現在寫成文字作爲一個總結,也供碰到同樣問題的朋友參考。關於C語言中的printf和wprintf的中文輸出,本文也進行了探討。

  需要說明的是,我的開發環境是VS 2005(標準庫當然也是微軟實現的),不保證其它環境下是相同的效果。

1、cout和wcout

  在缺省的C locale下,cout可以直接輸出中文,但對於wcout卻不行(至少VS 2005下不行)。對於wcout,需要將其locale設爲本地語言才能輸出中文:

  wcout.imbue(locale(locale(),"",LC_CTYPE));  // ①

  也有人用如下語句的,但這會改變wcout的所有locale設置,比如數字“1234”會輸出爲“1,234”。

  wcout.imbue(locale(""));

2、ofstream和wofstream

  在缺省的C locale下,ofstream能正確輸出中文到文件中,但不支持中文文件名;wofstream支持中文文件名,但不能向文件中輸出中文。要解決這個問題,需要在打開文件之前將全局locale設爲本地語言。將全局locale設爲本地語言後,ofstream和wofstream的問題都解決了,但cout和wcout卻不能輸出中文了。要讓cout和wcout輸出中文,需要將全局locale恢復原來的設置,如下所示:

  locale &loc=locale::global(locale(locale(),"",LC_CTYPE));  // ②
  ofstream ofs("ofs測試.txt");
  wofstream wofs(L"wofs測試.txt");
  locale::global(loc);  // ③
  ofs<<"test測試"<<1234<<endl;
  wofs<<L"Another test還是測試"<<1234<<endl;

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字符串,則不需設置。

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/dawei_sun/archive/2008/12/17/3541351.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章