好的C字符串库

好的C字符串库,c,string,search,io,C,String,Search,Io,我最近受到启发,开始了一个我一直想编写代码的项目。我想用C语言来做,因为内存处理是这个应用程序的关键。我一直在寻找C语言中字符串的良好实现,因为我知道我自己这样做可能会导致一些混乱的缓冲区溢出,我希望处理相当多的字符串 我找到了一篇文章,其中详细介绍了每一项,但它们似乎都有很多缺点(别误会,这篇文章非常有用,但它仍然让我担心,即使我选择其中一项,我也不会尽我所能)。我也不知道这篇文章是如何更新的,因此我现在的请求 我要找的东西可能包含大量字符,并简化了搜索字符串的过程。如果它允许我以任何方式标记

我最近受到启发,开始了一个我一直想编写代码的项目。我想用C语言来做,因为内存处理是这个应用程序的关键。我一直在寻找C语言中字符串的良好实现,因为我知道我自己这样做可能会导致一些混乱的缓冲区溢出,我希望处理相当多的字符串

我找到了一篇文章,其中详细介绍了每一项,但它们似乎都有很多缺点(别误会,这篇文章非常有用,但它仍然让我担心,即使我选择其中一项,我也不会尽我所能)。我也不知道这篇文章是如何更新的,因此我现在的请求

我要找的东西可能包含大量字符,并简化了搜索字符串的过程。如果它允许我以任何方式标记字符串,那就更好了。此外,它应该有一些相当好的I/O性能。打印和格式化打印并不是首要任务。我知道我不应该期望一个库为我完成所有的工作,但我只是想知道是否有一个文档化良好的字符串函数可以为我节省一些时间和工作

非常感谢您的帮助。提前谢谢

编辑:有人问我喜欢哪个许可证。任何种类的开源许可都可以,但最好是GPL(v2或v3)

编辑2:我找到了betterString(bstring)库,它看起来很不错。好的文档,小而多功能的函数,并且易于与c字符串混合。有人有关于它的好的或坏的故事吗?我读到的唯一的缺点是它缺少Unicode(同样,读到这篇文章,我还没有面对面地看到它),但其他一切似乎都很好


编辑3:另外,最好是纯C。

我建议不要使用任何库,除了
malloc
free
strlen
memcpy
snprintf
。这些函数为您提供了C语言中强大、安全和高效字符串处理的所有工具。请远离
strcpy
strcat
strncpy
、和
strncat
,所有这些都会导致效率低下和可利用的错误


既然您提到了搜索,那么无论您选择什么样的库,
strchr
strstrstr
几乎肯定会成为您想要使用的库
strspn
strcspn
也很有用。

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

  • strcat()
    在性能上可能非常昂贵,因为它必须在每次连接字符串时找到“\0”字符
  • strlen()
    非常昂贵,同样,它必须找到“\0”字符,而不是只读取维护的
    length
    变量
  • char数组当然不是动态的,可能会导致非常危险的bug(当您的缓冲区溢出时,分段错误崩溃可能是一个好的情况)
解决方案应该是一个库,它不仅包含函数,还包含一个包装字符串的结构,并允许存储重要字段,如
长度
缓冲区大小

我在网上查找了这些库,发现了以下内容:

  • GLib字符串库(应为最佳标准解决方案)——

  • 享受

    如果你真的想从一开始就做好,你应该看看,即Unicode支持,除非你确定你的字符串永远只能容纳普通的ASCII-7。。。搜索、正则表达式、标记化都在这里


    当然,C++会使事情变得简单很多,但是即使我的ICU的建议也会成立。

    < P>这是一个老问题,我希望你已经找到了一个有用的。如果没有,请查看上的简单动态字符串库。我在此处复制并粘贴作者的描述:

    SDS是一个用于C的字符串库,旨在扩充有限的libc字符串 通过添加堆分配的字符串来处理功能,这些字符串是:

    • 使用起来更简单
    • 二进制安全
    • 计算效率更高
    • 但是。。。与普通的C字符串函数兼容
    这是通过使用替代设计来实现的,在替代设计中,不使用C 结构来表示字符串,我们使用存储的二进制前缀 在SDS返回给用户的字符串的实际指针之前

    +--------+-------------------------------+-----------+
    | Header | Binary safe C alike string... | Null term |
    +--------+-------------------------------+-----------+
             |
             `-> Pointer returned to the user.
    
    由于元数据存储在实际返回指针之前作为前缀, 因为每个SDS字符串都会在 不管字符串的实际内容如何,SDS字符串都可以工作 以及C字符串,用户可以自由地互换使用它们 使用只读访问字符串的纯实函数。

    请检查。
    示例代码:

    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 ;
      }
    
    intmain(intargc,char*argv[]){
    tXt s=“123456789”;
    s=txtReplace(s,“123”,“321”);//将123替换为321
    int num=atoi(txtEat(&s,,');//选择第一个数字
    printf(“num=%d s=%s\n”,num,s);
    s=txtPrintf(“%s,%d”,s,num);//新字符串中的printf
    printf(“num=%d s=%s\n”,num,s);
    s=txtcontat(s,“,txtFlip(s),NULL);//连接一些字符串
    num=txtPos(s,“987”);//查找子字符串的位置
    printf(“num=%d s=%s\n”,num,s);
    如果(txtAnyError()){//检查错误
    printf(“%s\n”,txtLastError());
    返回1;}
    返回0;
    }
    
    我最近遇到了这个问题,需要在字符串后面追加数百万个字符。最后我自己做了

    它只是一个C字符数组,封装在一个类中,该类跟踪数组大小和分配的字节数

    与SDS和std::string相比,性能为1
    | 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();
    
    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