2013-03-11 26 views
6

Sto cercando un po 'di consigli sul modo migliore per convertire uno std::wstring in std::string - ma un conversione rapida e sporca da utilizzare come chiave in un oggetto std::map<std::string, int>.C++ - std :: wstring a std :: string - conversione rapida e sporca da utilizzare come chiave in std :: map

La mappa è abbastanza grande, ed è già ben integrato nel progetto già, e ci sono solo una manciata di chiavi che richiedono questa conversione quindi penso che sarà uno spreco per cambiare la mappa in uno che accetta std::wstring come la chiave.

L'output della conversione non ha molta importanza, ma deve essere coerente in modo da estrarre in modo affidabile i valori corretti dalla mappa ogni volta.

L'applicazione è un'applicazione solo per Windows.

Esiste un processo noto per eseguire una conversione approssimativa in modo affidabile per questo scopo? Oppure il modo migliore sarebbe attraverso il solito processo di conversione (come descritto in questa domanda/risposta SO: How to convert wstring into string?)?

Edit: Si prega di tenere presente - la perdita di informazioni va bene finché cose sono coerenti. Ad esempio, se inserisco alcuni caratteri giapponesi e vengono convertiti in modo coerente nella stessa (potenzialmente spazzatura) std::string, va bene. Questo non sarà mai per la visualizzazione, solo per essere usato come chiave per estrarre i valori da una mappa.

Grazie!

+0

Un [adattatore] (http://en.wikipedia.org/wiki/Adapter_pattern)? – krlmlr

+2

Forse dovresti convertire 'std :: wstring' in [UTF-8] (http://en.wikipedia.org/wiki/UTF-8), e impostare' std :: string' su quel valore. In questo modo eviterete i byte spuri '\ 0'. –

+0

Perché usi 'std :: wstring'? [Usa UTF8 ovunque.] (Http://utf8everywhere.org/) –

risposta

7

Se non sei interessato alla semantica del contenuto, ma solo al contenuto per essere comparabile, cercherò solo il wchar interno [] in un carattere [] di dimensione raddoppiata e usarlo per inizializzare la stringa (specificando indirizzo/dimensione nel costruttore)

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

Ora s è stampabile (può contenere caratteri nulli), ma ancora assegnabili e comparabili.

Yo può tornare indietro come:

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

Ora confrontate

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

dovrebbe stampare 1.

Tuttavia, notare che in questo modo l'ordine nella mappa (risultato di operator<) è ... sfocato a causa della presenza dello 0 e non riflette alcuna semantica di testo. Tuttavia la ricerca funziona ancora, dal momento che, nonostante tutto, è ancora un "ordine".

+1

Questo distrarrà l'OP: il punto è ovviamente non avere una bella stampa, ma controllare che nessuna perdita di informazioni si verifichi durante un ciclo. Qualunque risultato che cambia a seconda dell'uguaglianza ha lo stesso effetto. Ho fatto il più breve e semplice, senza richiedere intestazioni aggiuntive. Spetta all'OP trovare il miglior "beautifier" per le sue necessità (inclusa la sostituzione di cout con MessageBox o qualsiasi altra finestra di dialogo che mostra le cose che vorrebbe) –

+2

Se questa fosse una unordered_map, sarei preoccupato dei byte nulli all'interno della stringa. Se la funzione hashing ha una specializzazione per le stringhe, potrebbe o meno rispettare la dimensione effettiva std :: string e fermarsi al primo byte null. –

7

È possibile convertire std: wstring in utf-8 (utilizzando WideCharToMultiByte o qualcosa come questo lib: http://utfcpp.sourceforge.net/), ovvero una c-string con terminazione null e quindi creare std :: string da esso. Questa conversione sarà reversibile.

+0

+1: una buona scoperta. –

9

Come variante, vorrei andare per

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

Forse l'altra risposta è più veloce (dipende dalla realizzazione iteratori string), ma questo è uno std \ modo più STL come per me. Ma sì, questo perderà alcuni personaggi unici.