Poprawna konwersja string na wstring

0

Czytam, szukam, próbuję i nic nie idzie. Próbowałem z różnymi funkcjami widen, btowcs itd.

Mam prosty string:

 
std::string str("Koń");

chcę zamienić go na wstring. Z każdym razem w wstringu nie dostaję polskiego "ń", tylko "n" z falką na górze. Oczywiście różni się to od:

 
std::wstring(L"Koń");

Czy ktoś może mi powiedzieć, jak dobrze skonwertować tego stringa na wstringa? Nie chce mi się wierzyć, że nie ma do tego jakiejś prostej metody.

1
#include <locale>
#include <codecvt>
#include <string>

std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string narrow = converter.to_bytes(wide_utf16_source_string);
std::wstring wide = converter.from_bytes(narrow_utf8_source_string);
0

Kod jest banalny:

std::string str("Koń");
	std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
	try
	{
		std::wstring wide = converter.from_bytes(str);
		std::wcout << wide;
	}catch(std::range_error & err)
	{
		std::string msg = err.what();
	}

Visual Studio 2012

0

Skoro nikt tu nie jest w stanie mi odpowiedzieć, to proszę moderację o przeniesienie tematu na forum C++

2

Zapisz źródła w kodowaniu UTF8

0

Po zmianie na UTF-8 bez BOM (z BOM nie działało) zaczęło to przechodzić i jest PRAWIE dobrze. Ale to już chyba jakieś ustawienia środowiska, może ktoś pomóc?

 
std::string str("Koń"); //w debugerze na podglądzie daje "L;" zamiast "ń" - ale to mogę zrozumieć. W końcu to std::string
std::wstring wstr(L"Koń"); //ale to też na podglądzie w debugerze nie pokazuje "ń".

Poza tym, gdzieś można ustawić domyślne kodowanie dla plików? Szukałem tego, ale nie znalazłem. Przypominam - Visual Studio 2012.

0

Tools > Options > Environment > Documents, named Save documents as Unicode when data cannot be saved in codepage.

0

Po zmianie na UTF-8 bez BOM (z BOM nie działało) zaczęło to przechodzić

Zaczęło przechodzić, bo teraz literały tekstowe są w utf-8, a to błąd, ponieważ te powinny być w kodowaniu ansi. Jak chcesz, żeby było utf-8, daj przed literałem u8.

Plik zapisz normalnie, bez wydziwiania (jeśli w utf-8, to z BOM-em) i spróbuj tak:

std::string str = "Koń";

std::locale loc(".1250"); // strona kodowa 'str'
auto &cctv = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(loc);
std::wstring_convert<std::codecvt<wchar_t, char, std::mbstate_t>> converter( &cctv );

std::wstring wide = converter.from_bytes(str);
std::wcout.imbue(std::locale(".852")); // kodowanie konsoli windows
std::wcout << wide;
0

Czemu powinny być w ansi?
Czy Twoja wersja (ustawianie aktualnych locales jako tych z pliku) jest bardziej bezpieczna?

0

Nie masz gwarancji że twój kompilator da rady z takiego napisu ".852" stworzyć locale

0

Czemu powinny być w ansi?

Bo od literałów w utf-8 masz wspomniany prefiks u8.

Czy Twoja wersja (ustawianie aktualnych locales jako tych z pliku) jest bardziej bezpieczna?

Jest zgodna z tym, co chciałeś uzyskać, czyli konwersję ansi -> unikod. A czy bezpieczna? Zabawy ze stronami kodowymi zawsze niosą jakieś ryzyko, dlatego wymyślono unikod.

0

Dobra, to inne pytanie. Załóżmy, że mamy plik tekstowy, którego zawartość mamy odczytaną w std::string. I jak w takim przypadku sobie poradzić?

0

Sprawdzasz czy masz BOM - jak masz to jesteś w domu, a jak nie to możesz sobie szczęśliwe lub nieszczęśliwe zgadywać ewentualnie założyć że w tym przypadku masz jakiś konkretny np domyślny z systemu.
Alternatywa - statystyczna zgadywanka.

1 użytkowników online, w tym zalogowanych: 0, gości: 1