Как напечатать 128-255 символов из целого числа в C?

Я все еще играю с C, чтобы понять, как это работает.

У меня проблемы с печатью символов из расширенной таблицы ASCII (128-255). Если я делаю printf("Â") (например), он печатает Â (все работает нормально). Однако, если я назначу переменную, например a = 194, а затем напечатаю переменную printf("%c",a), она напечатает � вместо Â.

Кстати нормально работает с 32-127 символами (например 35 печатает #)

-> Как я могу напечатать один из 128-255 символов из целого числа (десятичного или двоичного)? Любая помощь будет оценена.

Я использую gcc11.3 в Ubuntu 20.04.1 LTS.

Стандартной «расширенной таблицы ASCII» не существует. Ваш терминал, вероятно, использует кодировку UTF-8, которая использует несколько байтов для символов, отличных от ASCII.

interjay 08.07.2023 10:05
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
64
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вероятно, и ваш компилятор, и терминал используют 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 не печатается, поскольку Â может быть связана с тем, что ваш терминал не поддерживает этот набор символов.

Другие вопросы по теме