Pregunta

Estoy escribiendo un pequeño envoltorio para una aplicación que utiliza archivos como argumentos.

La envoltura tiene que estar en Unicode, por lo que estoy usando wchar_t de los caracteres y cadenas que tengo. Ahora me encuentro en un problema, tengo que tener los argumentos del programa en una variedad de wchar_t de y en una cadena de wchar_t.

¿Es posible? Estoy definiendo la función main como

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

¿Debo usar de wchar_t para argv?

Muchas gracias, no parecen encontrar información útil sobre el uso de Unicode correctamente en C.

¿Fue útil?

Solución

En general, no. Esto dependerá de la O / S, pero el estándar C dice que los argumentos a 'main ()' debe ser 'principal (int argc, char ** argv)' o equivalente, por lo menos Char y wchar_t son del mismo tipo básico , no puede hacerlo.

Una vez dicho esto, usted podría conseguir UTF-8 cadenas de argumentos en el programa, los convierte a UTF-16 o UTF-32, y luego seguir con su vida.

En un Mac (10.5.8, Leopard), que tengo:

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

Eso es todo codificación UTF-8. (ODX es un programa de volcado hexadecimal).

Vea también: Por qué es que codificación UTF-8 se utiliza en la interacción con un entorno UNIX / Linux

Otros consejos

Código portátil no lo soporta. Windows (por ejemplo) soporta el uso de wmain en lugar de main, en cuyo caso argv se pasa como caracteres anchos.

En Windows, puede utilizar GetCommandLineW() y CommandLineToArgvW() para producir una matriz wchar_t[] de estilo argv, incluso si la aplicación no ha sido preparado para Unicode.

En Windows de todos modos, se puede tener una wmain() para UNICODE construye. No portátil sin embargo. No sé si las plataformas CCG o Unix / Linux proporcionan algo similar.

Suponiendo que su entorno Linux utiliza codificación UTF-8 a continuación, el siguiente código preparará su programa para el tratamiento fácil Unicode en C ++:

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

A continuación, el tipo wchar_t es de 32 bits en Linux, lo que significa que puede contener puntos de código Unicode individuales y se puede utilizar con seguridad el tipo wstring para el procesamiento de cuerda clásica en C ++ (carácter por carácter). Con la llamada a setlocale anteriormente, insertando en wcout se traducirá automáticamente su salida en UTF-8 y extrayendo de WCIN se traducirá automáticamente UTF-8 de entrada en UTF-32 (1 carácter = 1 punto de código). El único problema que permanece es que argv [i] cuerdas están todavía codificación UTF-8.

Puede utilizar la siguiente función para decodificar UTF-8 en UTF-32. Si está dañada la cadena de entrada se devolverá caracteres correctamente convertidos hasta el lugar donde se rompieron las reglas de codificación UTF-8. Se podría mejorarlo si necesita más informes de errores. Pero para los datos argv se puede suponer con seguridad que es correcto 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

En Windows, puede utilizar tchar.h y tmain, que se convirtió en wmain si el símbolo _UNICODE se define en tiempo de compilación, o de otro modo principal. TCHAR * argv [] se similarmente ser ampliado para WCHAR * argv [] si no se define Unicode y char * argv [] si no.

Si usted quiere tener su plataforma cruzada principal método de trabajo, puede definir sus propias macros en el mismo sentido.

tchar.h contiene una serie de macros convenientes para la conversión entre wchar y carbón.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top