wstring.size () работает по-разному в xcode или Visual C ++ - PullRequest
0 голосов
/ 11 февраля 2012

Я запустил тот же код, который определяет количество символов в строке широких символов.Тестируемая строка имеет 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;
}

Очевидным является то, что wstring.size () в Visual C ++ 2010 возвращает количество букв (11 символов), независимо от того, является ли оно символом ascii или международным.Однако он возвращает количество байтов строковых данных (17 байтов) в XCode 4.2 в Mac OS X.

Пожалуйста, ответьте мне, как получить длину символа строки широких символов, а не количество байтов в xcode.

--- добавлено 12 февраля -

Я обнаружил, что wcslen () также возвращает 17 в xcode.он возвращает 11 в vc ++.Вот проверенный код:

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

--- добавлено 18 февраля -

Я обнаружил, что llvm 3.0 вызывает неправильную длину.Эта проблема исправлена ​​после изменения внешнего интерфейса компилятора с llvm3.0 на 4.2

wcslen () работает по-разному в Xcode и VC ++ сообщает подробности.

Ответы [ 4 ]

4 голосов
/ 11 февраля 2012

Это ошибка, если версия std::wstring использует 17 символов: она должна использовать только 11 символов.Используя последние SVN-главы gcc и clang, он использует 11 символов для std::wstring и 17 символов для std::string.Я думаю, что это то, что ожидалось.

Обратите внимание, что стандартная библиотека C ++ внутренне имеет другое представление о том, что такое «символ», чем то, что можно ожидать при кодировании из нескольких слов (например, UTF-8 для словвведите char и UTF-16 для слов с 16 битами).Вот первый абзац главы, описывающей строку (21.1 [strings.general]):

В этом разделе описываются компоненты для манипулирования последовательностями любого типа, не являющегося массивом POD (3.9).В этом разделе такие типы называются символоподобными типами, а объекты типоподобных типов называются символоподобными объектами или просто символами.

Это в основном означает, что при использовании Unicode различные функции не будет обращать внимание на то, что составляет кодовую точку, а скорее обрабатывать строки как последовательность слов.Это серьезные последствия и то, что произойдет, например, при создании подстрок, поскольку они могут легко разделить многобайтовые символы.В настоящее время стандартная библиотека C ++ не поддерживает внутреннюю обработку многобайтовых кодировок, поскольку предполагается, что преобразование из кодировки в символы выполняется при чтении данных (и, соответственно, при записи данных происходит иначе).Если вы обрабатываете многобайтовые кодированные строки внутренне, вы должны знать об этом, поскольку вообще никакой поддержки нет.

Признано, что такое положение вещей на самом деле является проблемой.В C ++ 2011 был добавлен символьный тип char32_t, который должен поддерживать символ Unicode по-прежнему лучше, чем wchar_t (потому что Unicode использует 20 бит, в то время как wchar_t было разрешено поддерживать только 16 бит, что выбирается на некоторых платформах ввремя, когда Unicode обещал использовать максимум 16 бит).Однако это все равно не касается совмещения персонажей.Комитет C ++ признает, что это проблема, и что правильная обработка символов в стандартной библиотеке C ++ была бы полезной, но пока никто не выступит с комплексным предложением по решению этой проблемы (если вы считаете, что хотитепредложить что-то вроде этого, но вы не знаете, как, пожалуйста, не стесняйтесь связаться со мной, и я помогу вам, как подать предложение).

1 голос
/ 11 февраля 2012

XCode 4.2 очевидно использовал UTF-8 (или что-то очень похожее) в качестве узкой многобайтовой кодировки для представления строкового литерала символов "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";
}
0 голосов
/ 12 февраля 2012

std :: string и std :: wstring являются определениями типов std :: basic_string, шаблонными для char и wchar_t.Функция-член size () возвращает количество элементов в строке - количество символов char или wchar_t."" и L "" не имеют дело с кодировками.

0 голосов
/ 11 февраля 2012

Используйте .length(), а не .size(), чтобы получить длину строки.

...