Форум русскоязычного сообщества Ubuntu


Получить помощь и пообщаться с другими пользователями Ubuntu можно
на irc канале #ubuntu-ru в сети Freenode
и в Jabber конференции ubuntu@conference.jabber.ru

Автор Тема: Русские и английские символы через printf() в Си  (Прочитано 3295 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн KreshDiz

  • Автор темы
  • Новичок
  • *
  • Сообщений: 37
    • Просмотр профиля
Есть массив латинских и кириллических букв. Нужно вывести массив корректно printf'ом или другой стандартной функцией языка. Как это сделать чтобы не получить крокозябры?
#include<stdio.h>
void main(int argc, char argv[])
{
    char str[]={"Привет"};
    int i;
    //Так печатает полслова
    for(i=0; i<6; i++)
    printf("%c", str[i]);
    printf("\n");
    //Так печатает целое слово
    for(i=0; i<12; i++)
    printf("%c", str[i]);
    printf("\n");
    //Так печатает нормально
    for(i=0; i<12; i+=2)
    printf("1%c%c", str[i],str[i+1]);
    printf("\n");
    //Так печатает крокозябры
    for(i=0; i<12; i++)
    printf("1%c", str[i]);

   
}

« Последнее редактирование: 08 Декабря 2015, 20:40:27 от Azure »

shura1

  • Гость
Re: Русские и английские символы через printf()
« Ответ #1 : 08 Декабря 2015, 17:56:08 »
Короткий ответ - в С можно узнать длину массива и использовать его в качестве границы для индексной переменной -

for(i=0; i<sizeof(str); i++)
Длинный ответ заключает в себя знакомство с кодировками, с Юникоде и с UTF-8. Вот здесь перевод классической статьи.

Оффлайн alsoijw

  • Старожил
  • *
  • Сообщений: 4069
  • Fedora 25 GNOME 3 amd64
    • Просмотр профиля
Re: Русские и английские символы через printf()
« Ответ #2 : 08 Декабря 2015, 17:57:15 »
KreshDiz, кодировка файла, кодировка терминала, ось...
ЗЫ если хочешь печатать посимвольно, то печатай пока str
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

Оффлайн KreshDiz

  • Автор темы
  • Новичок
  • *
  • Сообщений: 37
    • Просмотр профиля
Re: Русские и английские символы через printf()
« Ответ #3 : 08 Декабря 2015, 18:05:16 »
Пишу пишу тему новую, нажимаю отправить, оказывается я случайно отправил её 15 минут назад, сейчас вопрос звучит чуть чуть иначе.
(Нажмите, чтобы показать/скрыть)

Вывести корректно узнав размер массива не составляет проблем. Но как корректно вывести(обработать) итый символ массива?
Linux Mint
Code::Blocks 13.12
GNU GCC Compiler

shura1

  • Гость
Re: Русские и английские символы через printf()
« Ответ #4 : 08 Декабря 2015, 18:10:48 »
Если вперемешку латинские и русские символы, то в С используя библиотеку по работе с Юникоде. Для Линукса это означает - UTF-8. Их много на самом деле. Если с прицелом на gnome и gtk, то glib. Хотя для простейших случаев, можно и обычными средствами С (используя wchar_t). Если проблема еще будет, то завтра посмотрю повнимательней.
« Последнее редактирование: 08 Декабря 2015, 18:16:26 от shura1 »

Оффлайн KreshDiz

  • Автор темы
  • Новичок
  • *
  • Сообщений: 37
    • Просмотр профиля
Re: Русские и английские символы через printf()
« Ответ #5 : 08 Декабря 2015, 18:16:28 »
Можете пример дать? не совсем понятно.
char str2[]={"wwwяяwяяяя"};
Как мне прочитать 4й элемент массива (буква я), не зная её размерности и размерности предыдущих символов?

Пользователь решил продолжить мысль 08 Декабря 2015, 18:20:32:
Компилятор не знает тип wchar_t.
« Последнее редактирование: 08 Декабря 2015, 18:20:32 от KreshDiz »

shura1

  • Гость
Re: Русские и английские символы через printf()
« Ответ #6 : 08 Декабря 2015, 19:33:47 »
Код: (c) [Выделить]
/* prog.c */
#include <wchar.h>
#include <stdio.h>
#include <locale.h>

wchar_t *s = L"hello, мир";

int main() {
    setlocale(LC_ALL, "ru_RU.UTF-8");
    wprintf(L"%ls\n", s);
    return 0;
}
Компиляция

gcc -Wall  -std=c99 prog.c
Запуск

./a.out
hello, мир

Пользователь решил продолжить мысль [time]08 Декабрь 2015, 20:43:05[/time]:
Это *простейший* случай. Для последовательной обработки посимвольно (я так понимаю из чисто познавательно-экспериментательных целей) - это все усложняться будет многократно. Правильное решение - пользоваться библиотеками (ну и да, поштудировать статью и википедию об Unicode и UTF-8). Экспериментировать лучше на яп более высокого уровня, чем С. Питон, Javascript не самые лучшие варианты, поскольку каждый имеет свою (единственно правильную) модель работы с Юникоде (Javascript, Java и С# схожи). Идеальные варианты (для работы с кодировками) - Ruby и Perl.

Чтоб понять сложность заданного вопроса рекомендую взглянуть (только взглянуть, не читать) на вот этот вопрос и *ответ* на stackoverflow
« Последнее редактирование: 08 Декабря 2015, 19:45:09 от shura1 »

Оффлайн alsoijw

  • Старожил
  • *
  • Сообщений: 4069
  • Fedora 25 GNOME 3 amd64
    • Просмотр профиля
Re: Русские и английские символы через printf()
« Ответ #7 : 08 Декабря 2015, 20:15:40 »
В vala(транслируется в c) сделано имхо достаточно удобно. unichar символ юникода. К примеру русская буква. Если перебирать строки по байтам, есть функция valid_char. Она проверяет является ли текущий байт символом. Метод length возвращает длину строки. Если нужно конкретно на c, то либо искать написанные функции либо писать свои. В википедии про одни символ говорится.
Цитировать
В общем случае варианты представления одного символа в кодировке UTF-8 выглядят так:

(1 байт)  0aaa aaaa
(2 байта) 110x xxxx 10xx xxxx
(3 байта) 1110 xxxx 10xx xxxx 10xx xxxx
(4 байта) 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
(5 байт)  1111 10xx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx
(6 байт)  1111 110x 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx 10xx xxxx
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

shura1

  • Гость
Re: Русские и английские символы через printf()
« Ответ #8 : 08 Декабря 2015, 20:28:51 »
Кстати да. vala - это обертка над библиотекой glib, которую я сразу рекомендовал. Насколько я понимаю (я сам vala не использовал) - синтаксис C#, а семантика С. То есть все должно быть достаточно открыто, было бы желание разобраться. Библиотека glib лежит в основе библиотеки gtk+, которая лежит в основе библиотек gnome и сinammon. Очень многофункциональная библиотека, в том числе реализующая работу со строками UTF-8.

UTF-8 - это одна из возможных реализаций стандарта Юникоде. Дефакто стандартная кодировка для Linux, MacOS, BSD. Стандартная для языка программирования go. Но перед тем, как начать разбираться с UTF-8, надо иметь понятие, хотя бы поверхностное, о кодировках вообще и кодировке Юникоде.

Оффлайн KreshDiz

  • Автор темы
  • Новичок
  • *
  • Сообщений: 37
    • Просмотр профиля
Re: Русские и английские символы через printf() в Си
« Ответ #9 : 08 Декабря 2015, 20:57:32 »
shura1, то что надо. Спасибо большое.
Направление понял и отыскал то что мне конкретно надо fwscanf(file, L"%lc", &sym)

shura1

  • Гость
Re: Русские и английские символы через printf() в Си
« Ответ #10 : 08 Декабря 2015, 21:25:42 »
На самом деле я даже сам не понимаю, как работает программа, которую я привел в качестве примера  ;D

Конкретно для меня не понятно, как вызов функции setlocale в теле функции main дает знать компилятору, что строковые константы L"..."  набраны в тексте программы в кодировке UTF-8. Самая, что ни на есть, черная магия (для меня, по крайней мере :)).
« Последнее редактирование: 08 Декабря 2015, 21:28:35 от shura1 »

 

Страница сгенерирована за 0.049 секунд. Запросов: 25.