假设我有string s = "101870002PTäPO PVä #Person Tätigkeitsdarstellung 001100001&0111010101101870100092001000010"
当我做substring(30,40)
时,它会以空格开头返回“#PersonTätigkeitsdarstellung”。
我想这是计算字节而不是字符。
通常字符串的大小为110,当我执行s.length()
或s.size()
时,由于3个特殊字符,它返回113.
我想知道是否有办法在返回值的开头避免这个空格。
感谢您的帮助!
答案 0 :(得分:0)
在utf-8中,代码点(字符)ä
由两个代码单元组成(在utf-8中为1个字节)。 C ++不支持将字符串视为代码点序列。因此,就标准库而言,std::string("ä").size()
为2。
一种简单的方法是使用std::wstring
。 wstring
使用的字符类型(wchar_t
)至少与系统支持的最宽字符集一样宽。因此,如果系统支持足够宽的编码来表示具有单个代码单元的任何(非复合)unicode字符,则字符串方法将按预期运行。目前utf-32足够广泛,并且受OS(。大多数?)unix支持。
需要注意的是,Windows仅支持utf-16而不支持utf-32,因此如果您选择wstring
方法并将程序移植到Windows并且程序的用户尝试使用unicode字符,那么超过2个字节宽,则每个代码点的一个代码单元的假设不成立。
wstring
方法也不考虑控制或复合字符。
这是一个小测试代码,用于转换包含多字节utf-8字符std::string
的{{1}}并将其转换为ä
:
wstring
不幸的是,libstdc ++还没有实现{c} 11中至少从gcc-4.8引入的string foo("ä"); // read however you want
wstring_convert<codecvt_utf8<wchar_t>> converter;
wstring wfoo = converter.from_bytes(foo.data());
cout << foo.size() << endl; // 2 on my system
cout << wfoo.size() << endl; // 1 on my system
。如果你不能要求libc ++,那么类似的功能可能在Boost.Locale中。
或者,如果您希望将代码移植到不支持utf-32的系统,您可以继续使用<codecvt>
并使用外部库进行迭代和计数等。这是一个:http://utfcpp.sourceforge.net/和另一个:http://site.icu-project.org/。我相信这是推荐的方法。