zoukankan      html  css  js  c++  java
  • 控制台输出宽字符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 ", 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
    ", sizeof(ws));
        for (; i < sizeof(ws); i++){  
            printf("byte: %x
    ", p[i]);    
        }
        printf("content start
    ");   
        printf("%s
    ", ws);
        printf("content end
    ");        */  
     
            /******************  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
    ", sizeof(ws));
        for (; i < sizeof(ws); i++){
            printf("byte: %x
    ", p[i]);        
        }
        printf("content start: %s
    ", ws);      
        printf("content end
    ");  */   
        
        
          /******************  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
    ", sizeof(ws));
        for (; i < sizeof(ws); i++){  
            wprintf(L"byte: %x
    ", p[i]);               
        }    
        wprintf(L"wprintf content start:
    ");  //必须用wprintf, 且wprintf和printf不能同时使用.
        wprintf(L"%ls
    ", ws);                
        wprintf(L"content end
    ");    */          
        
            /******************  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
    ", sizeof(ws));
        for (; i < sizeof(ws); i++){  
            printf("byte: %x
    ", p[i]);               
        }        
     
        printf("printf content start:
    ");  //wprintf和printf不能同时使用.
        printf("%ls
    ", ws);                
        printf("content end
    ");
     
        /******************  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
    ", sizeof(ws));
        for (; i < sizeof(ws); i++){        
            wprintf(L"byte: %x
    ", p[i]);               
        }      
        wprintf(L"wprintf content start:
    ");  //必须用wprintf, 且wprintf和printf不能同时使用.
        wprintf(L"%ls
    ", ws);                
        wprintf(L"content end
    ");   */       
        
        while(1); //方便看结果
        return 0;          
    }      
    View Code


    ————————————————
    版权声明:本文为CSDN博主「xiayuleWA」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/xiayuleWA/article/details/32140493

    常记溪亭日暮,沉醉不知归路。兴尽晚回舟,误入藕花深处。争渡,争渡,惊起一滩鸥鹭。

    昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否?知否?应是绿肥红瘦。
  • 相关阅读:
    党报
    一个人只有敢于承担责任,才有可能被赋予更大的责任。做不
    勇于担当:好男人的三块责任田——
    关于担当
    领导干部要勇于担当
    福布斯专访阿里蔡崇信:马云的坚持和改变
    阿里股权
    ContentProvider
    搞笑段子
    报业
  • 原文地址:https://www.cnblogs.com/htj10/p/12112603.html
Copyright © 2011-2022 走看看