【发布时间】:2012-01-17 22:51:37
【问题描述】:
我正在尝试打印一串 UTF-16 字符。我不久前发布了这个问题,给出的建议是使用 iconv 转换为 UTF-32 并将其打印为 wchar_t 字符串。
我做了一些研究,并设法编写了以下代码:
// *c is the pointer to the characters (UTF-16) i'm trying to print
// sz is the size in bytes of the input i'm trying to print
iconv_t icv;
char in_buf[sz];
char* in;
size_t in_sz;
char out_buf[sz * 2];
char* out;
size_t out_sz;
icv = iconv_open("UTF-32", "UTF-16");
memcpy(in_buf, c, sz);
in = in_buf;
in_sz = sz;
out = out_buf;
out_sz = sz * 2;
size_t ret = iconv(icv, &in, &in_sz, &out, &out_sz);
printf("ret = %d\n", ret);
printf("*** %ls ***\n", ((wchar_t*) out_buf));
iconv 调用总是返回 0,所以我猜转换应该没问题?
然而,印刷似乎是偶然的。有时,转换后的 wchar_t 字符串打印正常。其他时候,它似乎在打印 wchar_t 时遇到了问题,并且完全终止了 printf 函数调用,以至于即使是尾随的“***”也不会被打印出来。
我也尝试过使用
wprintf(((wchar_t*) "*** %ls ***\n"), out_buf));
但什么都没有打印出来。
我错过了什么吗?
参考:How to Print UTF-16 Characters in C?
更新
在 cmets 中加入了一些建议。
更新代码:
// *c is the pointer to the characters (UTF-16) i'm trying to print
// sz is the size in bytes of the input i'm trying to print
iconv_t icv;
char in_buf[sz];
char* in;
size_t in_sz;
wchar_t out_buf[sz / 2];
char* out;
size_t out_sz;
icv = iconv_open("UTF-32", "UTF-16");
memcpy(in_buf, c, sz);
in = in_buf;
in_sz = sz;
out = (char*) out_buf;
out_sz = sz * 2;
size_t ret = iconv(icv, &in, &in_sz, &out, &out_sz);
printf("ret = %d\n", ret);
printf("*** %ls ***\n", out_buf);
wprintf(L"*** %ls ***\n", out_buf);
仍然是相同的结果,不是所有的 UTF-16 字符串都被打印(包括 printf 和 wprintf)。
我还能缺少什么?
顺便说一句,我使用的是 Linux,并且已经验证 wchar_t 是 4 个字节。
【问题讨论】:
-
wprintf()需要格式字符串具有L前缀,例如wprintf(L"*** %ls ***\n", out_buf). -
为什么要将输入复制到本地缓冲区
in_buf?直接用c就行了…… -
您也不能合法地将指向
char数组的指针转换为指向wchar_t的指针。输出缓冲区的类型必须为wchar_t [n]。 -
并非所有平台都对
wchar_t使用UTF-32,Win 没有。 -
在 Linux 上,您不能在同一个应用程序中混合宽 (wprintf) 和窄 (printf) 输出。第一次调用设置方向并且不能更改后记。 “一旦流具有方向,它就无法更改并持续存在,直到流关闭。”见linux.about.com/library/cmd/blcmdl3_fwide.htm 和bytes.com/topic/c/answers/…