один байт памяти. При выводе строк использовал спецификатор %28s и тд. Все слова были аккуратно выровнены по правому краю до того момента как я захотел их сделать по русски то есть кириллицей, буквы которой занимают уже два байта. Ну думал что поменяв цифры в спецификаторе смогу исправить новое положение слов точно по правому краю. А нет.... Как бы я не старался либо буквы пропадают (в случае с заданием минимального и максимального количества символов слова типа %21.8s) или же вовсе сдвигаются далеко вправо самые короткие слова а самые длинные где-то посередине стоят. Помогите пожалуйста разобраться с кириллицей?))
Или си не говорит по русски?)))
Я думаю дело в том, что буквы русские занимают 2 байта, а пробелы все еще 1, так что просто в 2 раза увеличить не получится
Тут вариант написать свою реализацию притфа
Ну я так и описал проблему
Надо либо самому писать, либо найти для этого либу, думаю уже ктото таким занимался. И не именно для русского искать, а для юникода
Видел где-то как делали это но уже не могу найти больше, может есть ссылка?))
#include <stdio.h> #include <stdlib.h> size_t mbslen(const char *str) { size_t len = strlen(str); size_t mb_len = 0; for (size_t offset = 0; offset < len; mb_len++, offset += mblen(str + offset, len - offset)); return mb_len; } #define SWIDTH(W, STR) (int)(strlen(STR) - mbslen(STR) + W) int main() { const char str1[] = "Hello world!"; const char str2[] = "Привет мир!"; printf("%*s\n", SWIDTH(30, str1), str1); printf("%*s\n", SWIDTH(30, str2), str2); }
Попробую разобраться и сделать. Спасибо.
А как кстати mblen определяет длину внутри? Мы же кодировку не передаем
Мне попадался этот вариант уже где-то в интернете... Ток я так и не понял его)) но теперь раз это поможет то я обязательно возьму на заметку и попытаюсь сделать
Оно старшие биты в каждом байте смотрит, можно было б и ручками написать, но лень, раз есть стандартное решение.
Его же можно как собственный заголовок подключить или лучше как функцию добавить для компилятора?
А чего тут понимать то? mbslen считает длину строки многобайтовых символов(работает только для случаев, если терминальный ноль занимает 1 байт), стрлен считает количество байт в строке, соответственно для ширины используется поправка в виде количества дополнительных байт для кодировки каждого многобайтного символа.
Не понял, если честно
Типа приходит ему строка в виде байтов ABCD. Как он понимает, что AB - это первая буква, а CD - вторая буква, а не например A - первая буква, BC - вторая буква, D - третья буква? Или ABCD это 1 китайская буква
Есть аски, в ней старший бит 0, следовательно mblen сразу определит количество байт 1, есть utf-8, там 0/110/1110, следовательно он понимает, что перед ним utf-8 и надо проверить оставшиеся байты на ожидаемый формат.
Разве можно по старшему биту однозначно определить верную кодировку? Их же много бывает разных. Не понятно как-то. Мне кажется что таким образом точно можно сказать только, ascii это или нет
Так нет, конечно он не все кодировки рассматривает, я думал у тебя вопрос, как он определяет аски от юникода А текущая мультибайтовая кодировка указывается в локали, там магии нет.
Осталось понадеяться что исходный код программы будет сохранен в кодировке, которая есть в системе, и что локаль установлена верно?)
Не, в примере который я написал выше нужно понадеяться, что это будет именно utf-8, т.к. для utf-16 или utf-32 нельзя стрлен юзать) А в целом да, верно, кодировка исходника должна соответствовать локали.
Поэтому я бы наверное если такая задача возникла, делал бы через gettext
Что на самом деле оправдано, т.к. для utf-16 и utf-32 такая проблема в принципе возникнуть не может.
*ucs2, т.к. для utf-16 гипотетически может, т.к. там суррогатные пары есть.
А если в тексте еще и BOM есть? Отбросит?
Так Бом он исключительно для тебя, чтобы ты понял, с каким файлом работаешь, его ручками обрабатывать надо
Обсуждают сегодня