E 'possibile utilizzare un Unicode “argv”?
-
12-09-2019 - |
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.
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.