Сравните std :: wstring и std :: string

Как сравнить string wstring , такую ​​как L"Hello" , с string ? Если мне нужно иметь тот же тип, как я могу преобразовать их в один тип?

Поскольку вы спросили, вот мои стандартные функции преобразования из строки в широкую строку, реализованные с использованием classов C ++ std::string и std::wstring .

Прежде всего, обязательно запустите свою программу с помощью set_locale :

 #include  int main() { std::setlocale(LC_CTYPE, ""); // before any string operations } 

Теперь о функциях. Прежде всего, получив широкую строку из узкой строки:

 #include  #include  #include  #include  #include  #include  // Dummy overload std::wstring get_wstring(const std::wstring & s) { return s; } // Real worker std::wstring get_wstring(const std::string & s) { const char * cs = s.c_str(); const size_t wn = std::mbsrtowcs(NULL, &cs, 0, NULL); if (wn == size_t(-1)) { std::cout << "Error in mbsrtowcs(): " << errno << std::endl; return L""; } std::vector buf(wn + 1); const size_t wn_again = std::mbsrtowcs(buf.data(), &cs, wn + 1, NULL); if (wn_again == size_t(-1)) { std::cout << "Error in mbsrtowcs(): " << errno << std::endl; return L""; } assert(cs == NULL); // successful conversion return std::wstring(buf.data(), wn); } 

И возвращаясь, делая узкую цепочку из широкой струны. Я называю узкую строку «locale string», потому что она находится в зависящей от платформы кодировке в зависимости от текущей локали:

 // Dummy std::string get_locale_string(const std::string & s) { return s; } // Real worker std::string get_locale_string(const std::wstring & s) { const wchar_t * cs = s.c_str(); const size_t wn = std::wcsrtombs(NULL, &cs, 0, NULL); if (wn == size_t(-1)) { std::cout << "Error in wcsrtombs(): " << errno << std::endl; return ""; } std::vector buf(wn + 1); const size_t wn_again = std::wcsrtombs(buf.data(), &cs, wn + 1, NULL); if (wn_again == size_t(-1)) { std::cout << "Error in wcsrtombs(): " << errno << std::endl; return ""; } assert(cs == NULL); // successful conversion return std::string(buf.data(), wn); } 

Некоторые примечания:

  • Если у вас нет std::vector::data() , вы можете сказать &buf[0] .
  • Я обнаружил, что функции преобразования r стиля mbsrtowcs и wcsrtombs не работают должным образом в Windows. mbstowcs этого вы можете использовать mbstowcs и wcstombs : mbstowcs(buf.data(), cs, wn + 1); , wcstombs(buf.data(), cs, wn + 1);

В ответ на ваш вопрос, если вы хотите сравнить две строки, вы можете преобразовать их оба в широкую строку, а затем сравнить их. Если вы читаете файл с диска с известной кодировкой, вы должны использовать iconv() чтобы преобразовать файл из вашей известной кодировки в WCHAR, а затем сравнить с широкой строкой.

Остерегайтесь, однако, что сложный текст Юникода может иметь несколько разных представлений как последовательности кодовых точек, которые вы можете считать равными. Если это возможно, вам необходимо использовать библиотеку обработки Юникода более высокого уровня (например, ICU) и нормализовать ваши строки в какую-то общую, сопоставимую форму.

Вы должны преобразовать строку char строку wchar_t используя mbstowcs , а затем сравнить полученные строки. Обратите внимание, что mbstowcs работает на char * / wchar * , поэтому вам, вероятно, понадобится сделать что-то вроде этого:

 std::wstring StringToWstring(const std::string & source) { std::wstring target(source.size()+1, L' '); std::size_t newLength=std::mbstowcs(&target[0], source.c_str(), target.size()); target.resize(newLength); return target; } 

Я не совсем уверен, что использование &target[0] полностью соответствует стандарту, если у кого-то есть хороший ответ на это, пожалуйста, скажите мне в комментариях. Кроме того, существует неявное предположение, что преобразованная строка будет не длиннее (в количестве wchar_t s), чем количество char s исходной строки – логическое предположение, что я все еще не уверен, что это покрывается стандартом.

С другой стороны, кажется, что нет способа запросить mbstowcs размер необходимого буфера, так что либо вы идете по этому пути, либо идете с кодом (лучше сделанным и лучше определенным) из Unicode-библиотек (будь то Windows API или библиотеки Windows как iconv).

Тем не менее, имейте в виду, что сравнение строк Unicode без использования специальных функций является скользкой землей, две эквивалентные строки могут оцениваться по-разному, если сравнивать поразрядные.

Короче говоря: это должно сработать, и я думаю, что это максимум, который вы можете сделать только с стандартной библиотекой, но это зависит от реализации, как работает Unicode, и я бы не стал им доверять. В общем, лучше всего придерживаться кодировки внутри вашего приложения и избегать такого рода конверсий, если это абсолютно необходимо, и, если вы работаете с определенными кодировками, используйте API, которые не зависят от реализации.

Подумайте дважды, прежде чем делать это – вы, возможно, не захотите сравнивать их в первую очередь. Если вы уверены, что делаете это, и используете Windows, то конвертируйте string в wstring с помощью MultiByteToWideChar , а затем сравните с CompareStringEx .

Если вы не используете Windows, то аналогичными функциями являются mbstowcs и wcscmp . Стандартные широкоформатные функции C ++ часто не переносятся под Windows; например, mbstowcs устарел.

Кросс-платформенный способ работы с Unicode – использовать библиотеку ICU .

Постарайтесь использовать специальные функции для сравнения строк в Юникоде, не делайте этого вручную. Две строки Unicode могут иметь разные символы, но все равно быть одинаковыми.

 wstring ConvertToUnicode(const string & str) { UINT codePage = CP_ACP; DWORD flags = 0; int resultSize = MultiByteToWideChar ( codePage // CodePage , flags // dwFlags , str.c_str() // lpMultiByteStr , str.length() // cbMultiByte , NULL // lpWideCharStr , 0 // cchWideChar ); vector result(resultSize + 1); MultiByteToWideChar ( codePage // CodePage , flags // dwFlags , str.c_str() // lpMultiByteStr , str.length() // cbMultiByte , &result[0] // lpWideCharStr , resultSize // cchWideChar ); return &result[0]; } 
  • Реализация алгоритма Хой Шамоса с помощью C #
  • Возrotation константной ссылки на локальную переменную из функции
  • Полиморфизм C ++ без указателей
  • Как получить список открытых дескрипторов файлов по процессу на C #?
  • XAML GridView ItemTemplate не привязывается к управлению
  • Функция преобразования для проверки ошибок считается хорошей?
  • Как создать функцию шаблона внутри classа? (C ++)
  • Как вы тестируете ASP.NET Core MVC Controllers, которые возвращают анонимные объекты?
  • Как создать динамическое событие нажатия кнопки на динамической кнопке?
  • Почему конструкторы не наследуются?
  • Почему оператор условного оператора является ассоциативным?
  • Interesting Posts

    Сложность времени рекурсивного алгоритма

    Добавить два целых числа, используя только побитовые операторы?

    Как проверить, является ли элемент вне экрана

    Как я могу изменить действия панели действий динамически?

    Изменение уровня API Android Studio

    Как использовать javaFX Preloader с автономным приложением в Eclipse?

    MS Office 2007 – изменение языка отображения пользовательского интерфейса с немецкого языка на английский

    Стеганографическое программное обеспечение

    Найти похожие сообщения в Outlook 2010 с новым / всплывающим окном, как в 2007 году

    Зачем использовать Fragment # setRetainInstance (boolean)?

    javafx, обновить ui из другого streamа

    Планирование задания с помощью Spring программно (с динамическим набором fixedRate)

    PDF – удаление ограничений использования

    Условное форматирование Excel 2010: выборочное выделение дубликатов

    Список функций и версии языка Delphi, в которых они были введены / устарели

    Давайте будем гением компьютера.