2009-11-03 20 views
11

Estoy escribiendo un pequeño contenedor para una aplicación que usa archivos como argumentos.¿Es posible usar un "argv" Unicode?

El contenedor debe estar en Unicode, entonces estoy usando wchar_t para los caracteres y cadenas que tengo. Ahora que me encuentro en un problema, necesito tener los argumentos del programa en una matriz de wchar_t y en una cadena 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.

Respuesta

9

En general, no. Dependerá de la O/S, pero el estándar C dice que los argumentos a 'main()' deben ser 'main (int argc, char ** argv)' o equivalentes, a menos que char y wchar_t sean del mismo tipo básico no puedes hacerlo

Una vez dicho esto, puede obtener cadenas de argumentos UTF-8 en el programa, convertirlos a UTF-16 o UTF-32, y luego continuar con la vida.

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

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).

Consulte también: Why is it that UTF-8 encoding is used when interacting with a UNIX/Linux environment

3

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

9

El código portátil no es compatible. Windows (por ejemplo) admite el uso de wmain en lugar de main, en cuyo caso argv se pasa como caracteres anchos.

2

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 ampliará de manera similar a WCHAR * argv [] si se define unicode, y char * argv [] si no.

Si desea que su método principal funcione multiplataforma, puede definir sus propias macros con el mismo efecto.

TCHAR.h contiene una serie de macros de conveniencia para la conversión entre wchar y char.

3

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, ""); 
     // ... 
    } 

continuación, tipo wchar_t es de 32 bits en Linux, lo que significa que puede contener puntos de código Unicode individuales y puede usar wstring de forma segura para el procesamiento de cadenas clásicas en C++ (carácter por carácter). Con la llamada setlocale anterior, al insertar en wcout se traducirá automáticamente su salida en UTF-8 y la extracción de wcin traducirá automáticamente la entrada UTF-8 en UTF-32 (1 carácter = 1 punto de código). El único problema que queda es que las cadenas argv [i] todavía están codificadas en UTF-8.

Puede usar la siguiente función para decodificar UTF-8 en UTF-32.Si la cadena de entrada está dañada, devolverá correctamente los caracteres convertidos hasta el lugar donde se rompieron las reglas UTF-8. Puede 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 
6

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

Cuestiones relacionadas