Чтение символов вне ASCII
Вопрос
Мой друг показал мне ситуацию, когда чтение символов приводило к неожиданному поведению. Чтение символа «¤» привело к падению его программы. Я смог сделать вывод, что «¤» - это 164 десятичное число, поэтому оно находится за пределами диапазона ASCII.
Мы заметили поведение на '¤', но любой символ > 127, кажется, показывает проблему. Вопрос в том, как мы могли бы надежно читать такие символы char за 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
Решение
В вашей системе используется кодировка символов UTF-8 (как и должно быть), поэтому символ '¤' заставляет вашу программу прочитать последовательность байтов C2 A4
. Поскольку char
составляет один байт, он читает их по одному. Посмотрите на wchar_t
и соответствующие потоки wcin
и wcout
для чтения многобайтовых символов, хотя я не знаю, какие кодировки они поддерживают или как они играть с локалями.
Кроме того, ваша программа выводит недопустимый UTF-8, так что вы действительно не должны видеть эти два символа - я получаю знаки вопроса в моей системе.
(Это глупый и несколько оффтопный, но ваш while (input)
должен быть while (cin)
, иначе вы получите бесконечный цикл.) р>
Другие советы
Трудно сказать, почему программа вашего друга падает, не видя код, но это может быть потому, что вы используете char как индекс в массиве. Поскольку символы за пределами обычного диапазона ASCII превысят лимит подписанного символа, символ будет отрицательным.
вместо этого объявите 'input' как неподписанный символ