char和wchar_t的关系以及wprintf的应用

算法 Linux linux
内存里的wchar_t和char
字符串存储是转换成对应的编码按16进制字节存储
可以通过查看内存中存储的字节了解字符串对应的编码

#include <cstdio>
#include <cstdlib>
#include <clocale>
#include <cwchar>
#include <cstring>
// g++ demo.cpp (UTF-8编码)
int main(int argc, char * argv[])
{
    int i = 0;
    wchar_t wstr[] = L"中文";   // unicode 
    setlocale(LC_ALL, "zh_CN.UTF-8");       
    wprintf(L"\nwchar_t(%S)\n", wstr);
    char *ch = (char*)wstr;
    for(i=0; i<10; i++){
        wprintf(L"%p = 0x%02x\n", ch+i, (unsigned char)ch[i]);
    }

    char chstr[] = "中文"; // utf-8
    wprintf(L"\nchar(%s) :", chstr);
    wprintf(L"\n");
    ch = (char*)chstr;
    for(i=0; i<10; i++){
        wprintf(L"%p = 0x%02x\n", ch+i, (unsigned char)ch[i]);
    }
    wprintf(L"\n");
    return 0;
}

这里写图片描述
“中文”的编码 (Unicode : 2D 4E 87 65), (UTF-8 : E4 B8 AD E6 96 87 )
打印出内存中对于wchar_t和char的存储情况可以看到
wchar_t对应的是Unicode编码,而char对应的则是utf-8编码(因为CPP文件本身就是utf-8编码)

wchar_t数据类型一般为16位或32位,但不同的C或C++库有不同的规定,如GNU Libc规定wchar_t为32位
总之,wchar_t所能表示的字符数远超char型
win32 中wchar_t为16位 Linux中是32位
下面分别在64位系统和32位系统中运行结果
无论在64位系统还是32位中 wchar_t占用的字节数都是4字节(32位)
这里写图片描述

setlocale的作用
当向终端 控制台输出wchar_t类型的字符时,需要设置setlocale
因为通常终端、控制台环境自身是不支持UCS系列的字符集编码的,
使用流操作函数时(printf),在标准/RT库实现的内部会将UCS字符转换成合适的本地ANSI编码字符,
转换的依据就是setlocale设定的活动locale,最后将结果字符序列传递给终端

可以注释掉setlocale函数的调用,输出情况就是这样:
这里写图片描述

下面看看输出-N的情况
把输出的%S换成%s
把第12行换成 wprintf(L”\nwchar_t(%s)\n”, wstr);
这里写图片描述
这是因为ascii码表中(0x2D对应减号/破折号-), (0x4E对应大写字母N),刚好是在ascii系列编码的范围内(0-127)
不符合utf-8的编码规则 所以以ascii的标准输出字符串
那么就是说 %s 是按照char的格式输出字符串内容 刚好遇到后面的0x00结束字符串。

wchar_t和char的相互转换
UTF-8就是在互联网上使用最广的一种unicode的实现方式
他们之间的转换算法是固定的 所以Linux系统也提供了API(wcstombs和mbstowcs)供开发者直接调用转换
windows下面提供的API是MultiByteToWideChar和WideCharToMultiByte
转换规则可以查看 http://blog.csdn.net/dreamintheworld/article/details/77697914

#include <cstdio>
#include <cstdlib>
#include <clocale>
#include <cwchar>
#include <cstring>
// g++ demo.cpp (UTF-8编码) wchar_t 转 char
int main(int argc, char * argv[]){
    int i = 0;
    wchar_t wstr[] = L"中文";   // unicode 
    setlocale(LC_ALL, "zh_CN.UTF-8");       
    wprintf(L"\nwchar_t(%S)\n", wstr);
    char *ch = (char*)wstr;
    for(i=0; i<10; i++){
        wprintf(L"%p = 0x%02x\n", ch+i, (unsigned char)ch[i]);
    }

    char result[56];
    if(wcstombs(result, wstr, 56) < 0){
        printf("failed\n");
        return 0;
    }
    int len = strlen(result);
    i=0;
    wprintf(L"\nchar(%s) : ", result);
    for(i=0; i<len; i++){
        wprintf(L"0x%02x ", (unsigned char)result[i]);
    }
    wprintf(L"\n\n");
    return 0;
}

这里写图片描述

#include <cstdio>
#include <cstdlib>
#include <clocale>
#include <cwchar>
#include <cstring>
// g++ demo.cpp   char 转 wchar_t
int main(int argc, char * argv[]){
    int i = 0;
    char chstr[] = "中文"; // utf-8
    setlocale(LC_ALL, "zh_CN.UTF-8");     
    wprintf(L"\nchar(%s) : ", chstr);
    wprintf(L"\n");
    char *ch = (char*)chstr;
    for(i=0; i<10; i++){
        wprintf(L"%p = 0x%02x\n", ch+i, (unsigned char)ch[i]);
    }
    wprintf(L"\n");
    wchar_t w_result[56];
    if(mbstowcs(w_result, chstr, 56) < 0){
        printf("failed\n");
        return 0;
    }
    int len = 10;
    i=0;
    wprintf(L"\nwchar_t(%S) : \n", w_result);
    ch = (char*)w_result;
    for(i=0; i<len; i++){
        wprintf(L"%p = 0x%02x\n", ch+i, (unsigned char)ch[i]);
    }
    wprintf(L"\n\n");
    return 0;
}

这里写图片描述

优质链接
http://club.topsage.com/thread-2227977-1-1.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值