LINUX.ORG.RU

Создание строки в C (СИ)

 ,


1

3

Не могу найти внятного объяснения этого таинства.

Хочу создать пустую строку. Далее в коде в неё что-то записать (размер этого что-то неизвестен)

char *temp = NULL; //создаем указатель на будущую строку
int numofchars = 254; // 254 байта хватит всем


temp = (char*) malloc(numofchars+1); // выделяем память под нашу строку

strcpy(temp, "Privet, LOR");

...


free(temp);

Вопрос: правильно ли я всё делаю?

★★★★★

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

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

Охотно верю, видимо у вас максимальная длинна строки и средняя длинна строки близки...

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

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

И?

Да, в моём варианте длина строки вычисляется. Но зато просто копируются данные, а не проверяется каждый символ с равенством на '\0' и не заполняется остаток буфера нулями..

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

Пока мне достаточно если С строки будут быстрее std::string :)

Во многих случаях std::string будет быстрее char*, как раз из-за наличия размера. В стандартном C-api практически все операции со строками предполагают пробег по ним в поисках завершающего '\0'. В std::string и предлагаемом варианте он известен заранее.

Так же есть small string optimization, которая на 64-битах и мелких строках может дать вполне весомое преимущество перед аллокацией char*. Если данные подходят.

Ну и вообще, std::string может заметно отличаться по скорости от char*, только если его бездумно копируют или создают на каждый чих. Используй std::string_view и всё будет быстро и удобно.

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

автор явно не любит разделители в идентификаторах

sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);

ну и всё в таком духе

anonymous
()
char *temp = NULL;
asprintf(&temp, "%s", "Privet, LOR");
free(temp);
anmg
()
Ответ на: комментарий от anonymous

процедура main это S : Неограниченная_Строка

Очень выразительный язык. Читаешь и сразу понятно, что процедура — это строка.

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

На самом деле нет, в стандартной библиотеке 1-2 слова + префикс/суффикс, за счёт этого идентификатор короткий и легко воспринимается при чтении, а в этой либе суммарная длина гораздо больше и получается нечитаемое говно

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

Ну и причём тут ada и твой ковнокод?

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

Я понимаю, но стиль стандартной библиотеки не так плох, но надо понимать в чём его преимущества

anonymous
()

Не, явно Борька Керниганов с Дениской Ритчевым что-то не додумали, когда сочиняли язык Си.

praseodim ★★★★★
()

Если нужен буфер для работы:

char temp[256] = "Privet, LOR";

strncpy(temp, "something else", sizeof(temp)); /* а ещё лучше strlcpy() */

Если нужна просто аллоцированная строка:

char *temp = strdup("Privet, LOR"); /* убирает все эти ритуальные пляски с ручным malloc, numchars и sizeof */

Если нужна просто константная строка:

const char *temp = "Privet, LOR";
anonymous
()
Ответ на: комментарий от anonymous

а ещё лучше strlcpy()

С сями знаком без году неделя, но уже мечтаю чтобы её добавили в C20

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

Немного оффтоп: и много ты могучего-великого софта не имеющего аналогов напишешь, если будешь тупить над примитивными азами, над крохами? Ползать как червь по земле с malloc, когда мог бы парить как орел в высоких абстракциях?

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

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

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

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

Всё я понимаю.

sniper21 ★★★★★
() автор топика
Ответ на: комментарий от I-Love-Microsoft

Немного оффтоп: и много ты могучего-великого софта не имеющего аналогов напишешь, если будешь тупить над примитивными азами, над крохами? Ползать как червь по земле с malloc, когда мог бы парить как орел в высоких абстракциях?

Вах, какой красивый тост! Только переписываю я утилитку на 400 строк с C++ на C, дабы удовлетворить одному непростому требованию.

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

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

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

одному непростому требованию

Недостаток бекдоров?

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

Во многих случаях std::string будет быстрее char*, как раз из-за наличия размера.

Нет, std::string может только что-то лишь благодаря тому, что это обёртка над string.h

как раз из-за наличия размера.

Ничего не даёт в большинстве операций.

В стандартном C-api практически все операции со строками предполагают пробег по ним в поисках завершающего '\0'.

Что есть бесплатно. Ну и да, особенно те, что закалхожены в char_traits<char>.

Так же есть small string optimization, которая на 64-битах и мелких строках может дать вполне весомое преимущество перед аллокацией char*. Если данные подходят.

Это колхоз, который никакой «аллокации char *» не противоречит. Аллокация char * намного мощнее, ведь он не ограничена ничем.

Ну и вообще, std::string может заметно отличаться по скорости от char*, только если его бездумно копируют или создают на каждый чих. Используй std::string_view и всё будет быстро и удобно.

std::string на то и существует, что-бы «копироваться» - это раишное дерьмо. И когда ты начинаешь говорить про std::string_view, который ортогонален std::string и раишному дерьму, и является тем же самым, чем является char * - это выглядит как-то странно.

Где-то тут на лоре есть мой ultrafast_strlen(), который за O(1) даёт длину для маллочных сишных строк, но его вроде потёрли.

vcerloman
()

Добавлю ещё, что malloc лет 30 уже как не кастят. Где вы берёте таки устаревшие привычки?

PS: про strdup уже вспоминали?

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

Ты явно чего-то не знаешь. strcpy - там нет strlen по определению, даже в самых колхозных имплементациях его не используют.

Почти ни в каких операциях strlen"а нет.

vcerloman
()
Ответ на: комментарий от pftBest
static inline size_t ultrafast_strlen(char * str) {
  
  typedef union {
    size_t data;
      struct {
        size_t __flag0: 1;
        size_t is_mmaped: 1;
        size_t __flag2: 1;
        size_t size: 61;
      };
  } chunk_size_t;
  
  chunk_size_t chunk = {.data = *(size_t *)(str - 8)};
  
  size_t size = chunk.size << 3;
  size_t align = (chunk.is_mmaped ? 4096 : 16);
  size_t overhead = (chunk.is_mmaped ? 16 + 8 : 8);
  size_t end_pos = size - overhead; 
  size_t start_pos = (end_pos - align + 1);
  
  start_pos -= 1;
  
  start_pos = (start_pos < 10) ? 0 : start_pos;
  
  return start_pos + strlen(str + start_pos);
}

Как-то так. Суть в том, что маллок уже хранит длину чанка. А т.к. шаг длинны чанка не равен байту, то при одной и той же длине чанка - длина строки может быть разной. Максимальную её длину + 1 - можно получить с malloc_usable_size(). Для минимальной нужен колхоз.

А дальше всё просто - пускаем strlen() от минимального и прибавляет минимальный.

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

Во всём? Как минимум в том, что для sdscmp() не нужен strlen(), но колхозники этого не знают, поэтому ваяют это дерьмо, чтобы strlen() не тормозил. Это что касается ссылки.

А в целом - полный ахтунг. Начиная с того, что это колхоз-сишка, на которой можно написать только мусор. Писали это явно те, кто писать не может. Да и вообще это колхоз-обёртка над libc, которая ничего не делает.

Мне лень всё разбирать. Я увидел только одну функцию, которой нужен не сишный strlen(). Второй оно нужно только для валидации аргументов. Далее там пошло отборное, и может там то же что-то есть.

https://github.com/antirez/sds/blob/master/sds.c#L829 - полный аутизм. Похоже ещё про strstr() не рассказали. Ну ничего - завтра пацанам расскажут - они перепишут.

https://github.com/antirez/sds/blob/master/sds.c#L869 - это вообще комментировать не имеет смысла.

Хотя нет, вру. https://github.com/antirez/sds/blob/master/sds.c#L1063 - это ещё лучше. Долбим квадрат - нахрен таблицу.

https://github.com/antirez/sds/blob/master/sds.c#L439 - убожество. Контекст ограничен SDS_LLSTR_SIZE, и казалось бы - пиши с конца, а после делай move, но нет - пацаны это ещё не изучали.

Ну и копипаста явно в крови у пацанов.

https://github.com/antirez/sds/blob/master/sds.c#L499 - датычё

https://github.com/antirez/sds/blob/master/sds.c#L507 - мы везде делаем setlen, но что-то тут у нас не смоглось - копируем.

Колхозные принтф"ы даже комментировать лень.

https://github.com/antirez/sds/blob/master/sds.c#L527 - брутфорсим sprintf.

https://github.com/antirez/sds/blob/master/sds.c#L513 - это для того, чтобы пациенты мне не вещали о том, что «они на самом деле не неосилили таблицы, просто память экономили» - ога.

https://github.com/antirez/sds/blob/master/sds.c#L693 - а вот и проявление неосиляторства таблиц.

https://github.com/antirez/sds/blob/master/sds.c#L763 - а что не используют свою функцию реплейса? Там же по идее точно так же должны долбить в два фора.

И конечно же, тут нет ни ОДНОГО намёка на хоть какую-то оптимизацию, даже самую малую. Хотя нет, вижу - вижу:

https://github.com/antirez/sds/blob/master/sds.c#L903 - таблица, ну как таблица - мусор, но всё же компилятор сделает из неё таблицу. Хотя нет, пацаны ведь с Os собирают.

Про то, как это написано - я даже рассказывать не буду - меня заклюют. Хотя нет, пацаны с c99 собирают.

https://github.com/antirez/sds/blob/master/sds.c#L761 - ну ничего, похоже c99 - это только для понтов. Ну ничего, я верю, что пацаны смогут осилить.

А особенно меня умиляет pedantic, но при этом __attribute__ в хедерах. Это такая клоунада.

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

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

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

Жопорукие быдлокодеры везде встречаются. Это не значит, что язык — говно!

Набыдлокодить и на пхытоне можно так, что волосы дыбом встанут! И даже круче, потому как пхытон — говноЯП, предназначенный именно для быдлокодинга.

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

std::string будет быстрее, потому что для твоей маленькой строки std::string даже не будет аллоцировать память. К тому же std::string отлично оптимизируется: https://godbolt.org/g/ifmC1J

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

Если всё пройдет хорошо, то я покажу и свяжу с этим тредом :)

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

Т.е. ты сел в лужу?

Странно, сказать нечего тебе, а в лужу сел я.

я скажу одно слово heartbleed

Можешь сказать ещё фуарЫВДРАывраплынвпанп и другие слова, смысла которых ты не понимаешь, но это, как, впрочем, и всегда, смысла твоим словам не добавит.

redgremlin ★★★★★
()

Народ а есть в C функция по типу strXcpy(char* to, const char* from, size_t max_cpy);.
Копирующую как strcpy но не больше max_cpy char'ов, да ещё и зануляющую последний char.
Понятно что это можно и самому запилить, но всё же?

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

Правильно что удалили, убивать за такое надо. Ты завязался на детали реализации и сделал решение, которое несовместимо ни со строками на стеке, ни с обычной для C работой с указателями, аля str + bytes_to_skip, и при этом ещё и работает неправильно с преаллоцированным с запасом буфером. Если готов со всем этим расстаться, не парь мозг, заведи структуру типа

struct string {
   size_t capacity, length;
   char data[1];
}
и получишь реально O(1) strlen и без опасности сломать программу невинным редактированием.

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

А ты явно читать не умеешь, но я для тебя разберу:

Во всём? Как минимум в том, что для sdscmp() не нужен strlen(), но колхозники этого не знают, поэтому ваяют это дерьмо, чтобы strlen() не тормозил. Это что касается ссылки.

Т.е., тут говорится о том, что для strcmp() не нужен strlen(), но колхозники этого не знают. От того они прикручивают к строке len, и делают strlen(), который не тормозит. Т.е. это не нужно.

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

Меня твоё «мнение» мало интересует, как и твои глупые попытки что-то мне рассказывать. Меня не интересуют проблемы, которые возникают у всяких балаболов.

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

Нет, std::string может только что-то лишь благодаря тому, что это обёртка над string.h

И что это меняет? Ты опровергаешь то, что std::string может быть быстрее char* тем, что std::string может использовать string.h? Логика тебе чужда, я смотрю.

Ничего не даёт в большинстве операций.

В большинстве или нет, зависит от данных и набора операций. Но хорошо хоть не во всех. Уже прогресс. Скоро начнёшь понимать, что выйгрыш в некоторых операциях - тоже выйгрыш.

Что есть бесплатно.

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

Это колхоз, который никакой «аллокации char *» не противоречит. Аллокация char * намного мощнее, ведь он не ограничена ничем.

Ну и что это за бред? Причём тут противоречия, ограничения и мощность? Тебе русским языком сказано, что на 64-битах для мелких строк, std::string, благодаря sso, будет быстрее, чем выделение памяти на куче. Что тут можно было не понять?

std::string на то и существует, что-бы «копироваться» - это раишное дерьмо. И когда ты начинаешь говорить про std::string_view, который ортогонален std::string и раишному дерьму, и является тем же самым, чем является char *

Царь не осилил raii и string_view. Но мнение имеет. Впрочем как обычно.

Где-то тут на лоре есть мой ultrafast_strlen(), который за O(1) даёт длину для маллочных сишных строк, но его вроде потёрли.

Твой ultrafast_высер() кусок говна, неприменимый в адекватных проектах. Оставь его себе и больше не выкладывай.

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

Странно, сказать нечего тебе, а в лужу сел я.

Нет, это тебе нечего сказать. Но давая я поясню для пацанов.

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

На что данный балабол поплыл и начал нести ахинею вида «нет, не берутся» - т.е. уже сел в лужу.

А после, а ему дал отсылку на heartbleed, в котором проблема была именно в том, что длина бралась из сети.

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

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