C — Символы, неправильно отображаемые на выходе

#c #character

#c #символ

Вопрос:

Я могу вставить è символ в свой исходный код, но он неправильно отображается при выводе в моей программе; вместо него появляется Þ символ.

è Символ в расширенном формате ASCII соответствует 138 .

è Символ в Юникоде соответствует 232 числу.

Þ Символ в расширенном формате ASCII соответствует 232 числу.

Þ Символ в Юникоде соответствует 222 числу.

Через отладчик можно заметить, что компилятор преобразует è с числом 232 и переводит целое число 138 как символ Š (набор для табуляции строк), в то время как в выходных данных номер символа 232 представлен как Þ , а номер символа 138 представлен как è .

Что происходит за кулисами?

Пример кода:

 #include <stdio.h>

int main (void)
{
    unsigned char a = 'è';
    unsigned char b = 138;

    printf ("Char a:% c  n", a);
    printf ("Char a:% d  n  n", a);
    printf ("Char b:% c  n", b);
    printf ("Char b:% d  n  n", b);

    return 0;
 }
  

Вывод:

 Char a: Þ
Char to: 232
    
Char b: 'è'
Char b: 138
  

Что видит отладчик:

 char a = 232 'è'
char b = 138 'Š'
  

Комментарии:

1. Какой код символа в вашем исходном коде? Получаете ли вы предупреждения компилятора типа «литерал с несколькими символами, определенный реализацией»?

2. Я не получаю никакого предупреждающего сообщения, я не знаю, что именно является моим «исходным кодом символа».

3. Но в настройках моей IDE Code :: Blocks в разделе «Редактор> Настройки кодировки» я нахожу, что запись «WINDOWS-1252» включена

Ответ №1:

Я предполагаю, что вы работаете в Windows.

Что происходит, так это то, что ваш исходный код написан в Юникоде, и поэтому è символ кодируется как число 232. Компилятор использует это значение в сгенерированной программе.

При выполнении вашей программы этот код отправляется в printf функцию в качестве параметра, но поскольку Windows использует расширенный ASCII, он интерпретируется как Þ при печати в консоли.

Вы можете закодировать свои файлы в расширенном ASCII, чтобы они содержали правильные символы.

Чтобы определить, какую кодировку использует ваша консоль, вы можете использовать это в Windows :

 #include <windows.h>
unsigned cp = GetConsoleOutputCP();
  

Вы можете изменить кодировку консоли с помощью этого :

 #include <windows.h>
SetConsoleOutputCP(1252); //Set console encoding to Windows 1252
SetConsoleOutputCP(65001); //Set console encoding to utf8
  

Это задает вывод на консоль, но не ввод на консоль, поэтому, если вам нужно иметь дело с расширенным пользовательским вводом ASCII, вам нужно использовать GetConsoleCP() и SetConsoleCP() для установки кодировки ввода.

Вы можете увидеть другие доступные коды кодовой страницы здесь.

Комментарии:

1. Да, я использую Windows. В настройках моей IDE Code :: Blocks в разделе «Редактор> Настройки кодировки» я нахожу, что запись «WINDOWS-1252» включена.

2. Можете ли вы распечатать результат unsigned cp = GetConsoleOutputCP(); см. learn.microsoft.com/en-us/windows/console/getconsoleoutputcp

3. Я получаю сообщение об ошибке: 'GetConsoleOutputCP' was not declared in this scope'

4. Да, вы должны включить Windows. h Я забыл упомянуть об этом, извините: #include <windows.h>

5. Я получаю результат 850

Ответ №2:

Просто проверьте, что если вы будете писать:

   printf("%dnn", 'è');
  

Затем вы увидите, что символа недостаточно, чтобы содержать правильное значение.

Комментарии:

1. Если я выполняю эту инструкцию, я получаю -24 , но я не думаю, что это происходит потому, что char не может содержать è значение, а потому, что целое число интерпретируется в printf как подписанное %d . Если моя char переменная объявлена как unsigned , она может содержать, а затем отображать все символы расширенной таблицы ASCII вплоть до 255 .