substr用字符而不是字节

时间:2014-08-04 10:08:06

标签: c++ string substring special-characters substr

假设我有string s = "101870002PTäPO PVä #Person Tätigkeitsdarstellung 001100001&0111010101101870100092001000010"

当我做substring(30,40)时,它会以空格开头返回“#PersonTätigkeitsdarstellung”。 我想这是计算字节而不是字符。

通常字符串的大小为110,当我执行s.length()s.size()时,由于3个特殊字符,它返回113.

我想知道是否有办法在返回值的开头避免这个空格。

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

在utf-8中,代码点(字符)ä由两个代码单元组成(在utf-8中为1个字节)。 C ++不支持将字符串视为代码点序列。因此,就标准库而言,std::string("ä").size()为2。

一种简单的方法是使用std::wstringwstring使用的字符类型(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/。我相信这是推荐的方法。