web-dev-qa-db-ja.com

良いC文字列ライブラリ

私は最近、しばらくの間コーディングしたいと思っていたプロジェクトを立ち上げることにインスピレーションを得ました。このアプリケーションではメモリ処理が重要なので、Cで実行したいと思います。私はCで文字列の適切な実装を探していました。自分でそれを行うと、厄介なバッファオーバーフローが発生する可能性があることを知っており、かなり大量の文字列を処理することを期待しています。

私は this それぞれの詳細を説明する記事を見つけましたが、それぞれにかなりの短所があるようです(誤解しないでください、この記事は非常に役立ちますが、それでも心配です私は、それらの1つを選択したとしても、入手できる最善のものを使用しないだろうと思いました)。私はまた、記事がどれほど最新であるかを知らないので、私の現在の嘆願です。

私が探しているのは、大量の文字を保持できるものであり、文字列を検索するプロセスを簡素化します。それが私に何らかの方法で文字列をトークン化することを可能にするなら、さらに良いです。また、かなり良好なI/Oパフォーマンスが必要です。印刷、およびフォーマットされた印刷は、最優先事項ではありません。ライブラリがすべての作業を行うことを期待するべきではないことはわかっていますが、時間と作業を節約できる十分に文書化された文字列関数がそこにあるかどうかをさまよっていました。

どんな助けでも大歓迎です。前もって感謝します!

編集:私は私が好むライセンスについて尋ねられました。どんな種類のオープンソースライセンスでもかまいませんが、GPL(v2またはv3)が望ましいです。

EDIt2:betterString(bstring)ライブラリを見つけましたが、かなり見栄えがします。優れたドキュメント、小さいながらも用途の広い関数、およびc文字列との混合が容易です。誰かがそれについて良い話や悪い話がありますか?私がそれについて読んだ唯一の欠点は、それがUnicodeを欠いていることです(これについても読んで、まだ顔を合わせて見ていません)が、他のすべてはかなり良いようです。

EDIT3:また、その純粋なCよりも望ましい。

27
chamakits

これは古い質問です。すでに役立つ質問を見つけていただければ幸いです。そうでない場合は、 githubSimple Dynamic Stringライブラリを確認してください。私はここに著者の説明をコピー&ペーストします:

SDSは、ヒープに割り当てられた次の文字列を追加することにより、制限されたlibc文字列処理機能を拡張するように設計されたC用の文字列ライブラリです。

  • 使い方が簡単です。
  • バイナリセーフ。
  • 計算上より効率的です。
  • しかしまだ...通常のC文字列関数と互換性があります。

これは、C構造体を使用して文字列を表す代わりに、SDSによってユーザーに返される文字列への実際のポインターの前に格納されるバイナリプレフィックスを使用する代替設計を使用して実現されます。

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

実際に返されるポインタの前にプレフィックスとして格納されるメタデータと、文字列の実際の内容に関係なく、すべてのSDS文字列が文字列の最後に暗黙的にヌル項を追加するため、SDS文字列はC文字列およびユーザーは、読み取り専用で文字列にアクセスする実数専用関数と互換的にそれらを自由に使用できます。

27
Steinway Wu

mallocfreestrlenmemcpy、およびsnprintf以外のライブラリは使用しないことをお勧めします。これらの関数は、Cで強力、安全、効率的な文字列処理を行うためのすべてのツールを提供します。strcpystrcatstrncpy、およびstrncat、これらはすべて非効率で悪用可能なバグにつながる傾向があります。

検索について言及したので、どのライブラリを選択しても、strchrstrstrがほぼ確実に使用したいものになります。 strspnstrcspnも役立ちます。

9
R..

本当に最初から正しく理解したい場合は、 [〜#〜] icu [〜#〜] 、つまりUnicodeサポートを確認する必要があります。ただし、sure文字列はプレーンASCII-7以外のものを保持することはありません...検索、正規表現、トークン化はすべてそこにあります。

もちろん、C++に移行すると、物事が簡単になりますはるかにですが、それでもICU)という私の推奨事項は有効です。

2
DevSolar

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 ;
  }
2
archimedes

また、_<string.h>_関数が非常に非効率的であることがわかったため、外部C文字列ライブラリが必要であることがわかりました。次に例を示します。

  • strcat()は、文字列を連結するたびに '\ 0'文字を見つける必要があるため、パフォーマンスが非常に高くなる可能性があります。
  • strlen()は高価です。繰り返しになりますが、維持されているlength変数を読み取るだけでなく、「\ 0」文字を見つける必要があります。
  • もちろん、char配列は動的ではなく、非常に危険なバグを引き起こす可能性があります(セグメンテーション違反でのクラッシュは、バッファーがオーバーフローした場合の良いシナリオになる可能性があります)

解決策は、関数だけでなく、文字列をラップし、lengthや_buffer-size_などの重要なフィールドを格納できる構造体も含むライブラリである必要があります。

私はそのようなライブラリをWebで探し、次のことを見つけました。

  1. GLib文字列ライブラリ(最良の標準ソリューションである必要があります) https://developer.gnome.org/glib/stable/glib-Strings.html
  2. http://locklessinc.com/articles/dynamic_cstrings/
  3. http://bstring.sourceforge.net/

楽しい

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();

編集最大のパフォーマンスは、文字列をすべて開始時に割り当てることによって達成されます(コンストラクターパラメーターのサイズ)。合計サイズの一部を使用すると、パフォーマンスが低下します。 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
1
Pedro Vicente