2009-12-06 5 views
4

J'ai supposé que std :: wstring et std :: string fournissaient plus ou moins la même interface.L'affectation d'un "const char *" à std :: string est autorisée, mais l'affectation à std :: wstring n'est pas compilée. Pourquoi?

J'ai donc essayé de permettre aux capacités unicode pour notre application

# ifdef APP_USE_UNICODE 
    typedef std::wstring AppStringType; 
# else 
    typedef std::string AppStringType; 
# endif 

Cependant cela me donne beaucoup d'erreurs de compilation lors -DAPP_USE_UNICODE est utilisé.

Il s'est avéré que le compilateur étouffe lorsqu'un const char[] est affecté à std::wstring.

EDIT: exemple amélioré en supprimant l'utilisation du littéral "bonjour".

#include <string> 

void myfunc(const char h[]) { 
    string s = h; // compiles OK 
    wstring w = h; // compile Error 
} 

Pourquoi cela fait-il une telle différence?

L'attribution d'un const char* à std::string est autorisée, mais l'affectation à std::wstring génère des erreurs de compilation.

Est-ce que std::wstring ne devrait pas fournir la même interface que std::string? Au moins pour une opération aussi simple que l'affectation?

(environnement: gcc-4.4.1 sur Ubuntu Karmic 32bit)

Répondre

6

La partie pertinente de l'API de chaîne est ce constructeur:

basic_string(const charT*); 

Pour std :: string, charT est char. Pour std :: wstring c'est wchar_t. La raison pour laquelle elle ne compile pas est que wstring n'a pas de constructeur char *. Pourquoi wstring n'a-t-il pas de constructeur char *?

Il n'existe pas de méthode unique pour convertir une chaîne de caractère en chaîne de caractères wchar. Quel est le codage utilisé avec la chaîne char? Est-ce juste 7 bits ASCII? Est-ce UTF-8? Est-ce UTF-7? Est-ce SHIFT-JIS? Donc, je ne pense pas qu'il serait tout à fait logique pour std :: wstring d'avoir une conversion automatique de char *, même si vous pouvez couvrir la plupart des cas.Vous pouvez utiliser:

w = std::wstring(h, h + sizeof(h) - 1); 

qui convertira chaque omble chevalier à son tour wchar (à l'exception du terminateur NUL), et dans cet exemple qui est probablement ce que vous voulez. Comme le dit int3, si c'est ce que vous voulez dire, il est préférable d'utiliser un littéral à chaîne large en premier lieu.

11

Vous devriez faire:

#include <string> 

int main() { 
    const wchar_t h[] = L"hello"; 
    std::wstring w = h; 
    return 0; 
} 

std::string est un typedef de std::basic_string<char>, alors que std::wstring est un typedef de std::basic_string<wchar_t>. En tant que tel, le "équivalent" C-string d'un wstring est un tableau de wchar_t s. Le 'L' devant le littéral de chaîne indique que vous utilisez une constante de chaîne large.

+4

Une bonne façon de gérer cela est comme l'API win32 et d'écrire une macro TEXT qui laisse la chaîne telle quelle ou ajoute le L en utilisant le jeton de macro ##. Donc, vous pouvez écrire TEXT ("bonjour") et la macro s'étendrait à la forme correcte. –

-1

vous devez utiliser

#include <tchar.h> 

TString au lieu de wstring/string TCHAR * au lieu de char * et _T ("bonjour") au lieu de "bonjour" ou L "bonjour"

cette utilisera la forme appropriée de string + char, lorsque _UNICODE est défini.

+0

"(environnement: gcc-4.4.1 sur Ubuntu Karmic 32bit)" Il n'y a pas de "tchar.h" sur mon système Karmic. Je suis sûr que c'est spécifique à Windows ... – Thomas

+2

-1 TCHAR est spécifique à Windows ... Ne l'utilisez jamais dans des applications portables. – Artyom

+0

Je n'utiliserais jamais wchar dans les applications portables. Windows a un bien meilleur support que Linux:] – nothrow

1

Petite suggestion ... N'utilisez pas de chaînes "Unicode" sous Linux (par exemple, chaînes étendues). std::string est parfaitement bien et détient très bien Unicode (UTF-8).

La plupart des API Linux fonctionnent avec des chaînes char * et le codage le plus courant est UTF-8.

Alors ... Ne vous embêtez pas avec wstring.

+0

Pas vrai. Par exemple, 'string :: size()' vous donne une mauvaise réponse si votre chaîne contient des caractères UTF-8 qui ne sont pas ASCII. Il est en effet possible d'utiliser 'std :: string' pour cela, mais vous devez faire très attention! – Thomas

+0

Il y a un avantage de UTF-32 (qui est ce que wchar_t est sur Linux), c'est-à-dire qu'il est facile de faire des choses comme inverser des chaînes. Pour inverser une chaîne UTF-8, vous devez l'analyser en caractères distincts de toute façon. Donc, si vous faites beaucoup de choses qui agissent sur les caractères Unicode (plutôt que leurs octets UTF-8 constitutifs), alors vous voulez une large représentation. –

+0

Est-ce que std :: wstring :: size() donne le nombre de caractères correct? NON!!!sizeof (wchar_t) peut être 2 et ainsi, les points de code valides dans 0x10000 - 0x1FFFFF seraient représentés comme des paires de substitution, et si vous supposez que la taille vous donne un nombre correct pour wstring votre code est WRONG. ;) – Artyom

0

En plus des autres réponses, vous pouvez utiliser un truc du livre de Microsoft (en particulier, tchar.h), et d'écrire quelque chose comme ceci:

# ifdef APP_USE_UNICODE 
    typedef std::wstring AppStringType; 
    #define _T(s) (L##s) 
# else 
    typedef std::string AppStringType; 
    #define _T(s) (s) 
# endif 

AppStringType foo = _T("hello world!"); 

(Note: mon macro-fu est faible, et ce est non testé, mais vous voyez l'idée)

0

on dirait que vous pouvez faire quelque chose comme ceci:.

#include <sstream> 
    // ... 
    std::wstringstream tmp; 
    tmp << "hello world"; 
    std::wstring our_string = 

Bien que pour une situation plus complexe, vous voudrez peut-BRE abaissez et utilisez mbstowcs

1

Pour convertir un codage multi-octets en un codage de caractères large, consultez l'en-tête <locale> et le type std::codecvt. La bibliothèque Dinkumware a une classe Dinkum::wstring_convert qui facilite l'exécution de telles conversions multi-octets à larges.

La fonction std::codecvt_byname permet de trouver une instance codecvt pour un codage nommé particulier. Malheureusement, la découverte des noms des codages (ou locales) sur votre système est spécifique à l'implémentation.

Questions connexes