@Olivier. Это верно. Я заметил, что когда я написал его, если я уронил количество выделений, скажем, до 100 раз, эталонный тест совпадает с std :: string. Я отредактировал пост и добавил тест на github

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

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

Я ищу то, что может содержать большое количество символов и упрощает процесс поиска по строке. Если это позволяет мне токенизировать строку любым способом, даже лучше. Кроме того, он должен иметь довольно хорошую производительность ввода-вывода. Печать и форматированная печать - не самый главный приоритет. Я знаю, что не стоит ожидать, что библиотека сделает всю работу за меня, но я просто бродил, если бы была хорошо документированная строковая функция, которая могла бы сэкономить мне время и некоторую работу.

Любая помощь очень ценится. Заранее спасибо!

РЕДАКТИРОВАТЬ: меня спросили о лицензии, которую я предпочитаю. Подойдет любая лицензия с открытым исходным кодом, но желательно GPL (v2 или v3).

EDIt2: Я нашел библиотеку betterString (bstring), и она выглядит довольно хорошо. Хорошая документация, небольшой, но универсальный набор функций, и его легко смешивать со строками c. У кого-нибудь есть хорошие или плохие истории об этом? Единственный недостаток, о котором я читал, это то, что в нем отсутствует Юникод (опять же, читайте об этом, пока еще не видел его лицом к лицу), но все остальное кажется довольно хорошим.

EDIT3: Кроме того, предпочтительно, чтобы его чистый C.

 Chris Lutz14 янв. 2011 г., 05:52
<plug shame="none"> Я пишу (хобби) фреймворк, который включает строковый тип, это считается?</plug>
 David Heffernan14 янв. 2011 г., 08:36
Я бы предложил C ++, но по какой-то причине вы хотите усложнить себе жизнь.
 chamakits14 янв. 2011 г., 08:26
@ Крис, вы можете подключить его, если хотите: P Я могу взглянуть на него, но если он еще молод, я, вероятно, не буду использовать его для своего проекта. Ничего личного, просто известно, что c-строки хитры, и до тех пор, пока они не будут тщательно протестированы (с чем я могу помочь: P), я не чувствую себя комфортно, используя их в своей кодовой базе.
 detly14 янв. 2011 г., 06:30
Вы должны указать, какую лицензию вы делаете или не хотите, так как некоторые из лучших претендентов - GPL.

Ответы на вопрос(6)

так как я нахожу<string.h> функции очень неэффективные, например:

strcat() может быть очень дорогим по производительности, так как он должен находить символ '\ 0' каждый раз, когда вы объединяете строкуstrlen() это дорого, так как опять же, он должен найти символ '\ 0' вместо того, чтобы просто читать поддерживаемыйlength переменнаяМассив char, конечно, не является динамическим и может вызывать очень опасные ошибки (сбой при ошибке сегментации может быть хорошим сценарием, когда вы переполняете буфер)

Решением должна быть библиотека, которая не содержит только функции, но также содержит структуру, которая переносит строку и позволяет хранить важные поля, такие какlength а такжеbuffer-size

Я искал такие библиотеки в Интернете и обнаружил следующее:

Библиотека GLib String (должно быть лучшим стандартным решением) -https://developer.gnome.org/glib/stable/glib-Strings.htmlhttp://locklessinc.com/articles/dynamic_cstrings/http://bstring.sourceforge.net/

наслаждаться

malloc, free, strlen, memcpy, а такжеsnprintf, Эти функции предоставляют вам все инструменты для мощной, безопасной и эффективной обработки строк в C. Просто держитесь подальше отstrcpy, strcat, strncpy, а такжеstrncatВсе это, как правило, приводит к неэффективности и эксплуатационным ошибкам.

Так как вы упомянули поиск, какую бы библиотеку вы ни выбрали,strchr а такжеstrstr почти наверняка будет то, что вы хотите использовать.strspn а такжеstrcspn также может быть полезным.

 ijw14 янв. 2011 г., 14:15
[нужна цитата]
 Chris Lutz14 янв. 2011 г., 23:47
Ты забылmemmove, Это полезно.
 ninjalj20 июл. 2011 г., 18:29
В этом случае, я не согласен с @R. У Postfix и Qmail есть свои собственные процедуры обработки строк, у проекта GNU есть препятствия, и я, конечно же, раньше катал свои собственные. Я бы предпочел высокоуровневую библиотеку для динамически размещаемых строк по сравнению с низкоуровневойstr*() для чего-либо умеренно сложного (даже если эта библиотека состоит из единственной функции для создания / добавления строки).
 Benoit Thiery14 янв. 2011 г., 11:53
Не могли бы вы предоставить более подробную информацию о strcpy, strcat? Я использую их часто, и я никогда не видел, чтобы memcpy + strlen был быстрее.
 R..14 янв. 2011 г., 18:20
@Benoit: в принципе невозможно использоватьstrcat правильно, потому что, чтобы узнать, поместится ли новая часть в ваш буфер, вам уже нужно знать как длину строки, так и размер буфера. Не только делаетstrcat расточительно пересчитать первые 2, но это также позволяет вам легко игнорировать тот факт, что вы не знаете, помещаются ли они в буфер. Если вы не используетеstrcatВы всегда будете иметь под рукой правильную длину.strcpy не так плохо, но то же самое относится. Обратите внимание, что построение строки по частям сstrcat также бываетO(n^2).

необходимость добавления строки с миллионами символов. Я закончил делать свое.

Это просто массив символов C, инкапсулированный в класс, который отслеживает размер массива и количество выделенных байтов.

Производительность по сравнению с SDS и std :: string в 10 раз выше, чем в тесте ниже

в

https://github.com/pedro-vicente/table-string

Ориентиры

Для Visual Studio 2015 отладочная сборка x86:

| API                   | Seconds           
| ----------------------|----| 
| SDS                   | 19 |  
| std::string           | 11 |  
| std::string (reserve) | 9  |  
| table_str_t           | 1  |  

clock_gettime_t timer;
const size_t nbr = 1000 * 1000 * 10;
const char* s = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
size_t len = strlen(s);
timer.start();
table_str_t table(nbr *len);
for (size_t idx = 0; idx < nbr; ++idx)
{
  table.add(s, len);
}
timer.now("end table");
timer.stop();

РЕДАКТИРОВАТЬ Максимальная производительность достигается путем выделения строки все в начале (размер параметра конструктора). Если используется доля от общего размера, производительность падает. Пример с 100 выделениями:

std::string benchmark append string of size 33, 10000000 times
end str:        11.0 seconds    11.0 total
std::string reserve benchmark append string of size 33, 10000000 times
end str reserve:        10.0 seconds    10.0 total
table string benchmark with pre-allocation of 330000000 elements
end table:      1.0 seconds     1.0 total
table string benchmark with pre-allocation of ONLY 3300000 elements, allocation is MADE 100 times...patience...
end table:      9.0 seconds     9.0 total
 Pedro Vicente08 сент. 2017 г., 21:36
@Olivier. Это верно. Я заметил, что когда я написал его, если я уронил количество выделений, скажем, до 100 раз, эталонный тест совпадает с std :: string. Я отредактировал пост и добавил тест на github
 OlivierD10 июл. 2017 г., 23:19
Библиотека sds находится на C, а строка таблицы - на C ++. Кроме того, причина, по которой sds выглядит намного медленнее, заключается в том, что ваша таблица выделяется заранее, в то время как sds будет перераспределяться несколько раз для роста. Попробуйте еще раз с sdsgrowzero (s, nbr * len) или даже более быстрой sdsMakeRoomFor () и посмотрите, соответствуют ли ваши тесты.
Решение Вопроса

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

SDS - это строковая библиотека для C, предназначенная для расширения ограниченных функций обработки строк libc путем добавления выделенных в куче строк, которые:

Проще в использовании.Бинарный сейф.В вычислительном отношении более эффективный.Но пока ... Совместимо с обычными строковыми функциями Си.

Это достигается с помощью альтернативного дизайна, в котором вместо использования структуры C для представления строки мы используем двоичный префикс, который сохраняется до фактического указателя на строку, возвращаемую SDS пользователю.

+--------+-------------------------------+-----------+
| Header | Binary safe C alike string... | Null term |
+--------+-------------------------------+-----------+
         |
         `-> Pointer returned to the user.

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

 chamakits03 авг. 2014 г., 06:58
Это очень хорошая находка и хороший послужной список (используется в Redis). Я определенно буду помнить об этом в следующий раз, когда собираюсь написать какой-нибудь строковый тяжелый C-код.
 user471390805 окт. 2015 г., 17:52
Я обязательно попробую это.

пожалуйста, проверьтеmilkstrings.
Образец кода :

int main(int argc, char * argv[]) {
  tXt s = "123,456,789" ;
  s = txtReplace(s,"123","321") ; // replace 123 by 321
  int num = atoi(txtEat(&s,',')) ; // pick the first number
  printf("num = %d s = %s \n",num,s) ;
  s = txtPrintf("%s,%d",s,num) ; // printf in new string
  printf("num = %d s = %s \n",num,s) ;
  s = txtConcat(s,"<-->",txtFlip(s),NULL) ; // concatenate some strings
  num = txtPos(s,"987") ; // find position of substring
  printf("num = %d s = %s \n",num,s) ;
  if (txtAnyError()) { //check for errors
    printf("%s\n",txtLastError()) ;
    return 1 ; }
  return 0 ;
  }
 archimedes15 авг. 2016 г., 13:35
пока (! feof (fi)) нет в библиотеке. Это было частью некоторого примера кода.
 David C. Rankin14 авг. 2016 г., 10:10
Любая библиотека, которая включаетwhile (!feof(fi)) есть подозрение для начала. Видеть:Почему «while (! Feof (file))» всегда неверно?
 David C. Rankin15 авг. 2016 г., 15:09
В одном файлеmilkstrings.c, while (!feof (fi)) { появляется в строках306 а также371, В то время как истина, экземпляры обернуты вtxtSKIPEXAMP ярлык, оба торчат, как больной большой палец, который ударил кувалдой. напримерgrep -nhA10 'feof\|^#if.*SKIP' milkstrings.c Я не ваш отрицательный голос, я просто указываю, что независимо от того, скомпилированы ли они или нет, используяwhile (!feof (fi)) { таким образом, известная плохая идея, которая может привести непосредственно к неопределенному поведению.

вы должны посмотреть наICU, т.е. поддержка Unicode, если вы неконечно ваши строки никогда не будут содержать ничего, кроме простого ASCII-7 ... Поиск, регулярные выражения, токенизация - все это есть.

Конечно, переход на C ++ сделает всемного проще, но даже тогда моя рекомендация ICU будет верна.

Ваш ответ на вопрос