LINUX.ORG.RU

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

 


13

7

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

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

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

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

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

★★★★★

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

Ответ на: комментарий от zaz

int* getIPTR1(); // Looks good but not together with line above
int *getIPTR2(); // OMG, looks like pointer to function or so ...

возвращать поинтер на int это какое-то особое колдунство...

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

Зачем ты это пишешь? На что надеешься?

Ты шутишь?

Не согласен - высирай.

strcat() простая как бревно - просто копирует.

Не простая, твоих 2-х извилин не хватит, чтобы написать не примитивный аналог.

Просто копирует - это её семантика, strdup() не просто копирует, к чему ты это высрал?

Нет ни проверок переполнения

А они там нужны? Ты понимаешь вообще какую же херню ты несёшь? Ты кукарекал про уровень железа, т.е. сишка ближе к уровню железа - дак вот изволь не только высрать 2строчки несвязного говно, но хотябы попытаться связать его с контекстом.

Нет проверок - ок, каким образом это влияет на «близость к железу»?

Я тебя удивлю, но в std::string::append(std::string const&) нет никаких проверок. Ты наверное пытаешься кукарекать про std::string::reserve(size_t)?

Только вот его наличие никак не связано с «блюзостью к железу», а объясняется немного различной семантикой функций, при этом это различие так же не объясняется «разной близостью к железу».

Да и формально это вызов левой функции, который есть и strcat().

не выделения памяти

Опять же, к чему ты это высрал? Это как-то связано с твоим тезисом «отличаются разным уровнем к железу»? Нет.

Далее, т.е. это reserve(), а тогда что было раньше? Т.е. ты даже тут умудрился обосраться.

Семантика strcat() не предполагает привязку его к «выделению памяти», но этому ничего не мешает и никакой «уровень к железу» тут не причем.

ничего «интеллектуального».

Т.е. ты осилил лишь высрать какую-то невнятную херню и reserve()? Ну дак молодец.

Только тебе надо кукарекать не про «интеллектуальность», а про «разный уровень к железу».

Потенциальный генератор опасных и неочевидных багов, если ею пользуется человек только что прочитавший «Основы языка С».

Почему же когда любая нулёвая балаболка обсирается, то она начинает толкать про какие-то «баги»? И прочую шаблонную муру среди поломоек?

Ты кукарекал не про баги, не про ублюдков, а про «уровень к железу». Дак кукарекай, а если не можешь - жри говно, в чем твоя проблема?

И какой же гинератор «опасных» и «неочевидных» «багов» представляет из себя strcat()? Т.е. ты должен высрать минимум два.

std::string::append(std::string const&) сделает нужные проверки

И, что из этого следует? Сегфолтнится на бедаллоке не осилив даже «я упало» вывести?

Проверки каким-то образом относятся к «уровню близости к железу», strcat() их должен делать?

выделит сколько надо памяти

И? strdup() тоже выделит, к чему ты это несёшь? Как это связано с «блюзостью к железу»?

предоставляет Strong guarantee в случае исключений

И? Разве дефолтный реалок их не предоставляет? Больше там предоставлять нечего.

Дай-ка определение понятия «базовый язык».

Это те пункты, имена которых не заканчивается на library.

Т.е. строки кресты умеют благодаря рантайму, пусть и входящему в дефолную поставку крестов.

Для начала просто напиши две одинаковые программы, одну на С, другую на С++

Что значит две одинаковые «программы»? С одинаковой рантайм-семантикой? Рантайм семантика никак не относится к языку.

переведи их на ассемблер и сравни

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

И что же покажет это сравнение?

А дальше думай почему так.

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

А дальше думай почему так. Это тебе ниточка которая приведёт к пониманию разницы C и C++.

Какая корреляция между «переведи их на ассемблер» и «разницы C и C++»?

Вот тебе для затравки - программа, выводящая одну строку:

Что конкретно я тут должен увидеть? Поясни.

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

А вот «контактенация» - вот это проблема)

А можно уже узнать, в чем же заключается эта проблема? Ну кроме того, что 100% тутошных экспертов не осилил написать конкатенацию, ибо она либо не работает, либо лучшеб не работала вовсе.

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

Поэтому пойди пока почитай букварь, пока дяди тут поразговаривают.

О, классический, образцовый «программист С++». Я думал таких уже не делают

Пойду, конечно, почитаю букварь. Неудобно советовать, но вы бы тоже того, почитали что-нибудь. Про проблемы с добычей пищи у неандертальцев на курсах по С++ не расскажут

Ну и с дядями будет интереснее разговаривать, не все же STL и качество покрытия 3G обсуждать

anonymous
()
Ответ на: комментарий от zaz
int *iptr1, *iptr2;
int * iptr1, * iptr2;
int* getIPTR1(); // Looks good but not together with line above
//Это выглядит как говно. Зачем мы прихреначили указатель к типу? В чем логика?
int * getIPTR1();

int *getIPTR2(); // OMG, looks like pointer to function or so ...
//никак не связано с указателем на функцию, если только ты не нулёвая мразь, которая даже уровень 3-го класса не осилила.
//это где-то на уровне  5 * 5 +10 - похоже на сумму 5 и 10. //Если твой парсер настолько убогий, то какбэ тебе либо в дворники, либо в жабисты.

:D

Логика, связи? Нет, зачем - я сказал херню и выдал её за аргумент, ы.

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

Привык

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

некоторые компиляторы требуют.

это проблема компиляторов.

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

по факту термины язык (низкого|среднего|высокого) не имеет чёткого определения что так примечательно для маркетинговых целей.

Это действительно так. Но тем не менее такая классификация имеет смысл. Это та группа терминов, которая не дает абсолютной оценки (то есть нельзя измерить), но дает относительную - можно сравнивать когда разница значительна.

«Высокоуровневость» языка определяет насколько необходимо знать и учитывать низкоуровневые маханизмы компьютера и архитектуру платформы, на которой будет программа выполняиться. Косвенно это также выражается в инструментарии языка. Например, в С размер некоторых целочисенных типов зависит от разрядности аппаратной платформы; в Java такого нет. Берет ли язык на себя ответственность по выделению/высвобождению памяти когда, наример, ты «дописываешь» что-то в строку? Понятно что это всегра нужно делать на уровне железа, но вот в PHP и bash ты этим не занимаешься, а в ассемблере и С - придется. Сюда же работа с регистрами, учет стека, выравнивание памяти и т. п.

И понимать это важно.

Языки высокого уровня, как правило, генерят больше кода и, как правило, это сказывается на производительности. Например, чтобы понять, имеет ли смысл выделять больше памяти для строки, когда туда записывается новое значение, нужно в runtime'е делать проверки. Может by-design переполнение невозможно, и девелопер это знает, но компилятор этого не может знать, и все равно будет генерить такие пповерки.

Коме того, высокоуровневые языки как правило и не содержат «низкоуровневых инструментов». Вы знаете, что программа будет запускаться на определнной платформе, и вы знаете, что эта платформа имеет спец. команды, которые могут в 10 раз ускорить, например, шифрование? - Если используется язак высокого уровня - забудьте. Вы знаете что объект больше не будет ипользоваться и можно освободить память? - Не получится до тех пор, пока сборщик мусора так не решит.

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

Возьмем этот тред. У ТС'a удивление: «как, я должен посчитывать длинну строк, выделять память, обрабатывать ошибки только чтобы сконкатенировать строки?»? Да, потому что С - язык... ну, он не низкого уровня, но и не высокого. Я за тем это и разъясняю, чтобы уберечь ТС'а от подобных инсайтов, типа «А что, длинна int не одинакова на разных платформах?» или «А почему я в char str[] записал юникод, а str[3] мне выдает ахинею? В JavaScript такого не было!».

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

в Java такого нет

рекомендую плотнее ознакомиться с jvm там жёстко указан размер_безнаковость в некоторых случаях где такая жёсткость излишня.

в скором(да уже) времени при наличии аппаратно штатных типов больших чем у jvm это приводить к недопотреблению jvm вычислительных мощностей.

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

т.е jvm - свой уютный мирок.

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

какие долгоидущте выводы. Почему, зачеи. Для того чтобы отличалось толька способом конкатенации.

invy ★★★★★
()

создаем строку нужной длинны и strcat

размер новой строки тривиально считается

Slackware_user ★★★★★
()

У меня такой вариант кода. Думаю, комментарии излишни.

char* concat(char* s1, char* s2) {
	size_t len1 = strlen(s1), len2 = strlen(s2);
	char* result = (char*)malloc((len1 + len2 + 1) * sizeof(char));
	if (result == NULL) return EXIT_FAILURE;
	memcpy(result, s1, len1 * sizeof(char));
	memcpy(result + len1 * sizeof(char), s2, (len2 + 1) * sizeof(char));
	return result;
}
FilosofeM ★★
()
Ответ на: комментарий от makoven

Чрезмерно сложный, на мой вкус.

Не вставай на путь неосиляторства=) Ничего сложного.

Надо же еще оставить место для раста, когда первая версия выйдет.

Где оставить место? Мозг работает несколько иначе, чем склад.

А от си никуда не деться, как ни крути)

И он от тебя никуда не денется.

forCe
()
Ответ на: Не хуже от Camel

Я только высмеял отношение к C как к более плохому языку нежели C++. В то время как он просто другой, не лучше и не хуже. И решать призван другие задачи.

С++ умеет все, что умеет Си. Ну кроме новых фичей, вроде _Generic. Если ты говоришь о том, что для каких-то задач не нужны все возможности C++, то да, это так.

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

в Java такого нет

Потому, что у языка Java только одна платформа - JVM(за счет виртуальности которой и добиваются в итоге кроссплатформенности Java).

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

какой-нибудь компилятор уже научился оптимизировать

GCC 4.9.1 с O2 вообще выбрасывает циклы из кода:

0000000000400410 <main>:
  400410:       48 83 ec 18             sub    $0x18,%rsp
  400414:       bf d4 05 40 00          mov    $0x4005d4,%edi
  400419:       31 c0                   xor    %eax,%eax
  40041b:       48 89 e6                mov    %rsp,%rsi
  40041e:       c6 04 24 31             movb   $0x31,(%rsp)
  400422:       c6 44 24 01 32          movb   $0x32,0x1(%rsp)
  400427:       c6 44 24 02 33          movb   $0x33,0x2(%rsp)
  40042c:       c6 44 24 03 33          movb   $0x33,0x3(%rsp)
  400431:       c6 44 24 04 32          movb   $0x32,0x4(%rsp)
  400436:       c6 44 24 05 31          movb   $0x31,0x5(%rsp)
  40043b:       c6 44 24 06 00          movb   $0x0,0x6(%rsp)
  400440:       e8 9b ff ff ff          callq  4003e0 <printf@plt>
  400445:       31 c0                   xor    %eax,%eax
  400447:       48 83 c4 18             add    $0x18,%rsp
  40044b:       c3                      retq   

Clang делает аналогично:

0000000000400530 <main>:
  400530:       50                      push   %rax
  400531:       c6 44 24 02 33          movb   $0x33,0x2(%rsp)
  400536:       66 c7 04 24 31 32       movw   $0x3231,(%rsp)
  40053c:       c6 44 24 05 31          movb   $0x31,0x5(%rsp)
  400541:       66 c7 44 24 03 33 32    movw   $0x3233,0x3(%rsp)
  400548:       c6 44 24 06 00          movb   $0x0,0x6(%rsp)
  40054d:       48 8d 34 24             lea    (%rsp),%rsi
  400551:       bf fc 05 40 00          mov    $0x4005fc,%edi
  400556:       31 c0                   xor    %eax,%eax
  400558:       e8 a3 fe ff ff          callq  400400 <printf@plt>
  40055d:       31 c0                   xor    %eax,%eax
  40055f:       5a                      pop    %rdx
  400560:       c3                      retq 

Если компилировать отдельно функцию:

#include <string.h>
int fn(char *s)
{
  int a = 0;
  for (int k = 0; k < strlen(s); k ++)
	a += s[k];
  return a;
}

то с O2 strlen вызывается вне цикла и у gcc, и у clang.

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

раз уж мы перешли на личности, зачему, что ты зассал залогиниться и получить заслуженные -20 к скору )

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

судя по твоей реакции, мой код лишил тебя анальной девственности или что-то в этом роде

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

гы. это же царь.

у него больше десятка учёток было, большинство из которых не жили больше недели.

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

а есть проекты на этом селе?

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

Видел. Возможно, не так подробно. Но по-моему он никак не противоречит моим утверждениям.

Тут даже пример андроида лучше. Там действительно другая платформа совсем.

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

Очередной Си с классами? Убить в зародыше. Иначе переймет эстафету детища Страуструпа и ад на земле продлится еще на 30 лет

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

ты ещё не видел(или уже) как на Си реализовано работа с замыканиями - это настолько эпично, что память об этом вечна.

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

Ты про эту библиотеку? Или про что?

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

К сожалению, уже не реагируют. И нападки на питон и восхваление системд - всё мимо ушей. Видать я слишком толст)

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

это гнутое расширение

Оно великолепное и удобное. Я часто использую вложенные функции, чтобы "глобальное пространство имен" не засирать.

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

Никогда не любил вкладывать функции. А как-же функции со словом static? Я еще не програмист, но кажется где-то читал, что такие функции не покидают пределов определяющего их файла.

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

А как-же функции со словом static?

А зачем нужно слово «статик»? В современном коде, собственно который и юзает всю эту муру, никаких статиков, а уж тем более файлов не существует.

Юзанье вложенных функция всякими нулёвыми маргиналами типа едика, ну дак чего требовать с убогих.

Тем более функция итак «статик».

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

Хочешь сказать, что если просто, даже без статик, написать определение функции - его не будет видно за пределами файла?

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

Хочешь сказать, что если просто, даже без статик, написать определение функции - его не будет видно за пределами файла?

Вы контекст разговора способны держать в голове? Определение не функции, а вложенной функции.

Будет ли видно определение вложенной переменной? Она локальна. Т.к. функция это немного сложнее переменной и требует в отличии от оной объекта кода(т.е. просто переменная - это часть объекта кода функции, а тело функции не может быть частью объекта кода родителя) как локалстатик, то она по дефолту локальный статик - т.е. переменная не как часть объекта функции, а как отдельный объект.

Относительного сишного кода она видна не будет даже в рамках родительского файла - только в рамках родительской функции. Существовать в объектнике она будет, как и локалстатик. Т.е. глобальный объект с ограниченной областью видимости в рамках сишного кода.

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

А, я думал речь идет не о вложенных функциях

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

ну блин тяжело что ли загуглить

как закат солнца в ручную в Си - замыкания с явной передачей контекста через указатель на кусок дин.памяти.

это реально эпично.

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

возможно (это предположение) Ритчи не захотел конкретизировать вариант как из вложенной функции обращаться к локальным переменным объемлющей .

т.е определяться дисплеи или ещё как.

вообще судя по изначальным auto,static,extern Си (и его предшественики) не были блоковыми языками.

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

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

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

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

Ну а что тут такого? В C++ ограничиваются тем, что позволяют управлять способом захвата, инициализацией контекста(в C++14) и пр. такое. А для си вполне нормально управлять и памятью под контекст.

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

всё норм.

так как с паскалем укушенный то для меня вложенность функций естественно , а вот почкование контекстов и кактусование стека не очень было в своё время «очевидно»

и когда на С# гдето в 2006 изобрёл(велосипедно) замыкания(генерация функцией «обьекта» путём возврата делегата) (эксперементировал с а чё если так) продолжительное время прояснял «а вот как это оно»

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

Да я вообще не понял, что там под замыканиями имелось в виду. Я такое не знаю.

забей. Это ненужный и избыточный костыль, который есть в пас-кале, и на который фанатеги пас-кала усиленно фапают. Нужен потому, что в пас-кале нет нормальных указателей.

Да, запилили в C++11, оно работает, только никто не знает — зачем.

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

Да, запилили в C++11, оно работает, только никто не знает — зачем.

Заметь, это ты сам себя так назвал.

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

как аноним(вряд ли царь ) уже отметил

для замыканий вложенность не достаточное.

обычно замыканиям сопутствует сборка мусора

и прозрачное вытеснение/разветвление локальностей со стека на кучу либо вообще использование кучи для размещения записей активации функций без явного апаратного стека

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

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