控制台輸出寬字符wchar_t的中文顯示問題


 

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

wcout輸出時顯示不了中文,加上下面這句就行了。

std::wcout.imbue(std::locale("chs"));

-----------------------------------------------------------------------------

#include <iostream>
#include <locale>
//using namespace std;

//this main function deals with wide character and Chinese character
int main(int argc, char **argv)
{
std::ios_base::sync_with_stdio(false); //garantee that iostreams are not synchronized with stdin or stdout
std::locale loc("zh_CN.utf8"); //set the character set to zh_CN.utf8
std::wcin.imbue(loc); //set the locale of wcin and wcout
std::wcout.imbue(loc);
wchar_t c;
std::wcin >> c; //read the input
std::wcout << c << std::endl;  //output
return 0;
}

在這段程序中需要注意:
    1.必須使用wcin和wcout對寬字符進行輸入和輸出,wcin和wcout是cin和cout的寬字符版本,也屬於標准庫的一部分。
    2.main函數首句是標准庫中ios_base類的方法,將iostream與C語言中的stdin/stdout的同步關系取消,否則wcout不能正常輸出中文。
    3.第二句使用std空間中的locale函數設置所用的字符集,在linux環境中的可用字符集使用locale -a獲取。
    4.三四兩句將該字符集應用於wcin和wcout流中。
    5.很多文章中提到的locale loc("chs")方法並不適用於linux系統,windows下是否可行本文沒有測試。
————————————————
版權聲明:本文為CSDN博主「charles_ma」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/charles_ma/article/details/7268101

 

1.采用ansi編碼方式,在ubuntu下會出錯,另外通過g++ -Wall -finput-charset=ISO-8859-1 test.cpp 方式可以指定輸入文件格式,但是這樣很麻煩,因為首先要知道文件的格式是什么,在ubuntu下 通過file  test.cpp 命令可以查到,我把ISO-8859-1到ISO-8859-16都試了,文件編碼格式ANSI(即ISO8859-XX)且文件中有L"國家" 類似字符,編譯不會通過,或者通過-finput-charset=xxx指定文件格式編譯通過后輸出也不對,故太麻煩。

2.在windows下和ubuntu下都通過的方式是文件編碼采用UTF-8。

3.printf和wprintf不能混用,即一個程序中使用了printf, 就不使用wprintf,反之也是,既然printf輸出char 和 wchar_t字符都可以,所以統一使用printf是最佳選擇。

  當然使用printf打印wchar_t時格式不一樣,是%ls 或大寫的%S,  例如: printf("wide char: %ls\n", ws);

4. 一旦要打印中文字符,在程序初始化時加一句setlocale(LC_ALL, ""); 否則打印中文會出錯。

5. windows 對 字符串的內部編碼比較統一,char的編碼都成ANSI,如 char  s[] = "國家", s里存的是”國家”的ANSI編碼

      wchar_t的編碼都成UCS-2,如 wchar_t  ws[] = L"國家", s里存的是”國家”的UCS-2編碼

    UBUNTU 對字符串的處理不是很統一,char 字符串的編碼是隨着文件編碼格式有所變化,如文件為ansi,則ubuntu也為ansi,文件為UTF-8, 則char s[] = "國家" 里的也是            UTF-8編碼。

       wchar_t 則默認采用ucs-4編碼。


總結:源代碼文件編碼用UTF-8, 打印采用printf是跨平台(操作系統,編譯器), 跨char和wchar_t的最佳解決方案之一,另外不能忘了 setlocale(LC_ALL, "");


說的再多,不如自己測試下,如下為測試代碼,一共有5種case,每次注釋掉其他case,留要測試的case,並按照case注釋處更改文件編碼方式便可, 更改編碼方式采用notepad++最方便了.

#include <stdio.h>
#include <string.h> 
#include <stddef.h>
#include <wchar.h>
#include <locale.h>
 
// 測試運行環境:
// ubuntu 12.04 + g++ 4.6.3(或gcc,改文件后綴就行) 
// windows 7 + vs2012
// 說明,在注釋中說的編碼E59BBD,是按照打印結果從低字節到高字節排練,並不一定和實際
// 的編碼大小端一致。
 
int main()  
{
    //此語句重要,在win7 + vs2012和 ubuntu 12.04測試結果一致,只要打印wchar_t字符,均加此語句,否則出錯。
    setlocale(LC_ALL, "");        
                
    /******************  case 1  **********************************/    
    // 文件utf-8編碼, 字符串不加L
    // ubuntu : ws是utf-8編碼: 如"國":E59BBD; 打印結果:國家
    // windows: ws是ansi編碼: 如"國":b9fa; 打印結果: 國家
/*     char ws[] = "國家"; 
    char *p = (char *)ws;
    int i = 0;
     
    printf("sizeof(ws) is %d\n", sizeof(ws));
    for (; i < sizeof(ws); i++){  
        printf("byte: %x\n", p[i]);    
    }
    printf("content start\n");   
    printf("%s\n", ws);
    printf("content end\n");        */  
 
        /******************  case 2  **********************************/    
    // 2: 文件ansi編碼, 字符串不加L
    // ubuntu : ws是ansi編碼,如"國":b9fa; 打印結果:無,出錯
    // windows: ws是ansi編碼: 如"國":b9fa; 打印結果: 國家
/*       char ws[] = "國家";
    char *p = (char *)ws;  
    int i = 0; 
    
    //setlocale(LC_ALL, "zh_CN.UTF-8");        
    printf("sizeof(ws) is %d\n", sizeof(ws));
    for (; i < sizeof(ws); i++){
        printf("byte: %x\n", p[i]);        
    }
    printf("content start: %s\n", ws);      
    printf("content end\n");  */   
    
    
      /******************  case 3  **********************************/    
    // 3: 文件utf-8編碼, 字符串加L, 必須采用wchar_t, 用char編譯器報錯, 用wprintf打印     
    // ubuntu : ws是ucs-4編碼,如"國":0x000056fd; 打印結果:國家
    // windows: ws是ucs-2編碼: 如"國":0x56fd; 打印結果: 國家
/*     wchar_t ws[] = L"國家";  
    char *p = (char *)ws;  
    int i = 0;      
               
    wprintf(L"sizeof(ws) is %d\n", sizeof(ws));
    for (; i < sizeof(ws); i++){  
        wprintf(L"byte: %x\n", p[i]);               
    }    
    wprintf(L"wprintf content start:\n");  //必須用wprintf, 且wprintf和printf不能同時使用.
    wprintf(L"%ls\n", ws);                
    wprintf(L"content end\n");    */          
    
        /******************  case 4  **********************************/    
    // 4: 文件utf-8編碼, 字符串加L, 必須采用wchar_t, 用char編譯器報錯, 用printf打印    
    // ubuntu : ws是ucs-4編碼,如"國":0x000056fd; 打印結果:國家
    // windows: ws是ucs-2編碼: 如"國":0x56fd; 打印結果: 國家
    wchar_t ws[] = L"國家"; 
    char *p = (char *)ws;       
    int i = 0;      
              
    printf("sizeof(ws) is %d\n", sizeof(ws));
    for (; i < sizeof(ws); i++){  
        printf("byte: %x\n", p[i]);               
    }        
 
    printf("printf content start:\n");  //wprintf和printf不能同時使用.
    printf("%ls\n", ws);                
    printf("content end\n");
 
    /******************  case 5  **********************************/         
    // 5: 文件ansi編碼, 字符串加L, 必須采用wchar_t, 用char編譯器報錯
    // ubuntu : 編譯不通過
    // windows: ws是ucs-2編碼: 如"國":0x56fd; 打印結果: 國家
/*     wchar_t ws[] = L"國家"; // 文件ansi編碼,ws是unicode編碼: 如國:56fd
    char *p = (char *)ws;    
    int i = 0;    
              
    wprintf(L"sizeof(ws) is %d\n", sizeof(ws));
    for (; i < sizeof(ws); i++){        
        wprintf(L"byte: %x\n", p[i]);               
    }      
    wprintf(L"wprintf content start:\n");  //必須用wprintf, 且wprintf和printf不能同時使用.
    wprintf(L"%ls\n", ws);                
    wprintf(L"content end\n");   */       
    
    while(1); //方便看結果
    return 0;          
}      
View Code

 


————————————————
版權聲明:本文為CSDN博主「xiayuleWA」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/xiayuleWA/article/details/32140493


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM