【发布时间】:2012-03-08 16:33:12
【问题描述】:
在使用 sprintf() 等 C 标准库格式化函数处理包含非 ASCII 字符的 UTF-8 字符串时,我发现了一个有趣的问题:
printf() 系列的函数不知道 utf-8 并根据字节数而不是字符来处理所有内容。因此格式不正确。
简单示例:
#include <stdio.h>
int main(int argc, char *argv[])
{
const char* testMsg = "Tääääßt";
char buf[1024];
int len;
sprintf(buf, "|%7.7s|", testMsg);
len = strlen(buf);
printf("Result=\"%s\", len=%d", buf, len);
return 0;
}
结果是:
Result="|Täää|", len=7
很可能你们中的一些人会建议将应用程序从 char 转换为 wchar_t 并使用 fwprintf() 等,但由于现有应用程序庞大,这绝对是不可能的。我可以想象编写一个在内部使用这些函数的包装器,但这会很棘手而且效率很低。
因此,最好的解决方案是使用 UTF-8 感知替代标准 C 库的格式化函数。
目前我正在开发 QNX 6.4,但回复其他操作系统。例如Linux,也很受欢迎。
【问题讨论】:
-
您的示例输出省略了前导 '|'性格,这似乎不太可能反映真实发生的事情。
-
@unwind 你是对的,谢谢。固定。
-
您能否使用 Unicode 库(如 flexiguided.de/publications.utf8proc.en.html)并提供
printfUnicode 字符串的字节数? -
只是一个警告,计算 Unicode 数据中的“字符”是一项相当复杂的工作。除了 UTF-8 中的每个代码点由几个字节组成的事实之外,每个字形(或“字形”)可以由多个代码点组成,因此
fwprintf无论如何都不足以截断 Unicode 数据——因为例如,您可以切断重音而不切断它适用的字符。所以无论你最终使用什么,确保你指定的长度的含义对你来说是清楚的。