Задать вопрос

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

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

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

вывод:
�
Привет, мир
Привет, мир
  • Вопрос задан
  • 3616 просмотров
Подписаться 2 Простой Комментировать
Решения вопроса 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. Если локаль во время выполнения не будет соответствовать кодировке исходника, код всё равно будет работать.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

Похожие вопросы