具体来说,给出以下内容:
我可以计算字符串的长度,减去尾随空格/制表符,而不是先实际将其转换为ICU的内部编码,然后转换回来吗? (由于unicode规范化,这本身可能会有问题。)
对于某些编码,例如任何基于ascii的编码以及utf-8/16/32,解决方案非常简单,只需从字符串的后面进行迭代,每次比较1/2/4字节两个常数。
对于其他人来说,它可能会更难(可变长度编码会浮现在脑海中)。我希望这样做尽可能高效。
答案 0 :(得分:6)
对于大量编码,以及有限的U+0020 SPACE
和HORIZONTAL TAB U+0009
,这非常简单。
在ASCII,单字节Windows代码页和单字节ISO代码页中,这些字符都具有相同的值。只要值为9或32,您就可以简单地逐字节地工作,将它们关闭。
这种方法也适用于UTF-8,它具有很好的属性,即小于128的字节始终是ASCII字符。你不必怀疑它是一个前导字节还是一个连续字节,因为它们总是设置高位。
给定UTF-16,你一次工作两个字节,寻找0x0009和0x0020,小心处理字节顺序。与UTF-8一样,UTF-16具有很好的属性,如果你看到这个值,你不必怀疑它是否是代理对的一部分,因为它们总是具有不同的值。
有问题的情况是可变字节编码,它们无法保证给定单位是唯一的。如果您看到一个值为9的字节,则不一定知道它是一个制表符还是来自多字节编码的随机字节。但是,即使对于其中一些,您关注的特定值(9和32)也许是唯一的。例如,查看Windows code page 950,似乎前导字节具有较高的值集,并且尾部字节避开较低的值(需要大量检查才能绝对确定)。因此,对于您的有限情况,这可能就足够了。
对于从绝对任何编码中剥离任意字符集的一般问题,您需要根据该编码的规则解析字符串(以及了解所有字符映射)。对于一般情况,几乎可以肯定最好将字符串转换为某种Unicode编码,进行修剪,然后转换回来。如果您小心使用K规范化表格,则应正确往返。
答案 1 :(得分:1)
我使用相当简单的STL方法:
std::string mystring;
mystring.erase(mystring.find_last_not_of(" \n\r\t")+1);
到目前为止,这似乎对我的所有需求都有效(你的里程可能会有所不同),但经过多年使用它似乎可以完成这项工作:)
如果您需要更多信息,请告诉我们。)
答案 2 :(得分:0)
如果将“任意编码”要求限制为“使用相同代码值的空格和制表符的任何编码ascii”,这仍然相当普遍,您甚至根本不需要ICU。你需要的就是boost :: trim_right或boost :: trim_right_if。
http://www.boost.org/doc/libs/1_55_0/doc/html/string_algo/usage.html#idp206822440