Size: a a a

2020 February 17

DD

Davydov Denis in ru_ASUTP
[tux@nb tmp]$ cat ./test.c
#include <stdio.h>
#include <wchar.h>

int main() {
 wchar_t *str = L"приветhello";
 printf("%d, %d\n", wcslen(str), sizeof(str));
 return 0;
}
[tux@nb tmp]$ gcc ./test.c -o ./test && ./test
11, 8
источник

DD

Davydov Denis in ru_ASUTP
все четко
источник

RK

Rostyk Kudlak in ru_ASUTP
Пара слов про кодировки. Казалось бы, эта тема уже лет пятнадцать как должна быть всем полностью известна, а нет. Каждый раз как новый и приходится бесконечно одно и то же рассказывать, распутывая адскую кашу в головах.

Эти слова в основном про юникод. Все примеры кода для простоты на третьем питоне (во втором работа с юникодом очень плохо представлена, а в C++ с юникодом всё очень плохо).

Юникод (unicode) — это стандарт для представления и кодирования текстов на разных языках, в том числе «текстов» на «языке смайликов», например. В юникоде внутри программы (это важно, в самом конце будет объяснение, почему я упомянул программу) есть два уровня: логический, который оперирует символами (буквами), и физический, который оперирует байтами. В питоне вы работаете на логическом уровне, когда используете строки (объекты класса str, литералы с кавычками по бокам):

>>> t1 = 'жыр'
>>> len(t1)
3

Здесь мы видим строку в переменной t1, строка состоит из трёх русских букв, длина этой строки — 3. Это не три байта, это три символа! Юникодная строка (не только в питоне) — это по сути список юникодных символов, у каждого символа есть код в стандарте юникода. Для нашего примера коды символов можно посмотреть через функцию ord():

>>> [ord(x) for x in t1]
[1078, 1099, 1088]

В таком виде юникодный текст может крутиться внутри программы, но если мы хотим его передать наружу в виде байтов, то должны его закодировать так, чтобы на другом конце смогли корректно раскодировать. Кодирование на английском — encode, декодирование — decode. Сейчас самый стандартный способ кодирования — utf8, если вы видите фразу типа «текст в кодировке utf8», то это означает, что перед нами список (массив) байтов, не букв языка, а именно байтов. Кодирование делается так:

>>> u1 = t1.encode('utf8')
>>> len(u1)
6

Видим, что длина закодированного текста — шесть байтов. Как именно работает utf8, нам сейчас совершенно не интересно, главное, что после кодирования мы получаем байтовую строку, это по сути список чисел, каждое в диапазоне от 0 до 255 (этот тип называется bytes). При этом юникодная строка — это на самом деле список чисел в диапазоне от 0 до 1114111, только в питоне эта кухня скрыта, но вы должны понимать это, когда делаете len(s) на юникодной строке.

Обратный процесс — из байтов в юникодную строку — называется декодированием. Содержимое переменной u1 из примера выше такое:

>>> u1
b'\xd0\xb6\xd1\x8b\xd1\x80'

Чтобы его преобразовать в юникод, его нужно декодировать (помним: кодируем в байты, декодируем из байтов), в аргументе передаём название кодировки:

>>> u1.decode('utf8')
'жыр'

Помним главное, фраза «текст в кодировке utf8» означает, что у нас «текст» представляет собой список байтов, это ещё не юникодный текст, юникодным он станет после декодирования из кодировки utf8. Юникодная строка никак не закодирована, это строка из уже готовых для использования символов. В наш просвещённый 21 век в любой программе пора уже использовать тексты исключительно в юникоде.

Юникод — это центральный логический объект, для представления в байтах его нужно закодировать (encode), а набор байтов для использования нужно сначала декодировать (decode).

Кодировка utf8 позволяет закодировать любой юникодный символ. А вот, например, cp1251 — не любой, так как cp1251 — однобайтовая кодировка, то есть может использовать для кодирования символа только один байт, соответственно кодировка cp1251 понимает только очень ограниченный диапазон символов. Но это тема отдельного текста про ветхозаветные кодировки.

Мякотка — есть ещё третий уровень, который находится выше логического и физического — это визуальный. То, как символ или набор символов представляется на экране. Но это тоже тема отдельного текста, тут я и так увлёкся сверх меры.
источник

RK

Rostyk Kudlak in ru_ASUTP
он же прострочен
источник

RK

Rostyk Kudlak in ru_ASUTP
источник

RK

Rostyk Kudlak in ru_ASUTP
источник

MD

May Day in ru_ASUTP
Благодарю!
источник

KW

Konstantin Wilhelm in ru_ASUTP
Davydov Denis
все четко
Размер не в символах, а в байтах. Кириллица по 2 байта на символ, а латиница по одному? А если ещё умляуты с апокрифами добавить до кучи?
источник

RK

Rostyk Kudlak in ru_ASUTP
May Day
Благодарю!
источник

MD

May Day in ru_ASUTP
Премного благодарен!
источник

RK

Rostyk Kudlak in ru_ASUTP
но они как-то совсем разные на первый взгляд
источник

AT

Alexandre Terentiev in ru_ASUTP
Konstantin Wilhelm
Размер не в символах, а в байтах. Кириллица по 2 байта на символ, а латиница по одному? А если ещё умляуты с апокрифами добавить до кучи?
"Кириллица по 2 байта на символ, а латиница по одному?" в случае UTF-8, там аж до 4 байт на символ, если он редкий. А если UTF-16, то каждый символ по 2.
источник

KW

Konstantin Wilhelm in ru_ASUTP
Alexandre Terentiev
"Кириллица по 2 байта на символ, а латиница по одному?" в случае UTF-8, там аж до 4 байт на символ, если он редкий. А если UTF-16, то каждый символ по 2.
Вот это я и имел в виду, что "длина" символа переменная. И все это дело очень не однозначно. Но я в этом полный ламер
источник

DD

Davydov Denis in ru_ASUTP
[tux@nb tmp]$ cat ./test.c
#include <stdio.h>
#include <wchar.h>
#include <string.h>

int main() {
 wchar_t *wstr = L"zя𝄞";
 char *str = "zя𝄞";
 printf("%d, %d\n", wcslen(wstr), strlen(str));
 return 0;
}
[tux@nb tmp]$ gcc ./test.c -o ./test && ./test
3, 7
источник

DD

Davydov Denis in ru_ASUTP
получается английская буква - 1 байт, русская - 2 байта, а скрипичный ключ - 4 байта
источник

DD

Davydov Denis in ru_ASUTP
кстать, а телеграм его показал у всех? у меня в линуксе - да :)
источник

KW

Konstantin Wilhelm in ru_ASUTP
Davydov Denis
получается английская буква - 1 байт, русская - 2 байта, а скрипичный ключ - 4 байта
И после этого вы ещё хотите, чтобы все проги адекватно работали с текстом? 🤷‍♂
источник

DD

Davydov Denis in ru_ASUTP
Konstantin Wilhelm
И после этого вы ещё хотите, чтобы все проги адекватно работали с текстом? 🤷‍♂
ну работает же адекватно :)
источник

KW

Konstantin Wilhelm in ru_ASUTP
Davydov Denis
кстать, а телеграм его показал у всех? у меня в линуксе - да :)
У меня в андройде тоже показал
источник

KW

Konstantin Wilhelm in ru_ASUTP
Davydov Denis
ну работает же адекватно :)
Прям везде?
источник