Provided by: manpages-ja-dev_0.5.0.0.20221215+dfsg-1_all bug

名前

       hcreate, hdestroy, hsearch, hcreate_r, hdestroy_r, hsearch_r - ハッシュテーブルの管理

書式

       #include <search.h>

       int hcreate(size_t nel);

       ENTRY *hsearch(ENTRY item, ACTION action);

       void hdestroy(void);

       #define _GNU_SOURCE         /* feature_test_macros(7) 参照 */
       #include <search.h>

       int hcreate_r(size_t nel, struct hsearch_data *htab);

       int hsearch_r(ENTRY item, ACTION action, ENTRY **retval,
                     struct hsearch_data *htab);

       void hdestroy_r(struct hsearch_data *htab);

説明

       hcreate(),  hsearch(), hdestroy()  の 3 つの関数を利用すると、キー (文字列) と対応するデー
       タから構成される  エントリーを格納できるハッシュ検索テーブルを作成、管理することができる。
       これらの関数を使って、一度に使用できるのは一つのハッシュテーブルだけである。

       hcreate_r(),  hsearch_r(), hdestroy_r()  の 3 つの関数はリエントラント版で、これらを利用す
       ると、 一つのプログラムで同時に複数のハッシュテーブルを使うことができる。 最後の引数  htab
       は関数の操作対象となるテーブルを示す構造体へのポインターである。  プログラマはこの構造体を
       ブラックボックスとして扱うべきである (つまり、この構造体のフィールドに直接アクセスしたり変
       更したり しないこと)。

       最初に、 hcreate()  関数によってハッシュテーブルを作成しなければならない。 引数 nel でテー
       ブルの最大エントリー数を指定する (この最大値は後で変更することはできないので、よく考えて選
       択すること)。  作成されるハッシュテーブルの性能を向上させるために、 関数内部の実装によりこ
       の値は増やされる場合もある。

       hcreate_r()  関数は hcreate()  と同じ動作をするが、構造体 *htab で示されるテーブルを対象と
       して動作する。  htab が指し示す構造体は、 hcreate_r()  を初めて呼び出す前に 0 で埋めておか
       なければならない。

       hdestroy()  関数は、 hcreate()  で作成されたハッシュテーブルが占有していたメモリーを解放す
       る。 ハッシュテーブルによって占有されていたメモリーを解放し、 新しいテーブルを作成できるよ
       うにする。 hdestroy()  を呼び出すと、その後は hcreate()   を使って新しいハッシュテーブルを
       作成することができる。  hdestroy_r()  関数は、同様の処理を、それ以前に hcreate_r()  を使っ
       て作成した *htab で示されるハッシュテーブルに対して実行する。

       hsearch()  関数は、item と同じキーを持つ項目をハッシュテーブルから  検索し、項目が見つかっ
       た場合にはその項目へのポインターを返す (「同じ」かどうかは strcmp(3)  を使って判定する)。

       引数 itemENTRY 型であり、<search.h> の中で 以下のように定義されている。

           typedef struct entry {
               char *key;
               void *data;
           } ENTRY;

       フィールド key は検索キーとなるヌル終端された文字列を指す。 フィールド data は、このキーに
       対応するデータを指す。

       検索が失敗した後の動作は、引数 action により決まる。 この引数には ENTERFIND のいずれか
       の値を指定しなければならない。  ENTERitem のコピーを挿入することを (関数の結果として新
       しいハッシュテーブルエントリーへのポインターを返す)、 FIND  は  NULL  を返すことを意味する
       (actionFIND の場合、 data は無視される)。

       hsearch_r()  関数は hsearch()  と同様だが、 *htab で示されるハッシュテーブルに対して処理を
       行う。 hsearch_r()  関数が hsearch()  と異なるのは、見つかった項目へのポインターを、  関数
       の結果としてではなく、 *retval に格納して返す点である。

返り値

       hcreate()   と  hcreate_r()   は、成功した場合  0 以外の値を返す。 エラーの場合 0 を返し、
       errno にエラーの原因を示す値を設定する。

       成功すると、 hsearch()  は、ハッシュテーブル内のエントリーへのポインターを返す。  エラーの
       場合、 hsearch()  は NULL を返す。 エラーとなるのは、 actionENTER でハッシュテーブルが
       いっぱいの場合か、 actionFINDitem がハッシュテーブル内に  見つからない場合である。
       hsearch_r()   は、成功すると 0 以外を返し、エラーの場合 0 を返す。 エラーの場合、 これら二
       つの関数は errno にエラーの原因を示す値を設定する。

エラー

       hcreate_r()  と hdestroy_r()  は以下の理由で失敗する可能性がある。

       EINVAL htab が NULL である。

       hsearch()  と hsearch_r()  は以下の理由で失敗する可能性がある。

       ENOMEM actionENTER で、 key がテーブル内に見つからず、  テーブルに新しいエントリーを追
              加する余地がなかった。

       ESRCH  actionFIND で、 key がテーブル内に見つからなかった。

       POSIX.1 が規定しているのは、エラー ENOMEM だけである。

属性

       この節で使用されている用語の説明については、 attributes(7) を参照。

       ┌──────────────────────────┬───────────────┬────────────────────────┐
       │インターフェース属性                     │
       ├──────────────────────────┼───────────────┼────────────────────────┤
       │hcreate(), hsearch(),     │ Thread safety │ MT-Unsafe race:hsearch │
       │hdestroy()                │               │                        │
       ├──────────────────────────┼───────────────┼────────────────────────┤
       │hcreate_r(), hsearch_r(), │ Thread safety │ MT-Safe race:htab      │
       │hdestroy_r()              │               │                        │
       └──────────────────────────┴───────────────┴────────────────────────┘

準拠

       関数  hcreate(),  hsearch(),  hdestroy()   は  SVr4  から導入されたもので、POSIX.1-2001 と
       POSIX.1-2008 に記述されている。

       関数 hcreate_r(), hsearch_r(), hdestroy_r() は GNU による拡張である。

注意

       通常、ハッシュテーブルの実装は、衝突を最小限にするために  テーブルに十分な空き領域がある場
       合に効率がよくなる。 このため、普通は、 nel を、呼び出し側がテーブルに格納しようと思ってい
       る エントリーの最大数より少なくとも 25% は大きな値にすべきである。

       hdestroy()  と hdestroy_r()  は、ハッシュテーブルのエントリーの要素である keydata が指
       すバッファーを解放しない (これができないのは、これらのバッファーが動的に割り当てられたのか
       を 知ることができないからである)。 これらのバッファーを解放する必要がある場合、 プログラム
       では、これらのバッファーを解放できるように管理用のデータ構造を  設けて、これを管理しなけれ
       ばならない  (解放が必要となる理由は、たいていは、プログラム自身と生存期間が同じ   ハッシュ
       テーブルを一つだけ作成するのではなく、そのプログラムでは複数の  ハッシュテーブルを繰り返し
       て作成したり破棄したりするからであろう)。

バグ

       SVr4 と POSIX.1-2001  の規定では、  action  は検索が失敗したときにだけ意味を持つとなってい
       る。 よって、検索が成功した場合、action の値が ENTER でも 何もすべきではない。 (バージョン
       2.3 より前の) libc と glibc の実装はこの規格に違反しており、 この状況で、指定された key に
       対応する data が更新される。

       ハッシュテーブルエントリーの追加はできるが、削除ができない。

       次のプログラムは、ハッシュテーブルに  24 個の項目を挿入し、 それからそのうちのいくつかを表
       示する。

       #include <stdio.h>
       #include <stdlib.h>
       #include <search.h>

       static char *data[] = { "alpha", "bravo", "charlie", "delta",
            "echo", "foxtrot", "golf", "hotel", "india", "juliet",
            "kilo", "lima", "mike", "november", "oscar", "papa",
            "quebec", "romeo", "sierra", "tango", "uniform",
            "victor", "whisky", "x-ray", "yankee", "zulu"
       };

       int
       main(void)
       {
           ENTRY e;
           ENTRY *ep;

           hcreate(30);

           for (int i = 0; i < 24; i++) {
               e.key = data[i];
               /* データは、ポインターではなく、単なる整数値である。 */
               e.data = (void *) i;
               ep = hsearch(e, ENTER);
               /* エラーは起こらないはずである。 */
               if (ep == NULL) {
                   fprintf(stderr, "entry failed\n");
                   exit(EXIT_FAILURE);
               }
           }

           for (int i = 22; i < 26; i++) {
               /* テーブルにある 2 つのエントリーを表示し、
                  あとの 2 つがテーブルにないことを示す。 */
               e.key = data[i];
               ep = hsearch(e, FIND);
               printf("%9.9s -> %9.9s:%d\n", e.key,
                      ep ? ep->key : "NULL", ep ? (int)(ep->data) : 0);
           }
           hdestroy();
           exit(EXIT_SUCCESS);
       }

関連項目

       bsearch(3), lsearch(3), malloc(3), tsearch(3)

この文書について

       この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの
       説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。