LINUX.ORG.RU

Шок от С. Как склеивать строки?

 


13

7

Осваиваю си. Всё шло хорошо пока внезапно не понадобилось склеить строки (константные и переменные). Покурил stackoverflow. Предлагают 2 варианта:

Первый - создать char buf[молись_чтобы_хватило] и делать str(n)cat/sprintf в этот buf.

Второй - использовать asprintf, который расширение, нестандарт и вообще.

Вопрос: как вы склеиваете строки? Может есть какая-нибудь общепринятая либа?

Простите за нубский вопрос

★★★★★

Последнее исправление: makoven (всего исправлений: 1)

Во-первых, да - либа есть, называется стандартная библиотека C++, на ней строки склеиваются просто как joined = string1 + string2, без необходимости думать о распределении памяти, размерах буферов и обработке ошибок, а C не используется для того для чего он не предназначен.

Во-вторых, не «молись_чтобы_хватило», а «известно что хватит» + проверить что влезло после (разумеется, только для случаев когда известно что хватит, PATH_MAX или FILENAME_MAX например).

В-третьих, открой для себя malloc и, следовательно, возможность выделить буффер нужного размера. Только не забывай про лишний байт под терминирующий \0, как некоторые здешие позорища о пяти звёздах.

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

Ужас под названием gtk+ — это как раз пример того, почему не надо использовать С для того, для чего он не предназначен

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

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

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

Ну чтобы наверняка, хотя да, логично тогда было бы вставить и в malloc()

sizeof(char) == 1, всегда.

А нахера, если я вторую копирую строку вместе с \0?

У тебя память под него не выделяется.

anonymous
()

с++ <string>

если велосипед то:

 char* bluetape(char *h, char *t){
        потребно = h.strlen + t.strlen + 1;
        место_под_солнцем = адайка потребно байт?
        чё как или вилы(тут различные слова о и выхода нет)?
        memmove(место_под_солнцем,h,h.strlen);
        return memmove(место_под_солнцем+h.strlen,t,t.strlen+1);
}

вопросы владения рули сам ибо С

зы. кое кто высказывает недовольство интерфейсом функции memmove которая не итерирует на end а возвращает исходный start ибо следствие отсутствия желаемого и не красота.

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

действительно , удержался от байтообмазывания. СИЛЁН.

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

c++ <string> стандартно с++ <rope> для изысков

или своя(чьято) библиотечка на с делаяющае то же самое - сокрытие и контроль замалоченых ресурсов.

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

а размер да и сам combined где такой адаптивный размещается?

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

везде не нужно

следуй дисциплине кто(какие функция) «фабрики» продуценты чего либо

и кто-где консументы

и редуценты.

и бархатные и шелковистые станут.

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

А нафига тебе тысячу раз вызывать malloc по десятку байт? У тебя что ли динамические строки? Если да, то это нормально. Всякое говно вроде С++ похлеще вытворяет...

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от makoven

делать тысячи аллокаций каждая по десятку байт - это норма?

Обычно этого стараются избежать

У тебя какая задача - склеить две строки или тысячи строк? Если второе, выделяй сразу побольше памяти под результирующую строку

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

Да не. Мне не надо. Теоретически) А память аллцируется ровно столько сколько запросил или секторами/страницами, как на жестком диске?

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

rest-api на microhttpd. Впрочем, он позволяет отправлять данные порциями, так что склеивание не сильно актуально. Но иногда все-равно нужно

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

всегда.

Ну а вдруг? :D

У тебя память под него не выделяется.

Ладно, уговорил. Да и копирую я вторую строку без \0. Но мне-то простительно, я всего-то пол года как не школьник :D

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

после таких высказываний , единственный валлидный адрес назначения :

http://www.amazon.com/The-Programming-Language-Brian-Kernighan/dp/0131101633

в частности

chapter 5: Pointers and Arrays
        5.1  Pointers and Addresses                (о *& )
        5.2  Pointers and Function Arguments       (о всё копируется по значению)
        5.3  Pointers and Arrays                   (о a[i] есмь i[a] ибо *(a+i) )
        5.4  Address Arithmetic                    (о очевидной реализации alloc)
        5.5  Character Pointers and Functions      (о строках ага)
        5.6  Pointers are not Integers             (о прикручивании типизации(какая ни есть) в потомке NB)
        5.7  Multi-Dimensional Arrays              (о таковых литералах и различии между a[x][y] a[x,y])
        5.8  Pointer Arrays; Pointers to Pointers  (о многообразии структур_данных без структур, эдакий фортанLatte)
        5.9  Initialization of Pointer Arrays      (комбинация предыдущего пункта и ему предыдущего пункта)
        5.10 Pointers vs. Multi-dimensional Arrays (о новичках путающих int a[10][10] и int *b[10])
        5.11 Command-line Arguments                (о argc и argv)
        5.12 Pointers to Functions                 (о полиморфизме для "бедных")
qulinxao ★★☆
()
Ответ на: комментарий от makoven

rest-api на microhttpd

А. Ну как правило применяют такую стратегию: выделяют приблизительно достаточный кусок памяти, если его не хватает, делают realloc в 1.5-2 раза. Подробности гуглятся по «buffer growth strategy»

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

не только, он ещё и продемонстрировал bikeshedding

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

то тогда после освоения равнозначного Chapter5 from K&R

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

вон в doom'е изначальном вроде как не за каждым байтиком к операционке а сразу 4 МБ ( гигантская по тем временам ) а потом уже «все свои».

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

тут начинают течь абстракции есть ещё же mmu , ну и всякие близнецовые и прочие.

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

Кинь пример. А то я свой велосипед писал, чтобы одновременно и аргументы парсить и выхлоп --help формировать (в смысле — одной структурой). сделал после того, как задолбался читать исходники для понимания, что какой ключ делает (т.к. постоянно забывал --help дописывать)

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от i-rinat

Надо считать длины, запоминать, а потом печатать с помощью %.*s, указывая длину. И то, не факт, что snprintf не будет проверять каждый символ на \0.

Точно будет проверять, это лишь дополнительное ограничение сверху на длину строки.

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

Лучше не знаешь - не говори. Для gtk существуют куча обвязок под все языки программирования. А под Qt всего ничего и те дышат на ладан

niemand
()

внезапно не понадобилось склеить строки (константные и переменные)

п.1: в С строк нет, то есть соовсем-совсем __вообще_нет__. есть историческое соглашение о массивах представляющих нечто подобное. пока это не усвоишь в голове будет мешанина.

п.2: пока «строки» крутятся внутри твоих функций - склеивай как вздумается, хоть через косвенные указатели в индексном массиве. Как только надо возвращать «строку», вызывающая сторона должна озоботится о выделении буфера.

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

эээ есть строки , но только в докомпайлтайме - теже литералы для строк есть.

, а так да есть лишь последовательности чего угодно ,

одномерные, или двух или вообще переменномерные(деревья и прочие графы)

как ни странно *p понятней(знал и до) после итераторов( не в смысле питона и прочей ... , а stl, как нечто указывающее на элемент в какой то сущьности(...) таковых)

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

Когда найдешь сравнение последних версий, скажешь.

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

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

man Qt

а вообще, неужели проблема дважды вызвать strlen?

Диагноз: ниасилятор сей... Это ж низкий уровень, зато максимально быстро.

I-Love-Microsoft ★★★★★
()
Последнее исправление: I-Love-Microsoft (всего исправлений: 1)

Блиц-вопрос

Я тут немного помимокрокодильствую и поинтересуюсь, а для чего ты изучаешь C? И почему бы не изучить C++ вместо этого конструктора «сделай сам себе плюсы»?

Deleted
()

Первый - создать char buf[молись_чтобы_хватило]

А что, sizeof и strlen в С нет?

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

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

Или я чего то не правильно понимаю?

Dron ★★★★★
()

как вы склеиваете строки? Может есть какая-нибудь общепринятая либа?

man 3 strcat

молись_чтобы_хватило

молится не нужно:

char* str3 = malloc(strlen(str1)+strlen(str2)+1);
strcpy(str3, str1);
strcat(str3, str2);
emulek
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.