我最近受到启发,启动了一个我想要编写代码的项目。我想在C中做,因为内存处理是这个应用程序的关键。我正在四处寻找C中字符串的良好实现,因为我知道我自己这样做会导致一些混乱的缓冲区溢出,而且我希望处理相当多的字符串。
我发现this文章详细介绍了每一个,但他们每个人都觉得他们有很多利弊(不要误解我的意思,这篇文章非常有帮助,但它仍然令人担忧我,即使我选择其中之一,我也不会使用我能得到的最好的)。我也不知道这篇文章是如何更新的,因此我目前的请求。
我正在寻找的东西可能包含大量字符,并简化了搜索字符串的过程。如果它允许我以任何方式标记字符串,甚至更好。此外,它应该有一些非常好的I / O性能。打印和格式化打印不是最重要的。我知道我不应该指望一个库为我做所有的工作,但只是在那里有一个记录良好的字符串函数,这可以节省我一些时间和一些工作。
非常感谢任何帮助。提前谢谢!
编辑:我被问及我喜欢的许可证。任何类型的开源许可都可以,但最好是GPL(v2或v3)。EDIt2:我找到了betterString(bstring)库,它看起来很不错。良好的文档,小而多功能的功能,并且易于与c字符串混合。有没有关于它的好故事?我读到的唯一缺点是它缺乏Unicode(再次,读到这个,还没有看到它面对面),但其他一切似乎都很好。
EDIT3:另外,最好是纯C。
答案 0 :(得分:27)
这是一个老问题,我希望你已经找到了一个有用的问题。如果您没有,请查看github上的简单动态字符串库。我在这里复制并粘贴作者的描述:
SDS是C的字符串库,旨在增强有限的libc字符串 通过添加堆分配的字符串来处理功能:
这是使用替代设计而不是使用C来实现的 表示字符串的结构,我们使用存储的二进制前缀 在指向SDS返回给用户的字符串的实际指针之前。
+--------+-------------------------------+-----------+
| Header | Binary safe C alike string... | Null term |
+--------+-------------------------------+-----------+
|
`-> Pointer returned to the user.
由于在实际返回指针之前存储的元数据作为前缀, 并且因为每个SDS字符串隐含地在末尾添加一个空术语 字符串无论字符串的实际内容如何,SDS字符串都有效 与C字符串一起使用,用户可以互换使用它们 使用只读函数以只读方式访问字符串。
答案 1 :(得分:9)
我建议不要使用除malloc
,free
,strlen
,memcpy
和snprintf
之外的任何库。这些函数为您提供了在C语言中进行强大,安全和高效字符串处理的所有工具。只需远离strcpy
,strcat
,strncpy
和strncat
,其中往往会导致效率低下和可利用的漏洞。
由于您提到了搜索,无论您选择哪种库,strchr
和strstr
几乎肯定会成为您想要使用的库。 strspn
和strcspn
也很有用。
答案 2 :(得分:2)
如果你真的想从头开始做到这一点,你应该看看ICU,即Unicode支持,除非你确定你的字符串永远不会包含任何东西,只有普通的ASCII- 7 ...搜索,正则表达式,标记化都在那里。
当然,使用C ++可以使更多更容易,但即便如此,我对ICU的建议仍然有效。
答案 3 :(得分: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 ;
}
答案 4 :(得分:1)
我还发现需要一个外部C字符串库,因为我发现<string.h>
函数非常低效,例如:
strcat()
在性能上可能非常昂贵,因为每次连接字符串时都必须找到'\ 0'字符strlen()
价格昂贵,因为它必须找到'\ 0'字符而不是只读取维护的length
变量解决方案应该是一个不仅包含函数的库,还包含一个包装字符串的结构,它可以存储重要的字段,例如length
和buffer-size
我通过网络查找了这些库,发现了以下内容:
答案 5 :(得分:1)
我最近遇到了这个问题,需要附加一个包含数百万个字符的字符串。我最终做了自己的事。
它只是一个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();
EDIT 通过在start(构造函数参数大小)分配字符串来实现最大性能。如果使用总大小的一小部分,性能会下降。 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