2010-06-28 24 views
6

Mon code est essentiellement ceci:C++: caractères larges générés incorrectement?

wstring japan = L"日本"; 
wstring message = L"Welcome! Japan is "; 

message += japan; 

wprintf(message.c_str()); 

Je souhaite utiliser des chaînes larges mais je ne sais pas comment ils sont délivrés, donc j'utilisé wprintf. Quand je lance quelque chose comme:

./widestr | hexdump 

Les codepoints hexadécimaux créent ceci:

65 57 63 6c 6d 6f 21 65 4a 20 70 61 6e 61 69 20 20 73 3f 3f 
e W c l m o ! e J  p a n a i  s ? ? 

Pourquoi sont-ils tous ont sauté dans l'ordre? Je veux dire que si le wprintf est faux je ne comprends toujours pas pourquoi il sortirait dans un tel ordre brouillé spécifique!

éditer: endianness ou quelque chose? ils semblent tourner chaque deux caractères. hein.

EDIT 2: J'ai essayé d'utiliser wcout, mais il sort exactement les mêmes points de code hexidécimal. Bizarre!

+0

Peut-être que vous devriez essayer 'cout << message << endl'. – phimuemue

+0

@phimuemue, Cela ne fonctionne pas, il m'envoie environ 30 erreurs, d'abord étant 'widestr.cpp: 18: erreur: aucune correspondance pour 'operator <<' dans 'std :: cout << message'', y compris beaucoup sur traits de caractère ostream ou quelque chose, il ne sortira pas la chaîne large! –

+1

Quelle plate-forme et quel compilateur utilisez-vous? – hlovdal

Répondre

11

Vous devez définir locale

#include <stdio.h> 
    #include <string> 
    #include <locale> 
    #include <iostream> 

    using namespace std; 

    int main() 
    { 

      std::locale::global(std::locale("")); 
      wstring japan = L"日本"; 
      wstring message = L"Welcome! Japan is "; 

      message += japan; 

      wprintf(message.c_str()); 
      wcout << message << endl; 
    } 

fonctionne comme prévu (par exemple convertir grande chaîne pour réduire UTF-8 et l'imprimer).

Lorsque vous définissez locale globale sur "" - vous définissez paramètres régionaux du système (et si elle est UTF-8 il être imprimé au format UTF-8 - à savoir wstring seront converties)

Edit: oublie ce que j'ai dit à propos de sync_with_stdio - ce n'est pas correct, ils sont synchronisés par défaut. Pas besoin.

+1

Vous donnez l'impression que 'sync_with_stdio' et' wcout' sont des alternatives; ils font des choses complètement différentes. 'sync_with_stdio' est requis si vous voulez entrelacer les fonctions de flux C (comme' wprintf') avec l'utilisation du flux C++ ('wcout'); 'imbue' est nécessaire si vous voulez changer les paramètres régionaux utilisés par' wcout'. –

+0

Je ne peux pas le tester, mais 'wcout' devrait fonctionner sans les paramètres de page de codes sous Windows car' wchar_t' est une unité de code UTF-16 sous Windows et UTF-16 est le seul encodage natif de Windows. Donc 'std :: wcout' devrait utiliser' WriteConsoleW' sans conversion locale. Si ce n'est pas le cas, c'est un bug de la bibliothèque. – Philipp

+2

@Philipp Ce n'est pas comme cela que cela est défini par la norme. La norme indique que les caractères larges doivent être convertis en codage étroit en fonction de la page de code de l'environnement local. Et c'est ce qui est fait. Le problème avec Windows est qu'il ne prend pas en charge UTF-8. Donc, pour Windows, vous devez probablement utiliser 'locale :: globale (locale (" Japan "))' et utiliser l'encodage Shift-JIS en sortie. Sinon, il ne parviendrait pas à convertir les caractères. – Artyom