LINUX.ORG.RU

wchar_t

 


3

2

ЧЯДНТ?

$ echo $LANG
en_US.UTF-8

$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
$ cat src.c 
#include <stdio.h>
#include <wchar.h>
int main ()
{
   wchar_t word[] = L"Дробь";
   wprintf(L"%s\n", word);
   return 0;
}
$ gcc src.c
$
$./a.out
<тут-какойто-непонятный-символ>
★★★★★
Ответ на: комментарий от Deleted

всё не так. Криво всё и костыльно. Было-бы годно для совместимости с маздаем, но оно и не совместимо.

Я не очень понимаю, зачем и кому это нужно юзать.

drBatty ★★
()
Ответ на: комментарий от drBatty

Как видите, в линуксе всё работает прекрасно, любые юникодные символы прямо в исходнике можно ставить. Проблемы только у маздая. Но вы не переживайте, у нас маздайные исходники еще реже работают.

af5 ★★★★★
() автор топика
Ответ на: комментарий от af5

Как видите, в линуксе всё работает прекрасно, любые юникодные символы прямо в исходнике можно ставить.

я предпочитаю as is, без этих твоих L. Мне вообще непонятно, на кой ляд нужны символы, которые втрое больше чем надо? Они ведь ещё и втрое _дольше_.

drBatty ★★
()
Ответ на: комментарий от af5

в линуксе всё работает прекрасно

Пока версия компилятора не сменится. Поубивал бы. Стандарты не просто так пишут.

x3al ★★★★★
()
Ответ на: комментарий от drBatty

Мне вообще непонятно, на кой ляд нужны символы, которые втрое больше чем надо?

Сам ведь упомянул значки биохазарда, где ты их в аски найдешь

af5 ★★★★★
() автор топика
Ответ на: комментарий от x3al

Пока версия компилятора не сменится. Поубивал бы. Стандарты не просто так пишут.

Стандарты нужны чтобы их ... :)

af5 ★★★★★
() автор топика
Ответ на: комментарий от af5

Чтобы их нарушать с умом, а не просто потому, что сейчас работает. Тем более 90% юникода в исходниках появляются из-за того, что кодер неосилил gettext.

x3al ★★★★★
()
Ответ на: комментарий от drBatty

я предпочитаю as is, без этих твоих L

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

в utf-8, очевидно же!

3 байт даже в нём. 4 в массиве. Не вижу причин для беспокойства, наоборот, хорошо что не UTF-16

af5 ★★★★★
() автор топика

Резюме:
1)Адресная арифметика работает только с полноценными массивами (одинаковых элементов).
2)Аски-чары и однобайтовые нац.кодировки естественным образом образуют массивы чаров, на которых соответственно работает адресная арифметика (и все привыкли к этому как к чему-то само собой разумеющемуся)
3)UTF-8 чары не образуют массив, т.к. имеют разный размер, соответственно адресная арифметика с ними не работает и работать не может, нужен воркэраунд с предварительной конвертацией их в 4-байтный wchar_t, тогда будет адресная арифметика
4)В линуксе использовать wchar_t имеет смысл только если надо массив юникода, иначе можно обойтись без wchar_t и L
Всегда ваш,
кэп

af5 ★★★★★
() автор топика
Ответ на: комментарий от af5

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

такая адресная арифметика редко нужна. Обычно нужна другая: нужно знать, сколько например байт занимает строка. И это нужно знать именно в utf-8.

drBatty ★★
()
Ответ на: комментарий от af5

воркэраунд с предварительной конвертацией их в 4-байтный wchar_t, тогда будет адресная арифметика

Тяжелый случай, коллеги, рекомендую срочную эвтаназию.

arturpub ★★
()
Ответ на: комментарий от arturpub

beastie, ты же вроде сюда ходишь, может стоит прикрепить заместо или рядом с остальными tcl/tk? На моей недолгой памяти это вроде уже четвертый раунд wchar_t vs. unicode vs. адресация отдельных букв, и как всегда мало кто понимает о чем речь. Кстати прошлый так и не прикрепили, хотя я просил, и он был на порядок добрее и информативнее.

arturpub ★★
()
Ответ на: комментарий от drBatty

Да пока ни в каких не нужна, чисто теоретический вопрос в рамках изучения C, не оставлять же его невыясненным

af5 ★★★★★
() автор топика
Ответ на: комментарий от af5

Да пока ни в каких не нужна, чисто теоретический вопрос в рамках изучения C

ну если чисто теоретически, то моё мнение таково:

1. тип wchar_t не нужен. Его НЕ следует использовать, и он по ошибке попал в стандарт. Теперь его оттуда уже не выкинуть.

2. строки wchar_t порождают огромное количество проблем, и ничего не решают. Было-бы неплохо, если-бы этот тип был не просто _широким_, а _фиксированным_. К сожалению, это не так. Он тоже плавающий, и меняется в разных компиляторах и на разных платформах.

3. тип wchar_t не совпадает с типом строк на системе. Потому его требуется конвертировать и на входе и на выходе. Потери на конвертирования практически всегда выше профита от упрощения арифметики.

4. сама арифметика с символами нужна чрезвычайно редко. Символы встречаются не в сферическом вакууме, а в словах естественного языка. В этих словах нет никакой привязки к позиции буквы. Имеет смысл лишь поиск похожих/одинаковых подстрок в слове, а этот поиск работает одинаково при любой кодировке. Арифметика нужна лишь в случае, если нужно узнать размер всего слова/строки. Но в этом случае тоже нет никакой разницы, ибо считаем мы всё равно ВСЕГДА в char'ах. Проблемы как раз с другими типами, которые жёстко с char не связаны (например с wchar_t).

5. Даже в русском тексте, около половины символов русскими буквами НЕ являются (пробелы, пунктуация, цифры, и т.д.). Потому средняя длина символа много меньше 2х байт. Выделять для них 4 байта — расточительство. Это требует втрое больше памяти и втрое больше времени. Хотя и то и другое подешевело, но и того и другого всё равно НЕ ХВАТАЕТ.

В итоге, wchar_t годно лишь для каких-то очень специфических юзкейсов, например для программ для разгадывания кроссвордов. Да и то лишь как внутренний формат.

drBatty ★★
()
Ответ на: комментарий от drBatty

и да, средняя длинна слова в русском языке равна 5.28 символов. В utf8 это 84 бита. Потому, практически все слова русского языка(а тем более английского) влезают в один современный 128и битный регистр CPU. А вот UTF-32 уже не лезет. Потому слова в UTF-32 обрабатываются на современном CPU в десятки, и даже сотни раз медленнее(потому-что большинство слов длиннее 4х букв).

drBatty ★★
()
Ответ на: комментарий от drBatty

Золотые слова, док. Главный пункт это 4, при кажущейся простоте произвольного доступа, он [доступ] совершенно не имеет смысла, ни с точки зрения уникодной модели, ни с лингвистической. Мы оперируем размерами буферов, в которые по-любому-последовательно считываем кодированные потоки, количество представленных потоком букв и модификаторов мало кого интересует.

arturpub ★★
()
Ответ на: комментарий от drBatty

кстати, еще одна багофича: printf и wprintf не работают вместе. Может это как-то фиксится, хз.

af5 ★★★★★
() автор топика
Ответ на: комментарий от arturpub

Главный пункт это 4, при кажущейся простоте произвольного доступа, он [доступ] совершенно не имеет смысла, ни с точки зрения уникодной модели, ни с лингвистической.

ага. Разве что в кроссвордах, других примеров мне не придумать даже.

drBatty ★★
()
Ответ на: комментарий от af5

printf и wprintf не работают вместе. Может это как-то фиксится, хз.

попробуй походить на костылях и без костылей _одновременно_.

по ссылке arturpub правильно написано: это UB. Файл может или с w-костылём открываться, или без.

drBatty ★★
()
Ответ на: комментарий от drBatty

Да если и придумать, знай храни строки вместо букв. Языков-то уж почти не осталось с отдельно-стоящим типом мифического «символа».

arturpub ★★
()
Ответ на: комментарий от arturpub

Да если и придумать, знай храни строки вместо букв.

ну дык так и делают например в FS Linux. Оно получается куда как быстрее и безглючнее, чем в маздае, в котором приходится помнить о том, что буква это не просто биты, в буква, и что «Ф» == «ф».

ЗЫЖ регистрозависимость — это ещё один случай, когда wchar_t могли-бы помочь. Но на практике всё равно быстрее даже в этом случае использовать utf-8. И разгадка проста: уже много лет строки сравниваются не по одному символу, а сразу по нескольким, одновременно. Причём сравнение может быть и нечётким. Например можно искать (и сравнивать) не просто «Ф», а регулярное выражение "(Ф|ф)". Это медленнее. И всё равно быстрее, если буквы маленькие, и их можно много сразу проверять. Гуглить shift-and.

drBatty ★★
()
Ответ на: комментарий от drBatty

Масла в огонь подливает еще unicode titlecase, со всякими Dz, ῼ, а также немцы, для которых ae = ä, ß = ss — это вполне нормально и повсеместно. Так что надеяться на простой матчинг без регулярок просто глупо, никакой wchar_t не поможет.

arturpub ★★
()
Ответ на: комментарий от af5

кстати, еще одна багофича: printf и wprintf не работают вместе. Может это как-то фиксится, хз.

Например, вот так:

#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>
#include <locale.h>

int main() 
{
    setlocale(LC_ALL,"");

    printf("No printing!\n");
    printf("%ls", L"Printing!\n");
    printf("%ls", L"Wide char\n");
    printf("ASCII\n");
    return 0;
}

Из мана по ссылке:

NOTES Wide-character output to a byte oriented stream can be performed through the fprintf(3) function with the %lc and %ls directives.

gag ★★★★★
()
Ответ на: комментарий от drBatty

printf и wprintf не работают вместе. Может это как-то фиксится, хз.

попробуй походить на костылях и без костылей _одновременно_.

по ссылке arturpub правильно написано: это UB. Файл может или с w-костылём открываться, или без.

И тем не менее, хотя можно открыть или так, или так, но использовать и для char, и для wchar (см. выше).

gag ★★★★★
()
Последнее исправление: gag (всего исправлений: 1)
Ответ на: комментарий от af5

Да пока ни в каких не нужна, чисто теоретический вопрос в рамках изучения C, не оставлять же его невыясненным

В самом простом случае: произвести некое действие над каждым символом в строке (например, подсчитать кол-во вхождения). Для этого нужно пройтись по всем символам в строке. В glib для этого можно использовать g_utf8_next_char.

gag ★★★★★
()
Ответ на: комментарий от af5

хм... что же получается, wprintf тогда зачем нужен?

Тем, кто не будет использовать printf вообще или редко:

wprintf(L"Wide\n");
wprintf(L"%s", "normal\n");

gag ★★★★★
()
Последнее исправление: gag (всего исправлений: 1)
Ответ на: комментарий от af5

g_ это от слова гном?

GIMP (GNU...) -> GTK (GIMP Toolkit) -> GLib (GTK Library?). Можно только спорить, если никто не найдёт ссылки на цитату разработчиков.

gag ★★★★★
()
Ответ на: комментарий от arturpub

Так что надеяться на простой матчинг без регулярок просто глупо, никакой wchar_t не поможет.

это ещё полбеды, у регулярок тоже полно проблем. В частности . (точка) не совпадает с НЕСИМВОЛАМИ. А и не должна совпадать. Но они таки есть, в любой utf.

drBatty ★★
()
Ответ на: комментарий от gag

В самом простом случае: произвести некое действие над каждым символом в строке (например, подсчитать кол-во вхождения).

не нужен. Что тебе мешает искать \321\204 а не «ф»?

drBatty ★★
()
Ответ на: комментарий от drBatty

Измерить длину в символах, чтобы вычислить сколько места строка займёт на экране. Оттяпать последний символ при нажатии backspace.

thesame ★★★★
()
Ответ на: комментарий от thesame

Измерить длину в символах, чтобы вычислить сколько места строка займёт на экране.

уже много лет размер строки прямо не зависит от символов. Буква «Щ» шире, чем «и», хотя каждая по 2 байта в utf-8.

Оттяпать последний символ при нажатии backspace.

man scanf(3), getline(3), и многое другое. Я что-то не помню, что-бы этим надо было заниматься за последние 20 лет.

Ну если уж так хочется, man regex(3), и найди там RE /.$/, это и будет последний символ в текущей локали.

drBatty ★★
()
Ответ на: комментарий от drBatty

уже много лет размер строки прямо не зависит от символов. Буква «Щ» шире, чем «и», хотя каждая по 2 байта в utf-8.

Я про консольку.

man scanf(3), getline(3), и многое другое

но им-то внутри всё равно приходится этим заниматься.

Не подумай что я с тобой спорю, просто ты не мог придумать где это может понадобиться, и я тебе помог, потому что сам видел программы которые на этом лажают.

thesame ★★★★
()
Ответ на: комментарий от thesame

потому что сам видел программы которые на этом лажают.

эти проблемы в принципе не имеют нормального решения. И utf-32 тоже ничего принципиально не решает. Только загоняет проблему внутрь.

drBatty ★★
()
Ответ на: комментарий от arturpub

Языков-то уж почти не осталось с отдельно-стоящим типом мифического «символа».

Не знаю что ты этим хочешь сказать, но все языки с нативной поддержкой юникода отлично работают посимвольно — позволяют делать посимвольную итерацию по строке, узнавать длину строки в символах итп.

true_admin ★★★★★
()
19 августа 2013 г.
Ответ на: комментарий от drBatty

Вау, этож надо же - даже drBatty перечеркнули! Настало время валить из этого гадюшника на Rulinux!

anonymous
()
Ответ на: комментарий от true_admin

но все языки с нативной поддержкой юникода отлично работают посимвольно — позволяют делать посимвольную итерацию по строке, узнавать длину строки в символах итп.

например? (code point != character)

dzidzitop ★★
()
Ответ на: комментарий от true_admin

char представляет code point только еслі sizeof(char) == 4

А так в Unicode character ź: - может быть представлен однім code point (u+017a) - может быть представлен двумя code points (U+007A U+0301)

С точкі зренія Unicode эті представленія эквівалентны.

dzidzitop ★★
()
Ответ на: комментарий от dzidzitop

Я это понимаю (об этом весь тред вещали :)). Тут два момента:

1) Даже если её не делать нормализации то итерация по юникодной строке всё равно будет корректной: ЯП с нативным юникодом не разорвёт двухбайтовый символ на два куска. Другое дело что всякие ñ мы хотим видеть в виде одного символа, а не двух . Об этом ниже.

2) Кмк, нормальная практика это делать нормализацию чтобы не было неоднозначности. Я не знаю как внутрях оно работает, лень читать доки. Но вот эксперимент с питоном показал что IO модуль нормализует юникод. Как минимум, если записать ñ в виде двух байт и потом считать как _текст_ то на выходе будет один символ. Я считаю это весьма разумным поведением. Если нужно, можно исключить преобразование, но это надо будет делать явно.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

ЯП с нативным юникодом не разорвёт двухбайтовый символ на два куска.

проблема также і в том, что в UTF16 бывают code points которые занимают и по два двухбайтовых char (см. surrogate pairs)

dzidzitop

anonymous
()
Ответ на: комментарий от anonymous

В питоне это решили просто — запретили эти самые сурогаты :).

Вообще, по-моему, юникодные стандарты это фейл. Все эти навороты привели к гигантскому кол-ву проблем.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

В питоне это решили просто — запретили эти самые сурогаты :).

там UCS-2?

Все эти навороты привели к гигантскому кол-ву проблем.

+1

dzidzitop ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.