好的C字符串库

我最近受到启发,启动了一个我想要编写一段时间的项目。 我想在C中做,因为内存处理是这个应用程序的关键。 我正在四处寻找C中字符串的良好实现,因为我知道我自己这样做会导致一些混乱的缓冲区溢出,我希望处理相当多的字符串。

我发现这篇文章详细介绍了每一个,但他们每个人都觉得他们有很多利弊(不要误会我的意思,这篇文章非常有帮助,但它仍然让我担心,即使我是选择其中之一,我不会使用我能得到的最好的)。 我也不知道这篇文章是如何更新的,因此我目前的请求。

我正在寻找的是可以容纳大量字符的东西,并简化了搜索字符串的过程。 如果它允许我以任何方式标记字符串,甚至更好。 此外,它应该有一些非常好的I / O性能。 打印和格式化打印不是最重要的。 我知道我不应该期望一个库能为我做所有的工作,但如果有一个记录良好的字符串函数可以节省我一些时间和一些工作,只是徘徊。

任何帮助是极大的赞赏。 提前致谢!

编辑:我被问及我喜欢的许可证。 任何类型的开源许可都可以,但最好是GPL(v2或v3)。

EDIt2:我找到了betterString(bstring)库,它看起来很不错。 良好的文档,小而多function的function,并且易于与c字符串混合。 有没有关于它的好故事? 我读到的唯一缺点是它缺乏Unicode(再次,读到这个,还没有看到它面对面),但其他一切似乎都很好。

EDIT3:另外,最好是纯C.

这是一个老问题,我希望你已经找到了一个有用的问题。 如果不这样做,请查看github上的Simple Dynamic String库。 我在这里复制并粘贴作者的描述:

SDS是C的字符串库,旨在通过添加堆分配的字符串来增强有限的libc字符串处理function:

  • 使用起来更简单。
  • 二进制安全。
  • 计算效率更高。
  • 但是……与普通的C字符串函数兼容。

这是使用替代设计实现的,其中我们使用二进制前缀而不是使用C结构来表示字符串,而是存储在SDS返回给用户的字符串的实际指针之前。

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

由于在实际返回的指针之前存储的元数据作为前缀,并且由于每个SDS字符串隐含地在字符串的末尾添加空术语而不管字符串的实际内容如何,​​因此SDS字符串与C字符串和用户可以与以只读方式访问字符串的实际函数互换使用它们。

我建议不要使用除mallocfreestrlenmemcpysnprintf之外的任何库。 这些函数为您提供了在C中进行强大,安全和高效字符串处理的所有工具。只需远离strcpystrcatstrncpystrncat ,所有这些都会导致低效和可利用的错误。

既然你提到了搜索,无论你选择strchr库, strchrstrstr几乎肯定会成为你想要使用的。 strspnstrcspn也很有用。

如果你真的想从头开始做到这一点,你应该看看ICU ,即Unicode支持,除非你确定你的字符串永远不会包含任何东西,只有普通的ASCII-7 …搜索,正则表达式,标记化都在那里。

当然,使用C ++会让事情变得更容易,但即便如此,我对ICU的建议仍然有效。

请检查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 = %ds = %s \n",num,s) ; s = txtPrintf("%s,%d",s,num) ; // printf in new string printf("num = %ds = %s \n",num,s) ; s = txtConcat(s,"<-->",txtFlip(s),NULL) ; // concatenate some strings num = txtPos(s,"987") ; // find position of substring printf("num = %ds = %s \n",num,s) ; if (txtAnyError()) { //check for errors printf("%s\n",txtLastError()) ; return 1 ; } return 0 ; } 

我还发现需要一个外部C字符串库,因为我发现函数非常低效,例如:

  • strcat()性能非常昂贵,因为每次连接字符串时都必须找到’\ 0’char
  • strlen()很昂贵,同样,它必须找到’\ 0’字符而不是只读取一个维护的length变量
  • char数组当然不是动态的,可能会导致非常危险的错误(当你溢出缓冲区时,分段错误崩溃可能是个好方案)

解决方案应该是一个不仅包含函数的库,还包含一个包装字符串的结构,它可以存储重要的字段,如lengthbuffer-size

我通过网络查找了这些库,发现了以下内容:

  1. GLib字符串库(应该是最好的标准解决方案) – https://developer.gnome.org/glib/stable/glib-Strings.html
  2. http://locklessinc.com/articles/dynamic_cstrings/
  3. http://bstring.sourceforge.net/

请享用

我最近遇到了这个问题,需要附加一个包含数百万个字符的字符串。 我最终做了自己的事。

它只是一个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(); 

编辑通过在start(构造函数参数大小)分配字符串all来实现最大性能。 如果使用总大小的一小部分,性能会下降。 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