Lectura de caracteres fuera de ASCII
Pregunta
Un amigo mío me mostró una situación en la que leer personajes producía un comportamiento inesperado. Leer el carácter '¤' hizo que su programa se bloqueara. Pude concluir que '¤' es 164 decimal, por lo que está por encima del rango ASCII.
Notamos el comportamiento en '¤' pero cualquier carácter > 127 parece mostrar el problema. La pregunta es ¿cómo leeríamos de manera confiable tales caracteres char by char?
int main(int argc, const char *argv[])
{
char input;
do
{
cin >> input;
cout << input;
cout << " " << setbase(10) << (int)input;
cout << " 0x" << setbase(16) << (int)input;
cout << endl;
} while(input);
return 0;
}
masse@libre:temp/2009-11-30 $ ./a.out
¤
 -62 0xffffffc2
¤ -92 0xffffffa4
Solución
Su sistema está utilizando la codificación de caracteres UTF-8 (como debería), por lo que el carácter '¤' hace que su programa lea la secuencia de bytes C2 A4
. Como un char
es un byte, los lee uno a la vez. Mire las wchar_t
y las secuencias correspondientes wcin
y wcout
para leer caracteres multibyte, aunque no sé qué codificaciones admiten o cómo jugar con locales.
Además, su programa está emitiendo UTF-8 no válido, por lo que realmente no debería ver esos dos caracteres: recibo signos de interrogación en mi sistema.
(Este es un punto crítico y algo fuera de tema, pero su while (input)
debe ser while (cin)
, de lo contrario obtendrá un bucle infinito).
Otros consejos
Es difícil saber por qué el programa de su amigo se bloquea sin ver el código, pero podría deberse a que está utilizando el carácter como un índice en una matriz. Como los caracteres que se encuentran fuera del rango ASCII normal desbordarán el límite de un carácter firmado, el carácter terminará en negativo.
declare 'input' como unsigned char en su lugar