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 и собирать строку пачкой конкатенаций с аллокациями памяти и прочим...

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


Ответ на: комментарий от 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
()
Ответ на: комментарий от anonymous

Переполнение же.

Хотя glibc какой-то странной фигнёй занимается, и падает с EOVERFLOW если длина результата была бы > INT_MAX - 32.

Этот код в лучшем случае непортабелен и зависит от недокументированной детали реализации.

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

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

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

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

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

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

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

Ай, пля. Вот поэтому сразу по рукам надо бить за int в size_t. Мне даже в голову не придет такое написать, а когда читаешь думаешь ну ладно допустим. И вот ты уже допустил. Спасибо.

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

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

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

Именно. Это бы означало, что кто-то изменил форматную строку либо данные для неё, что есть UB.

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

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat
int n = printf("Hello, World!\n");

if (n < 0) {
    int ne = fprintf(stderr, "printf(): %s\n", strerror(errno));
    if (ne < 0) {
        char buf[1024] = "printf(): fprintf(stderr): ", *p;
        strncat(buf, strerror(errno), sizeof(buf)-1);
        p = buf;
        size_t l = strlen(buf);
        while (l > 0) {
            int nw = write(STDERR_FILENO, p, l);
            if (nw < 0) {
                syslog(LOG_ERR | LOG_USER, "DAD HALP");
                abort();
            }
            l -= nw;
            p += nw;
        }
    }
}
return (n < 0);
anonymous
()
Ответ на: комментарий от slovazap

Отвечай на прямой вопрос (С vs С++).

C - это язык, для запуска кода которого на гольном железе достаточно установить указатель стека. Для запуска и полноценой работы C++ кода требуется предварительная инициализация runtime-среды - нужен какой-то уже реализованный механизм «кучи» для хранения объектов, нужно предварительно инициализировать static-объекты. Ну т.е. чтобы запустить C++ код на гольном железе, предварительно должен быть запущен код, подготовленный си-шным программистом со знаниями «внутренностей» конкретного С++ компилятора (та же самая картинка, что и в случае с микропитоном).

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

Для более подробных обсуждений, если тебе очень хочется «поглумиться» над отсталыми ретроградами-сишниками (с твоей точки зрения), лучше открой отдельную тему. Может, туда заглянут грамотные люди, которым не лень тратить свое время на подобные обсуждения, и тебе всё растолкуют на пальцах. Могу только еще добавить, что если вдруг в одначасье вымрут все сишники - основательно так и навсегда :) - то следом загнутся все диалекты UNIX-систем, Linux, да и Windows тоже. Всё придется начинать «с нуля». На C очень много чего завязано.

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

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

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

Или ты думаешь что программист на микропитоне пишет на самом деле на C?

программист на QML на самом деле не пишет на C++. QML понятней, проще, безопасней, UI летает по сравннию с убогими плюсовыми виджетами. Следуя вашей логике (вернее отсутствию её) можно сказать что C++ не нужен вообще.

целые ядра на C++ пишут

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

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

QML понятней, проще, безопасней, UI летает по сравннию с убогими плюсовыми виджетами

давно пора плюсовое легаси на Rust переписать

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

Ниша для чего? Для уровня хеллоуворлд?

Да хотя бы даже.

Какие тут эмоции

Вот эти:

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

Если задача качественно и быстро решается на, например, микропитоне, то сектантство - это выбрать C.

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

Следуя вашей логике (вернее отсутствию её) можно сказать что C++ не нужен вообще.

Тут действительно отсутствие логики, только не у меня.

этого мусора навалом на гитхабе, только попроси плюсовика сыграть мурку

То ли дело сишники, ага. Каждый второй сделал готовый продукт на продажу.

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

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

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

Если ты хочешь сказать что не всегда микропитон может заменить C, то это было очевидно и так.

мне непонятно - для чего нужен C++ если если есть С и Rust. С это настоящее, Rust возможное будущее, а C++ для чего ? То что на нём что-то написано - это не аргумент.

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

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

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

Отвечай на прямой вопрос (С vs С++).

Я этого не писал, не надо мои цитаты подменять. Ты мне не ответил на:

Для начала, о какой именно реализации строк вы изволите столько снисходительно разглагольствовать?

И предупреждаю: когда ответишь, это будет только начало того как я буду тебя возить лицом по луже твоей безграмотности, потому что наглому безграмотному школию не написавшему ни строчки ни на C, ни на C++, нельзя прощать разглагольствования о применимости языков, да ещё и поучения с использованием лживых фактов.

Для запуска и полноценой работы C++ кода требуется предварительная инициализация runtime-среды - нужен какой-то уже реализованный механизм «кучи» для хранения объектов

Я тебе ещё раз говорю - нет, не нужен. Что ещё придумаешь?

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

Считай это ответом на твои заявления:

Серьёзно, как можно прямо заявить что «надёжно писать на C может далеко не каждый», и при этом спорить с тем что C не должен использоваться нигде.

Хотя бы понимание того что C++ может всё что может C у вас должно быть?

То есть по сути у вас возражений нет, я понял. Вся аргументация «но на C же что-то написано!».

нужен какой-то уже реализованный механизм «кучи» для хранения объектов

Я тебе ещё раз говорю - нет, не нужен...

Ну раз «куча» не нужна, то это уже будет не полноценный C++, а что-то кастрированное - причем процесс «кастрации» и последующего «лечения» напрочь убьет все «прелести» C++ в отношении чистого C. Хотя и в оригинальном, «некастрированном» варианте особых прелестей у С++ по части разработки системных задач не видать.

P.S. По поводу строчек: «String представляет собой строку, размещённую в куче».

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

На микроконтроллерах и С кастрированный. Так что C не настоящий и не годится для ембеда. Набросил.

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

А ты не сравнивай изменение размерности числовых типов, или там отсутствие чисел с плавающей точкой в каком-нибудь микроконтроллере - и невозможность создать объект в объектно-ориентированном языке ))

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

Считай это ответом на твои заявления

Это не ответ, это уже истерика из-за отсутствия аргументов, но панического желания сохранить лицо, хотя уже поздно.

Я повторяю вопрос: о какой именно реализации строк вы имели неосторожность заявить что они выделяются исключительно на куче?

Ну раз «куча» не нужна, то это уже будет не полноценный C++

Второй вопрос - в чём вы измеряете полноценность, и почему она зависит от наличия кучи?

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

Вся аргументация «но на C же что-то написано!».

Ну так авторы микропитона дураки без образования или нет?

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

C++ нужен тем, для кого C это прошлое

когда не было Rust еще можно было это понять, но сейчас тех кто использует С++ надо изолировать от компьютеров на законодательном уровне

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

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

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

в чём вы измеряете полноценность, и почему она зависит от наличия кучи?

Ну если C++ без оператора new - это для вас полноценный язык, имеющий какие-то преимущества над С ...

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

Ну если C++ без оператора new

С чего ты взял что без? Что, по-твоему, делает new? Как он связан с кучей? Как часто он, по-твоему, используется в современном C++?

это для вас полноценный язык, имеющий какие-то преимущества над С …

Абсолютно. Тебе есть что возразить?

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

... Что, по-твоему, делает new? Как он связан с кучей? Как часто он, по-твоему, используется в современном C++?

ну насмешил... ))

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

Я жду ответов на поставленные вопросы - посмеёмся вместе. Ну или сразу признавайся что не знаешь.

slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.