Domanda

Sto scrivendo un po 'wrapper per un'applicazione che utilizza i file come argomenti.

L'involucro deve essere in Unicode, quindi sto usando wchar_t per i personaggi e le stringhe che ho. Ora mi ritrovo in un problema, ho bisogno di avere gli argomenti del programma in una serie di wchar_t di e in una stringa wchar_t.

E 'possibile? Sto definendo la funzione main come

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

Devo utilizzare wchar_t di per argv?

La ringrazio molto, mi sembra di non trovare informazioni utili su come utilizzare correttamente Unicode in C.

È stato utile?

Soluzione

In generale, no. Dipenderà O / S, ma lo standard C dice che gli argomenti a 'principale ()' devono essere 'main (int argc, char ** argv)' o equivalente, in modo meno char e wchar_t sono dello stesso tipo di base , non è possibile farlo.

Detto questo, si potrebbe ottenere stringhe UTF-8 argomento nel programma, convertirli in UTF-16 o UTF-32, e poi andare avanti con la vita.

Su un Mac (10.5.8, Leopard), ho ottenuto:

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

Questo è tutto codifica UTF-8. (ODX è un programma dump esadecimale).

Si veda anche: Perché è che la codifica UTF-8 viene utilizzato quando si interagisce con un ambiente UNIX / Linux

Altri suggerimenti

Codice portatile non lo supporta. Windows (ad esempio) supporta l'utilizzo wmain invece di main, nel qual caso argv viene passata come caratteri estesi.

In Windows, è possibile utilizzare GetCommandLineW() e CommandLineToArgvW() per la produzione di una matrice wchar_t[] argv stile, anche se l'applicazione non è compilato per Unicode.

In Windows in ogni caso, si può avere un wmain() per UNICODE costruisce. Non portatile però. Non so se le piattaforme GCC o Unix / Linux forniscono qualcosa di simile.

Supponendo che l'ambiente Linux usa codifica UTF-8 quindi il seguente codice preparerà il vostro programma per facilitare il trattamento Unicode in C ++:

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

Avanti, tipo wchar_t è a 32-bit in Linux, il che significa che può contenere punti di codice Unicode individuali ed è possibile utilizzare in modo sicuro tipo wstring per l'elaborazione delle stringhe classica in C ++ (carattere per carattere). Con la chiamata setlocale sopra, inserendo in wcout tradurrà automaticamente l'uscita in UTF-8 e l'estrazione da wcin tradurrà automaticamente UTF-8 input in UTF-32 (1 carattere = 1 punto codice). L'unico problema che rimane è che argv [i] stringhe sono ancora codifica UTF-8.

È possibile utilizzare la seguente funzione di decodificare UTF-8 in UTF-32. Se la stringa di input è danneggiato tornerà caratteri correttamente convertiti fino al luogo in cui sono state suddivise le regole UTF-8. Si potrebbe migliorare se avete bisogno di più la segnalazione degli errori. Ma per i dati argv si può supporre con sicurezza che sia corretto UTF-8:

#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

In Windows, è possibile utilizzare tchar.h e _tmain, che sarà trasformato in wmain se il simbolo _UNICODE è definito al momento della compilazione, o altrimenti principale. TCHAR * argv [] sarà simile essere ampliato per WCHAR * argv [] se unicode è definita, e char * argv [] se non.

Se si desidera avere la vostra piattaforma di metodo di lavoro trasversale principale, è possibile definire le proprie macro per lo stesso effetto.

tchar.h contiene un certo numero di macro di convenienza per la conversione tra wchar e salmerino.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top