LINUX.ORG.RU

Правильный(???) стиль работы со строковыми данными на С

 ,


2

4

Иногда (прямо сейчас) приходится обрабатыавть строки на C.
Меня коробит от громоздкости операций выделения памяти, конкатенации и самое главное это snprintf с проблемой размера буфера под конечную строку, гигантское поле для выращивания вских мемориликов по невнимательности.

К примеру, размеры mult1_str, mult2_str и equal_str известны, нужно выделить память под всю строку:

snprintf(
    buf,
    buflen,
    "%s miltilple %s equals %s",
    mult1_str,
    mult2_str,
    equal_str
    );
варианты:
- махнуть шашкой и сделать килобайт на стеке ( ((( )
- ничем не размахивать и посчитать руками. (еще хуже)
- написать функцию которая будет вычислять длину «%s miltilple %s equals %s» без символов подстановки (уже лучше)
- отказаться от snprintf и собирать строку пачкой конкатенаций с аллокациями памяти и прочим...

А как делаешь ты?


Почему бы не попробовать работать со строками на языке, более подходящим для этого? Скажем на lua или на guile? Они, насколько мне известно, дружат с Си. С помощью такого подхода можно быстро добавлять требуемые фичи, не заморачиваясь с выделениями памяти и прочими прелестями низкоуровневого языка.

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

А с чего ты взял, что С не подходит для работы со строками? Даже регекспы есть. Что еще нужно-то?

Просто не пользуйся хрюникодом и будет тебе счастье!

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

Lua плох для текста!

varfolomey:~$ lua
> string.sub("Привет мир!", 1, 1)
�

varfolomey:~$ python3
>>> "Привет мир!"[0]
'П'

varfolomey:~$ guile
scheme@(guile-user)> (substring "Привет мир!" 0 1)
$1 = "П"

Deleted
()
Ответ на: комментарий от Deleted
> print(string.sub("Привет мир!",1,2))
П
> 

Нада 2 байта выводить ::) Ну не плох прям, но да вот так с ходу если, то осадочек остаётся

Deleted
()
Последнее исправление: Deleted (всего исправлений: 4)
Ответ на: комментарий от Deleted
> print(string.sub("Привет мир!",0,1)) --- like char 
�
> print(string.sub("Привет мир!",0,2)) --- like char[1] or wchar_t
П
> print(string.sub("Привет мир!",0,3)) --- like char[2]
П�
> print(string.sub("Привет мир!",0,4)) --- like char[3] ~wchar_t[1]
Пр
> 

Не?

Или так

> print(string.sub("✌ Привет мир!",0,3)) --- char[2]
✌
> 

UPD:

1,2

Аааааааааааааааа ахахах ну да ))))))))))))))

P.S. Этот маркдаун с переносами меня заколебал

Deleted
()
Последнее исправление: Deleted (всего исправлений: 6)
Ответ на: комментарий от Deleted

Во всех предыдущих обсуждениях на простой вопрос «зачем нужно [0]?» ничего кроме кроссвордов не придумывалось, да и то муть, если дальше копать. Что в utf-ах, что в ucs-ах есть combining, и ничего с этим не поделать, таков уникод. Поэтому обработка текста сводится к двум ситуациям.

1) Это какой-то миниязычок на ascii, тогда проблемы нет. Пример: field=«string:optional:utf-8:default=фыва» в качестве валидатора. При этом находить leading/trailing пробелы и прочие известные последовательности из ascii-сета или из конкретного набора все еще можно, без проблем. Даже если в потоке есть utf, ведь это просто уникальные оффсет-независимые последовательности.

2) Это полноценный текст с эмодзями, кандзей, биди и прочим гражданским гуаном, к которому нужны как минимум icu и icu-compatible regexp'ы с соотв.классами и четким пониманием, что именно требуется найти или сделать. И тут никакими [i] не обойтись просто так. И i++ тут не имеет смысла большего, чем i = next_utf8_position(s, i). Можно конечно взять таблицу классов и руками перебрать кодепоинты, но то же самое можно сделать и для utf-8 буфера. i=523 здесь не имеет смысла, только i++, только поток.

Языки и либы, которые якобы умеют в индексирование символов текста, на самом деле в него не умеют и покрывают лишь ненужные непортабельные юзкейсы. В основном строки тупо проверяют на валидность и кладут как есть, либо режут по заранее известным последовательностям и потом уже кладут. Но лабы по «выкуси третью русскую букву» на [i]-языках делать бесспорно проще.

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

Да я не спорю, [i] вообще ничего не решает, длинна символов разная, и тут как бэ надо октеты символа сначала узнавать, а уже потом символ выводить в нужном диапазоне. А тот что код выше, это я к тому что там по байту берётся, чисто лирика и улыбалово ))

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

Царь, это ты? А что ты пишешь собсна? Такое ощущение что мессенджер для СИИ который на ракетах летает.

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

Нет, разве я похож? (Разве что по стене текста.)

Наблюдения чисто из практики.

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

Просто я тут давно, и сколько было тредов про сишкины строки, столько было мнений, что [i] спасет всех от уникода (нет). Не регистранту выше камень в огород, просто многие действительно так считают.

Давно это было, я просил бисти прикрепить знатный срач с выводами, и он даже прикрепил, но потом открепил. Зачем - хз, топик весьма сложный и много стереотипов.

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

Это полноценный текст с эмодзями, кандзей, биди и прочим гражданским гуаном

Просто смотри текст как на данные которые нужно обрабатывать и всё. К одним данным ‘a-z’ у нас прямой доступ по нумерации, к другим данным ‘00000000-0010FFFF’ у нас доступ по вычислению длинн элементов данных и сёёё )))

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

Пиши [[i]]. Ну я и не отрицаю, что применимость этому есть, конечно есть. Как и любой другой подход или формат данных это имеет свои удобные стороны.

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

ХЗ, лично меня С полностью устраивает. И, что самое интересное, в отличие от этого зоопарка языков, С — абсолютно универсальный! У меня и микроконтроллеры при помощи С прошиваются, и мелкие утилитки на нем, и библиотечки (в т.ч. для обработки изображений), и веб-сервисы, и куча всяких демонов... Не говорю уже о модулях ядра!

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

Вдруг он и есть Линус, который отрывается на ЛОРе от души.

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