utuntu unicode打印中文

来源:互联网 发布:c语言编程器 编辑:程序博客网 时间:2024/06/07 05:30

在程序开发中,遇到unicode utf-8编码时,不能向屏幕打印中文字符的情况,经过试验测试可行的方法如下:

程序实例1:

  1. // 注意,此文档最好采用utf-8编码  
  2. #include <stdio.h>  
  3. #include <wchar.h>  
  4. #include <locale.h>  
  5.   
  6. int main()    
  7. {  
  8.     //此语句重要,在win7 + vs2012和 ubuntu 12.04测试结果一致  
  9.     //只要打印wchar_t字符,均加此语句,至少不会出错,此语句最好在程序初始化处  
  10.     setlocale(LC_ALL, "");    
  11.       
  12.   
  13.     // wprintf和printf最好不能同时使用.    
  14.     // 如下使用printf同时打印了char字符串和wchar_t字符串  
  15.     // 因此只采用printf是比较好的方法  
  16.     wchar_t ws[] = L"国家";   
  17.     printf("printf content start: %ls\n", ws);            
  18.     printf("content end\n");  
  19.   
  20.     return 0;            
  21. }        

用上面代码的原因: 

1. 从后面我的实验可以看到, 有八种组合方式, 唯独选择这么一种是有原因的.

2. wprintf 和 printf 通用会遇到莫名其妙的问题, 

3 . printf可以打印char, 使用格式为小写%s, 也可以打印wchar_t, 使用格式为%ls 或者 大写%S

4. 只要源文件编码为utf-8, 上面的代码就是跨操作系统和编译器平台的, 并且可以统一用一种方式打印char 和 wchar_t 字符串 


代码实例2:

#include <iostream>

#include <wchar.h>

using namespace std;

int main()

{

setlocale(LC_ALL,"");

wchar_t ws[]=L"中华人民共和国";

wcout<<ws<<endl;

return 0;

}

注: 需要统一使用wcout,如果前面有使用cout则为错误输出

下面为比较细节的讨论。


关于编码字符集:简单理解为,ascii码表达了美国英文字符,为一字节.

为了统一世界文字编码,出了unicode,如ucs-2,ucs-4,分别为16字节和32字节

因为历史包袱,unicode不可能完全替代以前的编码,所以出了有使用性的UTF-8编码,字节大小不定。


如何快速查看一个文字编码?如“国“字的utf-8编码是什么? 简单方法是新建一文件,记事本输入“国”, 记事本另存为,选择文件编码。 然后使用如下方式打开此文件,1:使用winhex软件 2. 使用notep++,选中文字”国“,点击菜单插件->converter->ascii to hex, 3, 其它.... (在线的就算了,我看了百度两个排名前两位的网站根本不是转的UTF-8, 而是转成了ucs-2,虽然其号称是转换成UTF-8)


如下表格是使用wchar_t的总结,其中编码格式设置是通过notepad++的格式菜单进行的,如下表格的测试代码后面会贴出来。





表格解释: 

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;            
}


其他相关参考资料

https://www.polarxiong.com/archives/ubuntu%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%AD%E8%AE%BE%E7%BD%AElocale%E4%B8%BA%E4%B8%AD%E6%96%87%E4%BB%8D%E7%84%B6%E6%97%A0%E6%95%88%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95.html

http://www.cnblogs.com/yg_zhang/p/4331498.html

http://blog.csdn.net/magicxiaoz/article/details/4347414
























阅读全文
0 0
原创粉丝点击