VC++常用转码库
acmilan2016/05/01软件综合 IP:四川
Visual C++编写控制台程序是ANSI编码的,然而这种编码比较过时,因此编程时常与其它两种字符串打交道:
一种是宽字符,一般WinAPI、COM、.NET使用这种字符串;
一种是UTF-8,一般来自网络数据。

这几种编码之间的转换一般使用MultiByteToWideChar和WideCharToMultiByte函数。
但是这个函数使用比较麻烦,特别是UTF-8,需要分配缓冲区,转码两次,再释放掉缓冲区。

提供的常用转码函数:
to_wide ANSI转换为宽字符
from_wide 宽字符转换为ANSI
to_utf8 ANSI转换为UTF-8
from_utf8 UTF-8转换为ANSI
utf8_to_wide UTF-8转换为宽字符
utf8_from_wide 宽字符转换为UTF-8

以上函数的参数列表基本相同(均为3个),使用方法(以to_utf8为例):
int retval = to_utf8(NULL, 0, srcstr); // 返回所需缓冲区大小(以字符计)
int retval = to_utf8(outbuf, outbufsize, srcstr); // 成功返回已写入大小(以字符计),失败返回0

另有一个使用堆内存保存结果的to_utf8_alloc函数,使用方法如下:
char *result = to_utf8_alloc(srcstr);
free(result);
由于from_utf8可以安全地执行就地转换(ANSI永远比UTF-8小),没有必要提供from_utf8_alloc函数。
如果需要这个功能的话,可以使用接下来要讲到的cp_to_cp_alloc实现。

以上常用转码函数是由以下六个通用转码函数封装得到的:
cp_to_wide 指定代码页转换为宽字符
cp_from_wide 宽字符转换为指定代码页
cp_to_wide_alloc 指定代码页转换为宽字符并返回包含结果的堆内存指针
cp_from_wide_alloc 宽字符转换为指定代码页并返回包含结果的堆内存指针
cp_to_cp 转换代码页
cp_to_cp_alloc 转换代码页并返回包含结果的堆内存指针

使用示例如下所示(使用了MessageBoxW显示宽字符串,因此需要#include <windows.h>):
<code class="lang-cpp">#pragma comment(lib, "user32.lib") // MessageBoxW
                 
#include <stdio.h>
#include <stdlib.h>
#include <windows.h> // MessageBoxW
#include "../zm.h"
                 
int main()
{
    char ansi_str[] = "我是中文示例12345678";
    wchar_t wide_str[] = L"我是\u315D\u314F\uB204\uB77C12345678";
    char utf8_a[256] = "";
    char utf8_b[256] = "";
    char ansi_a[256] = "";
    char ansi_b[256] = "";
    char ansi_c[256] = "";
    wchar_t wide_a[256] = L"";
    wchar_t wide_b[256] = L"";
                 
    printf("ansi_str=%s\n", ansi_str); // 显示原始ANSI字符串
    printf("wide_str=[see MessageBox]\n");
    MessageBoxW(NULL, wide_str, L"wide_str", MB_OK); // 显示原始宽字符串
                     
    to_utf8(utf8_a, 256, ansi_str); // ANSI转码到UTF-8
    printf("utf8_a=%s [from ansi_str]\n", utf8_a);
                 
    char *utf8_alloc = to_utf8_alloc(ansi_str); // ANSI使用堆内存转码到UTF-8
    printf("utf8_alloc=%s [from ansi_str]\n", utf8_alloc);
    free(utf8_alloc);
                 
    utf8_from_wide(utf8_b, 256, wide_str); // 宽字符转码到UTF-8
    printf("utf8_b=%s [from wide_str]\n", utf8_b);
                 
    from_wide(ansi_a, 256, wide_str); // 宽字符转码到ANSI
    printf("ansi_a=%s [from wide_str]\n", ansi_a);
                  
    from_utf8(ansi_b, 256, utf8_a); // UTF-8转码到ANSI(1)
    printf("ansi_b=%s [from utf8_a]\n", ansi_b);
                 
    from_utf8(ansi_c, 256, utf8_b); // UTF-8转码到ANSI(2)
    printf("ansi_c=%s [from utf8_b]\n", ansi_c);
                 
    to_wide(wide_a, 256, ansi_str); // ANSI转码到宽字符
    printf("wide_a=[see MessageBox] [from ansi_str]\n");
    MessageBoxW(NULL, wide_a, L"wide_a [from ansi_str]", MB_OK);
                 
    utf8_to_wide(wide_b, 256, utf8_b); // UTF-8转码到宽字符
    printf("wide_b=[see MessageBox] [from utf8_b]\n");
    MessageBoxW(NULL, wide_b, L"wide_b [from utf8_b]", MB_OK);
                 
    return 0;
}</windows.h></stdlib.h></stdio.h></code>

运行结果:

Capture.png

[修改于 8年4个月前 - 2016/09/02 18:48:47]

来自:计算机科学 / 软件综合
3
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
acmilan 作者
8年8个月前 修改于 8年8个月前 IP:四川
818007
注意to_utf8, from_utf8, cp_to_cp三个函数,使用这些函数,如果先获取缓冲区大小,再分配缓冲区,再执行转换,内部会重复分配、转换、释放两次,这样效率可能比较低。
对于常用的from_utf8(UTF-8转ANSI),目标字符串(ANSI)不可能比源字符串(UTF-8)长,可以执行就地转换。
对于其它情况,如果需要使用堆内存放置结果,则应使用to_utf8_alloc或cp_to_cp_alloc函数,以避免重复分配和释放内存。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
8年8个月前 修改于 8年8个月前 IP:四川
818017
。。。现在主要精力放在.NET上面,因此此程序不再维护,如果有什么问题请自己修改
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
acmilan作者
8年8个月前 修改于 8年4个月前 IP:四川
818032
。。。。。。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
所属分类
上级专业
同级专业
acmilan
进士 学者 笔友
文章
461
回复
2934
学术分
4
2009/05/30注册,5年10个月前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:邮箱
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}