2011-01-14 2 views
22

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

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

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

Любая помощь с благодарностью. Заранее спасибо!

EDIT: меня спрашивали о той лицензии, которую я предпочитаю. Любая лицензия с открытым исходным кодом будет делать, но предпочтительно GPL (v2 или v3).

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

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

+1

'' Я пишу фреймворк (хобби), который включает в себя тип строки, это так? '' –

+2

Вы должны указать, какую лицензию вы делаете или не хотите, так как некоторые из лучших претендентов - GPL. – detly

+0

@Chris вы можете подключить его, если хотите: P Я могу взглянуть на него, но если его еще молодой, я, вероятно, не буду использовать его для своего проекта. Ничего личного, его просто, что строки c, как известно, сложны, и пока это не было проверено (что я могу помочь с: P), я бы не чувствовал себя комфортно, используя его в моей базе кода. – chamakits

ответ

20

Это старый вопрос, надеюсь, вы уже нашли полезный. Если вы этого не сделаете, ознакомьтесь с библиотекой Simple Dynamic String на github. Я скопировать & пасты описания автора здесь:

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

  • Simpler использовать.
  • Двоичный сейф.
  • Вычислительно более эффективным.
  • Но все же ... Совместим с обычными функциями строки C.

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

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

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

+0

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

+0

Я окончательно попробую это. –

8

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

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

+0

Не могли бы вы предоставить более подробную информацию о strcpy, strcat? Я часто их использую, и я никогда не видел, чтобы memcpy + strlen был быстрее. –

+0

Хм .... Я это рассмотрю. Мое самое большое беспокойство заключается в том, что, честно говоря, прошло некоторое время с тех пор, как я закодировал C, и я прочитал о проектах, которые легко могут использовать их код из-за неопытности с C. Правда, я должен просто решить эту проблему и получить опыт , но я просто подумал, что сначала использую что-то полностью построенное, посмотрю, как это работает и что мне обычно нужно, а потом, в конце концов, прыгаю в мою. Тем не менее, я буду помнить эту рекомендацию. Благодаря! – chamakits

+0

[править] – ijw

1

Я также обнаружил необходимость внешней библиотеки C строки, так как я нахожу <string.h> функции очень unefficient, например:

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

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

Я искал таких библиотек через Интернет и нашел следующее:

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

Наслаждайтесь

2

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

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

2

Пожалуйста, проверьте 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 ; 
    } 
+0

Любая библиотека, которая включает 'while (! Feof (fi))', с самого начала подозревается. Смотрите: [** Почему "while (! Feof (file))" всегда неправильно? **) (http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong? s = 1 | 2.6948) –

+0

while (! feof (fi)) не находится в библиотеке. Это было частью некоторого примера кода. – archimedes

+0

В одном файле 'milkstrings.c',' while (! Feof (fi)) {'появляется в строках' 306' и '371'. Хотя это правда, экземпляры завернуты на ярлык 'txtSKIPEXAMP', оба торчат как больной палец, который был поражен кувалдой. например 'grep -nhA10 'feof \ |^# if. * SKIP' milkstrings.c' Я не ваш downvote, я просто указываю, что условно скомпилирован или нет, используя' while (! feof (fi)), {'таким образом - известная плохая идея, которая может привести непосредственно к неопределенному поведению. –

1

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

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

Производительность по сравнению с SDS и станд :: строка в 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(); 

EDIT Максимальная производительность достигается путем выделения всей строки в начале (размер параметра конструктора). Если используется доля общего размера, производительность падает. Пример со 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 
+0

Библиотека sds находится на C, а ваша таблица - на C++. Кроме того, причина, по которой sds выглядит намного медленнее, заключается в том, что ваша таблица предварительно выделена, а sds будет повторно распределять несколько раз для роста. Попробуйте еще раз с помощью sdsgrowzero (s, nbr * len) или даже быстрее sdsMakeRoomFor() и посмотрите, сохраняются ли ваши тесты. – OlivierD

+0

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

Смежные вопросы