Как сравнить std::wstring и char*?

Что я имею:

  • [wstr1] 1 значение std::wstring (например, "(GMT+04:30) Кабул")
  • [str2] 1 char* заполнен теми же данными, что и std::wstring (с тем же текстом)

Я просто пытаюсь сравнить эти два значения, но следующий код не работает. КМП.

Вот конвертер из char* в std::wstring,

std::wstring TimeZone::TimeZone::char2ws(const char* src)
{
    /* Convert to a wchar_t*
     * http://msdn.microsoft.com/en-us/library/ms235631(v=vs.80).aspx
     */

    // Convert to a wchar_t*
    size_t origsize = strlen(src) + 1;
    const size_t newsize = 512;
    size_t convertedChars = 0;
    wchar_t wcstring[newsize];
    mbstowcs_s(&convertedChars, wcstring, origsize, src, _TRUNCATE);

    return wcstring;
}

после этого я сделал простое сравнение с

// wstr1 is std::wstring, with "(GMT+04:30) Kabul" string
// wstr2 = char2ws(str2), 
return (wstr1 == wstr2);

И не повезло. Строки в отладчике IDE VSVC2008 визуально равны.

Вопрос: почему метод сравнения всегда дает мне false?

Спасибо.


Решение: большое спасибо Alexandre C.

bool weirdEquals(const std::wstring& str, char const* c)
{
    std::string c_str(c);
    if (str.size() < c_str.size())
    {
        return false;
    }
    return std::equal(c_str.begin(), c_str.end(), str.begin());
}

PS. Я внес некоторые изменения.


person mosg    schedule 21.02.2011    source источник
comment
wcstring[] - это переменная стека, как вы можете ее вернуть? Вам не хватает финального '\ 0'? Почему вы не проверяете код ошибки из mbstowcs_s?   -  person James    schedule 21.02.2011
comment
Он возвращает std::wstring по значению, а не по ссылке на массив.   -  person Erik    schedule 21.02.2011
comment
@James Почему вы не проверяете код ошибки из mbstowcs_s? Errno равно 0, это означает, что ошибок нет, беседа прошла успешно.   -  person mosg    schedule 21.02.2011


Ответы (3)


Сравните так, если вы уверены, что у вас есть только символы ASCII. В противном случае вы можете передать пользовательский (зависящий от локали?) компаратор в std::equal.

bool weirdEquals(char const* c, size_t n, const std::wstring& str)
{
    if (str.size() < n) return false;
    return std::equal(c, c + n, str.begin());
}
person Alexandre C.    schedule 21.02.2011

Чтобы сравнить строки, вам нужно сравнить их по одному и тому же набору символов. wchar_t и char явно используют разные наборы символов, поэтому вы не можете сравнивать их, используя обычное сравнение строк char-for-char.

Как правило, вы должны преобразовать строку char* в строку wchar_t* (используя mbtowcs или MultiByteToWideChar), чтобы вы могли сравнить их как строки Unicode, как вы это делаете.

Но я подозреваю, что в вашем случае вы ожидаете совпадения только простых символов ASCII, и в этом случае вы можете выполнить сравнение символов, сравнивая wchar_ts с chars. Примечание: не используйте для этого приведение типов.

Что касается того, почему ваше преобразование не работает, см. Ответ @Erik.

person tenfour    schedule 21.02.2011

Вам нужно передать newsize, а не origsize, в mbstowcs_s.

Также рассмотрите возможность использования:

wchar_t wcstring[newsize] = { 0 };
person Erik    schedule 21.02.2011
comment
Спасибо, но вам нужно передать размер newsize, а не origsize, в mbstowcs_s. это меня немного сбивает с толку... Официальный MSDN msdn.microsoft.com/en-us/library/ms235631(v=vs.80).aspx печально, что в mbstowcs_s должно быть значение origsize, нет? wchar_t wcstring[newsize] = { 0 }; — не помогает - person mosg; 22.02.2011