Как выводить русские символы в си?

Привет, помогите понять, как это работает и как исправить
#include <stdio.h>

int main() {
  char *a = "Привет, мир";
  printf("%c\n", *a);
  printf("%s\n", a);
  for (; *a != '\0'; a++) {
    printf("%c", *a);
    }
    return 0;
}

вывод:
�
Привет, мир
Привет, мир
  • Вопрос задан
  • 1780 просмотров
Решения вопроса 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
как это работает

Поскольку русский -- не часть ASCII, работает это по-разному в зависимости от кодировки. Если предположить, что исходник в UTF-8, то русские символы закодированы двумя байтами, а %c выводит только один. Если на одном выведенном байте остановиться -- получится фигня с вопросом. Но если вывести подряд все байты многобайтового символа -- получится этот символ.

как исправить

вариантов несколько. Самый простой -- выводить строки целиком. Если надо выводить посимвольно, можно узнавать количество байт в представлении одного символа функцией mblen, типа того:
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
  char *a = "Привет, мир";
  int s;
  setlocale(LC_ALL, "");
  for (; *a != '\0'; a+=s) {
    s = mblen(a, strlen(a));
    printf("%.*s-", s, a);
    }
    return 0;
}

Здесь setlocale нужен для того, чтобы mblen понял, в какой кодировке символы на входе. Локаль в момент выполнения должна быть совместимой с кодировкой исходника в момент компиляции, если это условие не выполняется, работать будет неправильно.

Ещё вариант -- работать не с многобайтовой кодировкой а с wchar_t:
#include <locale.h>
#include <stdio.h>
#include <stddef.h>

int main() {
  wchar_t *a = L"Привет, мир";
  setlocale(LC_ALL, "");
  for (; *a != '\0'; a++) {
    printf("%lc-", *a);
    }
    return 0;
}

Здесь setlocale нужен для другого: он говорит внутренностям printf в какую локаль выполняется вывод чтобы в неё конвертировать wchar_t. Если локаль во время выполнения не будет соответствовать кодировке исходника, код всё равно будет работать.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы