0

我运行了相同的代码来确定宽字符串中的字符数。测试的字符串有ascii、数字和韩语。

#include <iostream>

using namespace std;

template <class T,class trait>
void DumpCharacters(T& a)
{
    size_t length = a.size();
    for(size_t i=0;i<length;i++)
    {
        trait n = a[i];
        cout<<i<<" => "<<n<<endl;
    }

    cout<<endl;
}

int main(int argc, char* argv[])
{
    wstring u = L"123abc가1나1다";
    wcout<<u<<endl;
    DumpCharacters<wstring,wchar_t>(u);

    string s = "123abc가1나1다";
    cout<<s<<endl;
    DumpCharacters<string,char>(s);

    return 0;
}

显而易见的是,Visual C++ 2010 中的 wstring.size() 返回字母的数量(11 个字符),无论它是 ascii 还是国际字符。但是,它返回 Mac OS X 中 XCode 4.2 中字符串数据的字节数(17 个字节)。

请回复我如何获取宽字符串的字符长度,而不是 xcode 中的字节数。

--- 2 月 12 日添加 --

我发现 wcslen() 在 xcode 中也返回 17。它在 vc++ 中返回 11。这是经过测试的代码:

const wchar_t *p = L"123abc가1나1다";
size_t plen = wcslen(p);

--- 添加于 2 月 18 日 --

我发现 llvm 3.0 导致长度错误。将编译器前端从 llvm3.0 更改为 4.2 后,此问题已修复

wcslen() 在 Xcode 中的工作方式不同,VC++说明了细节。

4

4 回答 4

4

如果std::wstring版本使用 17 个字符是错误的:它应该只使用 11 个字符。使用最近的 gcc 和 clang 的 SVN 头,它使用 11 个字符std::wstring和 17 个字符std::string。我认为这是预期的。

char请注意,标准 C++ 库内部对“字符”的概念与使用多字编码(例如,UTF-8 用于类型字和 UTF-16 用于 16 位字)时的预期不同. 这是描述字符串的章节的第一段(21.1 [strings.general]):

本条款描述了用于操作任何非数组 POD (3.9) 类型的序列的组件。在本条款中,此类类型称为 char-like types ,而 char-like 类型的对象称为 char-like objects 或简称为字符。

这基本上意味着,当使用 Unicode 时,各种函数不会关注代码点的构成,而是将字符串作为单词序列处理。这是严重的影响,例如在生成子字符串时会发生什么,因为这些可能很容易将多字节字符分开。目前,标准 C++ 库不支持在内部处理多字节编码,因为假定从编码到字符的转换是在读取数据时完成的(相应地,在写入数据时是另一种方式)。如果您在内部处理多字节编码字符串,则需要注意这一点,因为根本不支持。

人们认识到,这种情况实际上是一个问题。对于 C++2011,char32_t添加了字符类型,它应该比支持 Unicode 字符更好wchar_t(因为 Unicode 使用 20 位,而wchar_t只允许支持 16 位,这是在 Unicode 承诺最多使用 16 位时在某些平台上做出的选择)。但是,这仍然不能处理组合字符。C++ 委员会认识到这是一个问题,在标准 C++ 库中进行适当的字符处理将是一件好事,但到目前为止,没有人提出一个全面的建议来解决这个问题(如果你觉得你想提出这样的建议,但您不知道如何,请随时与我联系,我将帮助您如何提交建议)。

于 2012-02-11T18:18:56.440 回答
1

XCode 4.2"123abc가1나1다"在初始化string s. 该字符串的 UTF-8 表示恰好是 17 个字节长。

宽字符表示(存储在 中u)是 11 个宽字符。有很多方法可以将窄编码转换为宽编码。试试这个:

#include <iostream>
#include <clocale>
#include <cstdlib>

int main()
{
    std::wstring u = L"123abc가1나1다";
    std::cout << "Wide string containts " << u.size() << " characters\n";

    std::string s = "123abc가1나1다";
    std::cout << "Narrow string contains " << s.size() << " bytes\n";

    std::setlocale(LC_ALL, "");
    std::cout << "Which can be converted to "
              << std::mbstowcs(NULL, s.c_str(), s.size())
              << " wide characters in the current locale,\n";
}
于 2012-02-11T17:42:56.513 回答
0

使用.length(), 不.size()获取字符串长度。

于 2012-02-11T18:37:39.093 回答
0

std::string 和 std::wstring 是在 char 和 wchar_t 上模板化的 std::basic_string 的 typedef。size() 成员函数返回字符串中元素的数量 - char 或 wchar_t 的数量。"" 和 L"" 不处理编码。

于 2012-02-12T09:10:46.993 回答