Я все еще играю с C, чтобы понять, как это работает.
У меня проблемы с печатью символов из расширенной таблицы ASCII (128-255). Если я делаю printf("Â") (например), он печатает Â (все работает нормально). Однако, если я назначу переменную, например a = 194, а затем напечатаю переменную printf("%c",a), она напечатает � вместо Â.
Кстати нормально работает с 32-127 символами (например 35 печатает #)
-> Как я могу напечатать один из 128-255 символов из целого числа (десятичного или двоичного)? Любая помощь будет оценена.
Я использую gcc11.3 в Ubuntu 20.04.1 LTS.





Вероятно, и ваш компилятор, и терминал используют UTF-8 для кодирования символов, отличных от ASCII.
Наборы символов и кодировки — обширная тема со множеством различных и несовместимых соглашений и реализаций. Â действительно кодируется как 194 в устаревших однобайтовых кодировках, таких как ISO8859-1 и Windows-1252. Это также номер символа в стандарте Unicode, который имеет более 100 000 различных кодовых точек для представления почти всех языков и наборов символов в мире.
Существуют разные способы представления этих символов в виде последовательностей байтов, наиболее распространенным из которых является UTF-8, используемый на 99% веб-страниц. Символы ASCII в диапазоне 32-127 представлены как одиночные байты, а символы с большей кодовой точкой используют от 2 до 4 байтов, ведущий байт в диапазоне от C2 до F4 и от 1 до 3 конечных байтов в диапазоне от 80 до BF . Â кодируется как C3 82, что означает, что "Â" на самом деле представляет собой 2-байтовую строку, идентичную "\xC3\x82".
Вы можете проверить это с помощью этого кода:
#include <stdio.h>
#include <string.h>
int main(void) {
const char *s = "Â";
int len = strlen(s);
printf("%s: len=%d, bytes = ", s, len);
for (int i = 0; i < len; i++) {
printf("%02hhX%c", s[i], " \n"[i == len - 1]);
}
return 0;
}
Вывод должен быть Â: len=2, bytes=C3 82.
Чтобы преобразовать символы, отличные от ASCII, в последовательности UTF-8 в выходных потоках, вы можете использовать функции локали из <locale.h> и вывод широких символов:
setlocale(LC_ALL, "en_US.UTF-8");
printf("%lc\n", 194);
Выход:
Â
Если локаль правильно настроена в терминале, вы можете выбрать локаль по умолчанию с помощью setlocale(LC_ALL, "");
Как указывает @interjay, а также написано в Википедии:
... Не существует формального определения «расширенного ASCII», и даже использование этого термина иногда подвергается критике, поскольку его можно ошибочно интерпретировать как означающее, что Американский национальный институт стандартов (ANSI) обновил свой ANSI X3.4-1986. стандарт для включения большего количества символов, или что термин идентифицирует единую однозначную кодировку, ни то, ни другое не имеет места. ...
🔗 Википедия: расширенный ASCII
Кроме того, вы можете напечатать Â при использовании printf("Â");, потому что вы используете его как строку. Â интерпретируется как символ Unicode (как вашим компилятором, так и вашим терминалом). Вы можете проверить это, скомпилировав следующее:
#include <stdio.h>
int main() {
char c = 'Â'; // set single character variable to be Â
printf("%c", c); // print the variable
return 0;
}
В моей системе мой компилятор выдает мне это предупреждение:
extended_ascii.c: In function ‘main’:
extended_ascii.c:4:18: warning: multi-character character constant [-Wmultichar]
4 | char c = 'Â'; // set single character variable to be Â
| ^~~
extended_ascii.c:4:18: warning: overflow in conversion from ‘int’ to ‘char’ changes value from ‘50050’ to ‘-126’ [-Woverflow]
что предполагает, что Â действительно является многобайтовым символом Unicode.
Вы также можете попробовать запустить этот код, чтобы проверить, во что расширяется Â:
#include <stdio.h>
int main() {
char c[] = "Â"; // set a string variable to be Â
for(int i = 0; c[i] != '\0'; i++) { // loop through each character
printf("%d ", c[i]); // print integer value of each character
}
return 0;
}
и его вывод:
-61 -126
Итак, ваш  — это многобайтовый символ, расширяющийся до этих значений. Если вы попытаетесь напечатать каждый из этих символов по отдельности, вы снова увидите ��. Таким образом, при совместной печати терминал будет интерпретировать это как символ Unicode и напечатать желаемый результат.
Кстати, я также нашел это в Интернете:
В наборе символов Windows-1252 код ASCII 194 представлен символом Â ...
Обратите внимание на использование набора символов Windows-1252. Хотя я понятия не имею об этом наборе символов, наиболее вероятная причина того, что 194 не печатается, поскольку Â может быть связана с тем, что ваш терминал не поддерживает этот набор символов.
Стандартной «расширенной таблицы ASCII» не существует. Ваш терминал, вероятно, использует кодировку UTF-8, которая использует несколько байтов для символов, отличных от ASCII.