2016-06-01 17 views
10

Sappiamo che nella stringa letterale "\ u94b1" sarà convertito in un carattere, in questo caso una parola cinese '钱'. Ma se è letteralmente 6 caratteri in una stringa, dicendo '\', 'u', '9', '4', 'b', '1', come posso convertirlo manualmente in un personaggio?Come posso convertire una stringa come " u94b1" in un vero carattere in C++?

Ad esempio:

string s1; 
string s2 = "\u94b1"; 
cin >> s1;   //here I input \u94b1 
cout << s1 << endl; //here output \u94b1 
cout << s2 << endl; //and here output 钱 

voglio convertire s1 in modo che cout << s1 << endl; sarà anche uscita .

Qualche suggerimento, per favore?

+6

Possibile duplicato di http://stackoverflow.com/questions/3147900/how-to-read-file-which-contains-uxxxx-in-vc – kennytm

risposta

4

In effetti la conversione è un po 'più complicata.

string s2 = "\u94b1"; 

è infatti l'equivalente di:

char cs2 = { 0xe9, 0x92, 0xb1, 0}; string s2 = cs2; 

Ciò significa che si sta inizializzandolo i 3 personaggi che compongono la rappresentazione UTF8 di 钱 - si char solo esaminare s2.c_str() per assicurarsi di che .


Così per elaborare i 6 caratteri prime '\', 'u', '9', '4', 'b', '1', è necessario innanzitutto estrarre il wchar_t da string s1 = "\\u94b1"; (quello che si ottiene quando lo leggi). E 'facile, basta saltare i due primi caratteri e leggerlo come esadecimale:

unsigned int ui; 
std::istringstream is(s1.c_str() + 2); 
is >> hex >> ui; 

ui è ora 0x94b1.

Ora, se si dispone di un sistema compatibile C++ 11, è possibile convertire con std::convert_utf8:

wchar_t wc = ui; 
std::codecvt_utf8<wchar_t> conv; 
const wchar_t *wnext; 
char *next; 
char cbuf[4] = {0}; // initialize the buffer to 0 to have a terminating null 
std::mbstate_t state; 
conv.out(state, &wc, &wc + 1, wnext, cbuf, cbuf+4, next); 

cbuf contiene ora i 3 personaggi che rappresentano 钱 in utf8 e un null di terminazione, e finalmente può fare :

string s3 = cbuf; 
cout << s3 << endl; 
+0

Grazie per il modo 'stringstream'. Prendo una funzione per tradurre tutte le cose '\ uxxxx' in utf8 caratteri –

2

Si esegue questa operazione scrivendo il codice che controlla se la stringa contiene una barra rovesciata, una lettera u e quattro cifre esadecimali e la converte in un punto di codice Unicode. Quindi la tua implementazione std :: string probabilmente assume UTF-8, quindi tu traduci quel punto di codice in 1, 2 o 3 byte UTF-8.

Per i punti extra, capire come inserire punti di codice al di fuori del piano di base.

+0

Does 'std :: string' assume anche una codifica? Ho sempre pensato che fosse un muto contenitore di caratteri che può essere byte, unità di codice, punti di codice o qualsiasi altra cosa, a seconda dell'implementazione e nessuna parte di 'std :: string' supporta qualcosa come lavorare con il testo (es. Normalizzazione Unicode, linguaggio- ordinamento consapevole, ecc.). Ottieni una serie di cose. In che modo la mappatura al testo non è compito di C++. – Joey

+0

@Joey "Il modo in cui le mappe di testo non sono il lavoro di C++". Non proprio. std :: string non può assumere una codifica, ma sicuramente altre parti di C++ lo fanno. Se ha a che fare con locales, probabilmente ha qualche idea su una o più codifiche. –

+0

Grazie per l'ispirazione! –

1

Con utfcpp (solo intestazione) si può fare:

#include </usr/include/utf8.h> 

#include <cstdint> 
#include <iostream> 

std::string replace_utf8_escape_sequences(const std::string& str) { 
    std::string result; 
    std::string::size_type first = 0; 
    std::string::size_type last = 0; 
    while(true) { 
     // Find an escape position 
     last = str.find("\\u", last); 
     if(last == std::string::npos) { 
      result.append(str.begin() + first, str.end()); 
      break; 
     } 

     // Extract a 4 digit hexadecimal 
     const char* hex = str.data() + last + 2; 
     char* hex_end; 
     std::uint_fast32_t code = std::strtoul(hex, &hex_end, 16); 
     std::string::size_type hex_size = hex_end - hex; 

     // Append the leading and converted string 
     if(hex_size != 4) last = last + 2 + hex_size; 
     else { 
      result.append(str.begin() + first, str.begin() + last); 
      try { 
       utf8::utf16to8(&code, &code + 1, std::back_inserter(result)); 
      } 
      catch(const utf8::exception&) { 
       // Error Handling 
       result.clear(); 
       break; 
      } 
      first = last = last + 2 + 4; 
     } 
    } 
    return result; 
} 

int main() 
{ 
    std::string source = "What is the meaning of '\\u94b1' '\\u94b1' '\\u94b1' '\\u94b1' ?"; 
    std::string target = replace_utf8_escape_sequences(source); 
    std::cout << "Conversion from \"" << source << "\" to \"" << target << "\"\n"; 
} 
+0

Aiuto utile! Ho esaminato utfcpp e ho fatto la mia funzione facendo ciò che fa 'utf16to8', traducendo il punto di codice in diversi byte di carattere, che vengono aggiunti alla stringa di destinazione. I miei lavori sono praticamente uguali ai tuoi. Comunque, grazie mille. –

Problemi correlati