Question

J'écris un petit emballage pour une application qui utilise des fichiers comme arguments.

L'emballage doit être en Unicode, alors j'utilise wchar_t pour les personnages et les chaînes que j'ai. Maintenant, je me trouve dans un problème, je dois avoir les arguments du programme dans un tableau de wchar_t et de dans une chaîne wchar_t.

Est-il possible? Je définir la fonction main comme

int main(int argc, char *argv[])

Dois-je utiliser des années wchar_t pour argv?

Merci beaucoup, il me semble ne pas trouver des informations utiles sur la façon d'utiliser Unicode correctement dans C.

Était-ce utile?

La solution

En général, non. Cela dépendra de l'O / S, mais la norme C dit que les arguments « principal () » doit être 'principal (int argc, char ** argv) ou équivalent, donc à moins que l'omble chevalier et wchar_t sont le même type de base , vous ne pouvez pas le faire.

Cela dit, vous pouvez obtenir des chaînes d'arguments UTF-8 dans le programme, les convertir en UTF-16 ou UTF-32, puis passer à la vie.

Sur un Mac (10.5.8, Leopard), je suis arrivé:

Osiris JL: echo "ï€" | odx
0x0000: C3 AF E2 82 AC 0A                                 ......
0x0006:
Osiris JL: 

C'est tout codage UTF-8. (ODX est un programme de vidage hexadécimal).

Voir aussi: Pourquoi est-ce que l'encodage UTF-8 est utilisé lors de l'interaction avec un environnement UNIX / Linux

Autres conseils

Code Portable ne le supporte pas. Windows (par exemple) permet l'utilisation d'wmain au lieu de main, auquel cas argv est passée en caractères larges.

Sous Windows, vous pouvez utiliser GetCommandLineW() et CommandLineToArgvW() pour produire un tableau de wchar_t[] style argv, même si l'application n'est pas compilé pour Unicode.

Sous Windows de toute façon, vous pouvez avoir un wmain() pour UNICODE construit. Non portable bien. Je ne sais pas si les plates-formes GCC ou Unix / Linux fournissent quelque chose de similaire.

En supposant que votre environnement Linux utilise encodage UTF-8, puis le code suivant préparera votre programme pour le traitement facile Unicode en C ++:

    int main(int argc, char * argv[]) {
      std::setlocale(LC_CTYPE, "");
      // ...
    }

Ensuite, tapez wchar_t est de 32 bits sous Linux, ce qui signifie qu'il peut contenir des points individuels de code Unicode et vous pouvez utiliser en toute sécurité de type wstring pour le traitement de cordes classique en C ++ (caractère par caractère). Avec appel ci-dessus setlocale, l'insertion dans wcout se traduira automatiquement en sortie UTF-8 et l'extraction de WCIN se traduira automatiquement entrée UTF-8 en UTF-32 (1 caractère = 1 point de code). Le seul problème qui reste est que argv [i] chaînes sont toujours codage UTF-8.

Vous pouvez utiliser la fonction suivante pour décoder UTF-8 en UTF-32. Si la chaîne d'entrée est corrompu, il retourne correctement les caractères convertis jusqu'à l'endroit où les règles UTF-8 ont été brisées. Vous pouvez l'améliorer si vous avez besoin de rapports plus d'erreur. Mais pour les données argv on peut supposer que c'est UTF-8 correct:

#define ARR_LEN(x) (sizeof(x)/sizeof(x[0]))

    wstring Convert(const char * s) {
        typedef unsigned char byte;
        struct Level { 
            byte Head, Data, Null; 
            Level(byte h, byte d) {
                Head = h; // the head shifted to the right
                Data = d; // number of data bits
                Null = h << d; // encoded byte with zero data bits
            }
            bool encoded(byte b) { return b>>Data == Head; }
        }; // struct Level
        Level lev[] = { 
            Level(2, 6),
            Level(6, 5), 
            Level(14, 4), 
            Level(30, 3), 
            Level(62, 2), 
            Level(126, 1)
        };

        wchar_t wc = 0;
        const char * p = s;
        wstring result;
        while (*p != 0) {
            byte b = *p++;
            if (b>>7 == 0) { // deal with ASCII
                wc = b;
                result.push_back(wc);
                continue;
            } // ASCII
            bool found = false;
            for (int i = 1; i < ARR_LEN(lev); ++i) {
                if (lev[i].encoded(b)) {
                    wc = b ^ lev[i].Null; // remove the head
                    wc <<= lev[0].Data * i;
                    for (int j = i; j > 0; --j) { // trailing bytes
                        if (*p == 0) return result; // unexpected
                        b = *p++;   
                        if (!lev[0].encoded(b)) // encoding corrupted
                            return result;
                        wchar_t tmp = b ^ lev[0].Null;
                        wc |= tmp << lev[0].Data*(j-1);
                    } // trailing bytes
                    result.push_back(wc);
                    found = true;
                    break;
                } // lev[i]
            }   // for lev
            if (!found) return result; // encoding incorrect
        }   // while
        return result;
    }   // wstring Convert

Sous Windows, vous pouvez utiliser tchar.h et _tmain, qui sera transformé en wmain si le symbole _UNICODE est défini au moment de la compilation, ou principale autrement. TCHAR * argv [] sera de même être étendue à WCHAR * argv [] si unicode est défini, et char * argv [] sinon.

Si vous voulez avoir votre principale plate-forme de croix de méthode de travail, vous pouvez définir vos propres macros dans le même sens.

tchar.h contient un certain nombre de macros ci pour la conversion entre wchar et le charbon.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top