Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - std::wstring to std::string - quick and dirty conversion for use as key in std::map

Tags:

c++

stdstring

I'm looking for a bit of advice on the best way to convert a std::wstring to std::string - but a quick and dirty conversion for use as a key in an std::map<std::string, int> object.

The map is quite large, and is already well integrated into the project already, and there are only a handful of keys that require this conversion so I think it will be wasteful to change the map into one that accepts std::wstring as the key.

The output of the conversion doesn't really matter, but it has to be consistent so as to reliably pull the correct values from the map every time.

The application is a Windows only application.

Is there any known process to do a rough conversion reliably for this purpose? Or would the best way be via the usual, proper, conversion process (as described in this SO question/answer: How to convert wstring into string?)?

Edit: Please bear in mind - losing information is fine as long as things are consistent. i.e. If I throw in some Japanese characters, and they consistently convert into the same (potentially garbage) std::string, that's fine. This will never be for display, only to be used as a key to pull out values from a map.

Thanks!

like image 303
Jace Avatar asked Mar 11 '13 07:03

Jace


3 Answers

If you are not interested in the semantic of the content, but just to the content to be comparable, I'll just coherce the inner wchar[] into a char[] of doubled size and use it to initialize the string (by specifying address/size in the constructor)

std::wstring ws(L"ABCD€FG");
std::string s((const char*)&ws[0], sizeof(wchar_t)/sizeof(char)*ws.size());

Now s is unprintable (it may contain null chars) but still assignable and comparable.

Yo can go back as:

std::wstring nws((const wchar_t*)&s[0], sizeof(char)/sizeof(wchar_t)*s.size());

Now compare

std::cout << (nws==ws)

should print 1.

However, note that this way the order in the map (result of operator<) is ... fuzzy because of the presence of the 0, and don't reflect any text sematics. However search still works, since -however fuzzy- it is still an "order".

like image 101
Emilio Garavaglia Avatar answered Nov 06 '22 07:11

Emilio Garavaglia


As a variant, I would go for

std::wstring w( L"Some" );
std::string s( w.begin(), w.end() );

Maybe the other answer is faster (depends on string iterators' implementation), but this is a more std\stl way as for me. But yep, this will lose some unique characters.

like image 10
Roman Kruglov Avatar answered Nov 06 '22 08:11

Roman Kruglov


You can convert std::wstring to utf-8 (using WideCharToMultiByte or something like this lib: http://utfcpp.sourceforge.net/), that is, a null-terminating c-string, and then construct std::string from it. This conversion will be reversible.

like image 8
user2155932 Avatar answered Nov 06 '22 07:11

user2155932