Неожиданные результаты с преобразованием строк wchar_t и c_str

На основе этот ответ на связанный вопрос, я попытался написать метод, который преобразует стандартную строку в широкую строку, которую я затем могу преобразовать в wchar_t *.

Почему нет двух разных способов создания эквивалента wchar_t *? (Я показал значения, которые дает мне мой отладчик).

TEST_METHOD(TestingAssertsWithGetWideString)
{
std::wstring wString1 = GetWideString("me");
const wchar_t* wchar1 = wString1.c_str(); // wchar1 = "me"const wchar_t* wchar2 = GetWideString("me").c_str(); // wchar2 = "ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ@" (Why?!)
}

где GetWideString определяется следующим образом:

inline const std::wstring GetWideString(const std::string &str)
{
std::wstring wstr;
wstr.assign(str.begin(), str.end());

return wstr;
};

Примечание: следующее тоже не работает.

const wchar_t* wchar2 = GetWChar("me");

const wchar_t *GetWChar(const std::string &str)
{
std::wstring wstr;
wstr.assign(str.begin(), str.end());

return wstr.c_str();
};

0

Решение

Каждый раз, когда вы звоните GetWideString()Вы создаете новый std::wstring, который имеет недавно выделенный буфер памяти. Вы сравниваете указатели на разные блоки памяти (если Assert::AreEqual() просто сравнивая указатели сами, а не содержание блоков памяти, на которые указывают).

Обновить: const wchar_t* wchar2 = GetWideString("me").c_str(); не работает, потому что GetWideString() возвращает временный std::wstring это выходит за рамки и освобождается, как только утверждение закончено. Таким образом, вы получаете указатель на временный блок памяти, а затем оставляете этот указатель свисающим, когда эта память освобождается, прежде чем вы сможете использовать указатель для чего-либо.

Также, const wchar_t* wchar2 = GetWChar("me"); не должен компилироваться. GetWChar() возвращает std::wstring, который не реализует неявное преобразование в wchar_t*, Вы должны использовать c_str() способ получить wchar_t* из std::wstring,

2

Другие решения

Потому что два указателя не равны. wchar_t * это не Stringтак что вы получите универсальный AreEqual.

1

std::wstring содержит широкие символы типа wchar_t, std::string содержит символы типа char, Для специальных символов, хранящихся в std::string используется многобайтовая кодировка, то есть некоторые символы представлены двумя символами в такой строке. Таким образом, преобразование между ними не может быть легким, как вызов простого assign,

Для преобразования между «широкими» и многобайтовыми строками вы можете использовать следующие помощники (только для Windows):

// multi byte to wide char:
std::wstring s2ws(const std::string& str)
{
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
return wstrTo;
}

// wide char to multi byte:
std::string ws2s(const std::wstring& wstr)
{
int size_needed = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), 0, 0, 0, 0);
std::string strTo(size_needed, 0);
WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), &strTo[0], size_needed, 0, 0);
return strTo;
}
0
По вопросам рекламы [email protected]