Ho letto alcuni articoli su Unicode e mi sono reso conto che mi rimane ancora confuso cosa fare esattamente al riguardo.C++ string letterale ancora confuso
Come programmatore C++ su piattaforma Windows, le discipline che mi sono state date erano per lo più identiche a quelle di qualsiasi insegnante: utilizzare sempre il set di caratteri Unicode; templatizzarlo o utilizzare TCHAR se possibile; preferisco wchar_t, std :: wstring su char, std :: string.
#include <tchar.h>
#include <string>
typedef std::basic_string<TCHAR> tstring;
// ...
static const char* const s_hello = "핼로"; // bad
static const wchar_t* const s_wchar_hello = L"핼로" // better
static LPCTSTR s_tchar_hello = TEXT("핼로") // even better
static const tstring s_tstring_hello(TEXT("핼로")); // best
In qualche modo ho incasinato, e mi portano a me stesso di credere che se io dico "qualcosa", che significa che è ASCII formattato, e se dico L "qualcosa" è Unicode. Poi ho letto questo:
tipo wchar_t è un tipo distinto i cui valori possono rappresentare codici distinti per tutti i membri del set di caratteri esteso più grande specificato tra le lingue supportate (22.3.1). Il tipo wchar_t deve avere le stesse dimensioni, firma e requisiti di allineamento (3.11) come uno degli altri tipi interi, chiamato il suo tipo sottostante. Tipi char16_t e char32_t indicano tipi distinti con le stesse dimensioni, signnessness e allineamento di uint_least16_t e uint_least32_t, rispettivamente, in, chiamati tipi sottostanti.
Quindi cosa? Se il mio locale dice iniziare dalla codepage 949, l'estensione di wchar_t è 949 + 2^(sizeof (wchar_t) * 8)? E il modo in cui parla sembra "Non mi interessa se la tua implementazione di C++ usa la codifica UTF o cosa".
Almeno, potrei capire che tutto dipende da quale locale è l'applicazione. Così ho provato:
#define TEST_OSTREAM_PRINT(x) \
std::cout << "----" << std::endl; \
std::cout << "cout : " << x << std::endl; \
std::wcout << "wcout : " << L##x << std::endl;
int main()
{
std::ostream& os = std::cout;
std::cout << " * Info : " << std::endl
<< " sizeof(char) : " << sizeof(char) << std::endl
<< " sizeof(wchar_t) : " << sizeof(wchar_t) << std::endl
<< " littel endian? : " << IsLittelEndian() << std::endl;
std::cout << " - LC_ALL: " << setlocale(LC_ALL, NULL) << std::endl;
std::cout << " - LC_CTYPE: " << setlocale(LC_CTYPE, NULL) << std::endl;
TEST_OSTREAM_PRINT("핼로");
TEST_OSTREAM_PRINT("おはよう。");
TEST_OSTREAM_PRINT("你好");
TEST_OSTREAM_PRINT("resume");
TEST_OSTREAM_PRINT("résumé");
return 0;
}
Poi uscita era:
Info
sizeof(char) = 1
sizeof(wchar_t) = 2
LC_ALL = C
LC_CTYPE = C
----
cout : 핼로
wcout : ----
cout : おはよう。
wcout : ----
cout : ?好
wcout : ----
cout : resume
wcout : resume
----
cout : r?sum?
wcout : r?um
Un'altra uscita con locale coreano:
Info
sizeof(char) = 1
sizeof(wchar_t) = 2
LC_ALL = Korean_Korea.949
LC_CTYPE = Korean_Korea.949
----
cout : 핼로
wcout : 핼로
----
cout : おはよう。
wcout : おはよう。
----
cout : ?好
wcout : ----
cout : resume
wcout : resume
----
cout : r?sum?
wcout : resume
Un'altra uscita:
Info
sizeof(char) = 1
sizeof(wchar_t) = 2
LC_ALL = fr-FR
LC_CTYPE = fr-FR
----
cout : CU·I
wcout : ----
cout : ªªªIªeª|¡£
wcout : ----
cout : ?u¿
wcout : ----
cout : resume
wcout : resume
----
cout : r?sum?
wcout : resume
Si scopre Se io non dare la giusta localizzazione, applicazione non riesce a gestire un certo numero di caratteri, non importa che abbia usato char o wchar_t. Questo non è solo un problema. Visual studio dà avvertimento:
warning C4566: character represented by universal-character-name '\u4F60' cannot be represented in the current code page (949)
Non sono sicuro se questo sta descrivendo quello che sto ottenendo come output o qualcos'altro.
Domanda. Quali sarebbero le migliori pratiche e perché? Come si può rendere una piattaforma applicativa/implementazione/nazione indipendente? cosa succede esattamente alle stringhe letterali sulla fonte? come vengono interpretati i valori stringa dall'applicazione?
Per la massima compatibilità: mantenere i caratteri nella sorgente sui caratteri ASCII di base. Usa la codifica UTF8 usando i byte definiti con \ x nelle stringhe. Il nuovo file u8 "\ u1234" nell'ultima versione di C++ renderà tutto più semplice, ma non è ancora supportato da Visual Studio. Vedi anche questa domanda: http://stackoverflow.com/questions/3768363/character-sets-not-clear – JCx
'' TCHAR's sono una seccatura gigantesca. A meno che tu non stia cercando di supportare versioni molto vecchie di Windows, dai solo alle stringhe di Windows. Per compatibilità con altre cose, è possibile memorizzare stringhe utilizzando UTF-8 e convertirle quando si utilizza una funzione API di Windows. – chris