É possível usar um Unicode “argv”?
-
12-09-2019 - |
Pergunta
Eu estou escrevendo um pequeno wrapper para um aplicativo que arquivos usa como argumentos.
As necessidades de mensagens publicitárias para a Unicode, por isso estou usando wchar_t para os personagens e cordas eu tenho. Agora eu me encontro em um problema, eu preciso ter os argumentos do programa em uma matriz de wchar_t de e em uma string wchar_t.
É possível? Eu estou definindo a função main
como
int main(int argc, char *argv[])
Devo usar wchar_t é para argv
?
Muito obrigado, eu não parecem encontrar informações úteis sobre como utilizar Unicode corretamente no C.
Solução
Em geral, não. Vai depender o O / S, mas o padrão C diz que os argumentos para 'principal ()' deve ser 'principal (int argc, char ** argv)' ou equivalente, de modo a não ser que de char e wchar_t são o mesmo tipo de base , você não pode fazê-lo.
Dito isto, você poderia começar UTF-8 cordas argumento para o programa, convertê-los em UTF-16 ou UTF-32, e depois seguir com a vida.
Em um Mac (10.5.8, Leopard), eu tenho:
Osiris JL: echo "ï€" | odx
0x0000: C3 AF E2 82 AC 0A ......
0x0006:
Osiris JL:
Isso é tudo UTF-8 codificado. (Odx é um programa hexadecimal).
Veja também: Por que é que a codificação UTF-8 é usado quando interagindo com um ambiente UNIX / Linux
Outras dicas
código portátil não apoiá-lo. Windows (por exemplo) suporta usando wmain
vez de main
, caso em que argv é passado como caracteres largos.
No Windows, você pode usar GetCommandLineW()
e CommandLineToArgvW()
para produzir uma variedade wchar_t[]
de estilo argv, mesmo que o aplicativo não é compilado para Unicode.
No Windows de qualquer maneira, você pode ter um wmain()
para Unicode cria. embora não portátil. Eu não sei se as plataformas do CCG ou Unix / Linux fornecer qualquer coisa similar.
Assumindo que o seu ambiente Linux utiliza codificação UTF-8, em seguida, o seguinte código irá preparar o seu programa para facilitar o tratamento Unicode em C ++:
int main(int argc, char * argv[]) {
std::setlocale(LC_CTYPE, "");
// ...
}
Em seguida, tipo wchar_t é de 32 bits no Linux, o que significa que ele pode conter pontos de código individuais Unicode e você pode usar com segurança wstring tipo para processamento seqüência clássica em C ++ (caractere por caractere). Com chamada setlocale acima, inserindo wcout irá traduzir automaticamente a sua saída em UTF-8 e extrair wcin irá traduzir automaticamente a entrada UTF-8 em UTF-32 (1 caracter = 1 ponto de código). O único problema que resta é que argv [i] cordas são ainda UTF-8 codificado.
Você pode usar a seguinte função para decodificar UTF-8 em UTF-32. Se a cadeia de entrada está corrompido ele irá retornar caracteres adequadamente convertidos até o lugar onde as regras UTF-8 foram quebrados. Você poderia melhorá-lo se precisar de mais relatórios de erro. Mas para argv dados pode-se seguramente assumir que ele está correto 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
No Windows, você pode usar tchar.h e _tmain, que será transformado em wmain se o símbolo _UNICODE é definido em tempo de compilação, ou principal de outra forma. TCHAR * argv [] será igualmente ser expandido para WCHAR * argv [] se Unicode é definido, e char * argv [], se não.
Se você quer ter a sua plataforma de trabalho método cross principal, você pode definir suas próprias macros para o mesmo efeito.
Tchar.h contém um número de macros de conveniência para a conversão entre wchar e carvão animal.