Струнные сравнения. Как вы можете сравнить строку с std :: wstring? WRT strcmp - PullRequest
5 голосов
/ 07 октября 2009

Я пытаюсь сравнить два формата, которые, как я ожидал, будут в некоторой степени совместимы, поскольку оба они обычно являются строками. Я попытался выполнить strcmp со строкой и std :: wstring, и, как я уверен, гуру C ++ знают, это просто не скомпилируется. Можно ли сравнить эти два типа? Здесь есть простое преобразование?

Ответы [ 4 ]

9 голосов
/ 07 октября 2009

Вам необходимо преобразовать строку char* - "многобайтовую" на языке ISO C - в строку wchar_t* - "широкий символ" на языке ISO. Стандартная функция, которая делает это, называется mbstowcs («Строка из нескольких байтов в строку широких символов»)

ПРИМЕЧАНИЕ : как Стив указал в комментариях, это функция C99 и, следовательно, не совместимая с ISO C ++, но может поддерживаться реализациями C ++ как расширение. MSVC и g ++ поддерживают его.

Используется таким образом:

const char* input = ...;

std::size_t output_size = std::mbstowcs(NULL, input, 0); // get length
std::vector<wchar_t> output_buffer(output_size);

// output_size is guaranteed to be >0 because of \0 at end
std::mbstowcs(&output_buffer[0], input, output_size);

std::wstring output(&output_buffer[0]);

Если у вас есть два wstring с, просто сравните, как обычно. Обратите внимание, что для преобразования будет использоваться текущий языковой стандарт системы (т. Е. В Windows это будет текущая кодовая страница «ANSI») - обычно это именно то, что вам нужно, но иногда вам придется иметь дело с определенной кодировкой, и в этом случае вышеописанное не сработает, и вам нужно будет использовать что-то вроде iconv.

EDIT

Все остальные ответы, похоже, предназначены для прямой трансляции кодовой точки (т. Е. Эквивалент (wchar_t)c для каждого char c в строке). Это может не работать для всех локалей, но будет работать, если, например, все ваши char - ASCII или Latin-1, а ваши wchar_t - Unicode. Если вы уверены, что это именно то, что вам действительно нужно, самый быстрый способ - вообще избежать конверсии и использовать std::lexicographical_compare:

#include <algorithm>

const char* s = ...;
std::wstring ws = ...;

const char* s_end = s + strlen(s);

bool is_ws_less_than_s = std::lexicographical_compare(ws.begin, ws.end(),
                                                      s, s_end());
bool is_s_less_than_ws = std::lexicographical_compare(s, s_end(),
                                                      ws.begin(), ws.end());
bool is_s_equal_to_ws = !is_ws_less_than_s && !is_s_less_than_ws;

Если вам необходимо проверить равенство, используйте std::equal с проверкой длины:

#include <algorithm>

const char* s = ...;
std::wstring ws = ...;

std::size_t s_len = strlen(s);
bool are_equal =
    ws.length() == s_len &&
    std::equal(ws.begin(), ws.end(), s);
2 голосов
/ 07 октября 2009

Прежде всего, вы должны спросить себя, почему вы используете std :: wstring, который представляет собой формат Unicode с char * (cstring), который является ansi. Рекомендуется использовать Unicode, поскольку он позволяет интернационализировать ваше приложение, но в большинстве случаев использование микса не имеет особого смысла. Если вы хотите, чтобы ваши строки были в юникоде, используйте wchar_t . Если вы хотите, чтобы ваши строки STL были ANSI, используйте std :: string.

Теперь вернемся к вашему вопросу.

Первое, что вы хотите сделать, - конвертировать один из них в другой тип данных.

std::string и std::wstring имеют функцию c_str

вот определения функций

const char* std::string::c_str() const
const wchar_t* std::wstring::c_str() const

Я не помню, как вручную конвертировать char * в wchar_t * и наоборот, но после этого вы можете использовать strcmp. Если вы Google, вы найдете способ.

Вы можете использовать функции ниже для преобразования std :: wstring в std :: string, тогда c_str выдаст вам char *, который вы можете strcmp

#include <string>
#include <algorithm>

// Prototype for conversion functions
std::wstring StringToWString(const std::string& s);
std::string WStringToString(const std::wstring& s);

std::wstring StringToWString(const std::string& s)
{
std::wstring temp(s.length(),L' ');
std::copy(s.begin(), s.end(), temp.begin());
return temp; 
}


std::string WStringToString(const std::wstring& s)
{
std::string temp(s.length(), ' ');
std::copy(s.begin(), s.end(), temp.begin());
return temp; 
}
2 голосов
/ 07 октября 2009

Быстрый и грязный путь -

if( std::wstring(your_char_ptr_string) == your_wstring)

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

Обратите внимание, что wstring использует 16-битные символы (т. Е. Unicode - 65536 возможных символов), тогда как char * имеет тенденцию быть 8-битными символами (Ascii, только латинский английский). Они не одинаковы, поэтому wstring -> char * может потерять точность.

-Tom

2 голосов
/ 07 октября 2009

Преобразуйте ваш wstring в строку.

wstring a = L"foobar";
string  b(a.begin(),a.end());

Теперь вы можете сравнить его с любым символом *, используя b.c_str () или что угодно.

char c[] = "foobar";
cout<<strcmp(b.c_str(),c)<<endl;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...