我在使用C标准库格式化函数(如sprintf())处理包含非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;
}
Run Code Online (Sandbox Code Playgroud)
结果是:
Result="|Täää|", len=7
Run Code Online (Sandbox Code Playgroud)
很可能你们中的一些人会建议将应用程序从char转换为wchar_t并使用fwprintf()等,但由于现有的巨大应用程序,这绝对是不可能的.我可以想象编写一个在内部使用这些函数的包装器,但这会非常棘手并且非常低效.
因此,最好的解决方案是替换标准C库的格式化功能的UTF-8.
目前我正在研究QNX 6.4,但回复其他操作系统.例如Linux,也非常受欢迎.
好吧,一旦你要求printf对Unicode字符进行智能填充,就会遇到重大问题.正如他们所说,
w͢͢͝h͡o͢͢͡͡k̵͟n̴͘ǫw̸̛s͘w̧̕a҉̡͢ţ̕ho̵r͏̵rors̡̡lį̶e͟͟͟͟in͢͢t̕h̷̡͟e͟͟d̛a͜r̕͡k̢̨̢̨h̴e͏a̷̢̡rt͏͏̴̷̵̶̵̶̸̸̷̧̧̛̛̛͘͘͜͜͜͠͏̷͏̡̡̡͝͝͝͞͞
有多少个Unicode字符Tääääßt?好吧,它可以是7到11之间的任何位置,具体取决于它的编码方式.每个ä都可以写成U + 00E4,这是一个字符,或者它可以写成U + 0061 U + 0308,这是两个字符.所以你的下一个希望是计算字形集群.(不,标准化不会使问题消失.)
但是,字形簇有多宽?显然,a是一列宽.U + 200B应为零列宽,这是一个"零宽度"空间.每个ひらがな应该是两列宽吗?它们通常位于终端仿真器中.将ひらがな格式化为7列时会发生什么,你得到了"??? ",这会增加一个空间,或者你得到了"???",这只是6列?
如果您剪切混合了RTL和LTR文本的内容,您是否应该重新设置文本方向?你会怎样做?(某些终端模拟器,例如Apple的,支持从左到右和从右到左文本的混合.)
截断文字的目的是什么?您是在尝试向用户显示有限空间中的字符串,还是在尝试编写使用固定宽度字段的格式?
基本上,如果你想将Unicode文本剪切成块,你不应该用简单的东西printf(或者wprintf,这可能更糟)来做.使用LibICU(网站)迭代您想要的休息时间.编写一个支持UTF-8的版本printf就是要求你不想要的各种麻烦.
| 归档时间: |
|
| 查看次数: |
5179 次 |
| 最近记录: |