我正在编写一个应该包装任意unicode文本的终端(控制台)应用程序.
终端通常使用等宽(固定宽度)字体,因此要包装文本,它只是计算字符数并观察单词是否适合某行并相应地采取行动.
问题是Unicode表中有全宽字符占用终端中2个字符的宽度.
计算这些将看到1个unicode字符,但打印的字符是2个"正常"(半宽)字符宽,打破了包装程序,因为它不知道占用两倍宽度的字符.
例如,这是一个全角字符(U + 3004,JIS符号)
? 12
它虽然预先格式化,但它不占用2个字符的全宽,但它确实使用了终端中西方字符宽度的两倍.
为了解决这个问题,我必须区分全宽或半宽字符,但我找不到在C++中这样做的方法.是否真的有必要知道unicode表中的所有全角字符来解决问题?
您应该将ICU u_getIntPropertyValue与UCHAR_EAST_ASIAN_WIDTH财产一起使用.
例如:
bool is_fullwidth(UChar32 c) {
int width = u_getIntPropertyValue(c, UCHAR_EAST_ASIAN_WIDTH);
return width == U_EA_FULLWIDTH || width == U_EA_WIDE;
}
Run Code Online (Sandbox Code Playgroud)
请注意,如果您的图形库支持组合字符,那么在确定序列使用的单元数时,您还必须考虑这些因素.例如e,U+0301COMBINING ACUTE ACCENT 后面只占用1个单元格.
不需要建表,Unicode 的人已经这么做了:
http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
相同的代码用于终端仿真软件,例如xterm[1]、konsole[2]以及很可能的其他软件......