HOWTO · C
在 C 語言中實現字典
本文介紹瞭如何在 C 語言中實現字典。
本頁內容
ISO C 沒有內建的字典型別。如果目標環境提供 POSIX hsearch 介面,便可使用其雜湊表函式儲存及查詢鍵值項目。下方範例會建立資料表、插入兩筆項目、查詢存在與不存在的鍵、檢查傳回的指標,最後釋放資料表。這只是其中一種做法,並非涵蓋所有可能的字典設計。
使用 POSIX hsearch 函式在 C 中實作字典
hcreate、hsearch 和 hdestroy 是由 <search.h> 宣告的 POSIX 函式,並非 ISO C 標準函式庫函式。這些函式是否可用,取決於目標作業系統與 C 函式庫;使用範例前,請先確認你的環境提供此介面。POSIX 的 hcreate 與 hsearch 規格定義了此介面,也列出可供查閱的相關要求。此處提供的資料未指定特定平台或函式庫版本。
使用 hcreate 和 hsearch 建立雜湊表並加入項目
呼叫一次 hcreate,即可建立具有指定容量的資料表。成功時會傳回非零值;無法建立資料表時則傳回零。ENTRY 包含一個 char * 型別的鍵,以及一個 void * 型別的資料指標。將 ENTRY 和 ACTION 值傳給 hsearch:ENTER 表示要求插入,FIND 表示要求查詢。呼叫成功時會傳回指向項目的指標;失敗時則傳回 NULL。
執行以下範例:
本節中的程式碼以及顯示的標籤或輸出仍為英文。
#define _XOPEN_SOURCE 700
#include <search.h>
#include <stdio.h>
int main(void) {
if (hcreate(4) == 0) {
fputs("could not create table\n", stderr);
return 1;
}
ENTRY item = {"language", "C"};
if (hsearch(item, ENTER) == NULL) {
fputs("could not insert language\n", stderr);
hdestroy();
return 1;
}
item.key = "standard";
item.data = "POSIX";
if (hsearch(item, ENTER) == NULL) {
fputs("could not insert standard\n", stderr);
hdestroy();
return 1;
}
ENTRY query = {"language", NULL};
ENTRY *found = hsearch(query, FIND);
if (found == NULL) {
puts("language: not found");
} else {
printf("language: %s\n", (char *)found->data);
}
query.key = "compiler";
found = hsearch(query, FIND);
if (found == NULL) {
puts("compiler: not found");
} else {
printf("compiler: %s\n", (char *)found->data);
}
hdestroy();
return 0;
}
language: C
compiler: not found
查詢鍵並處理找不到的項目
第一次呼叫 FIND 時會查詢 language;程式先前已將此鍵與值 C 一起插入。第二次則查詢未曾插入的 compiler。程式讀取 data 前會先檢查每個查詢結果,因此結果若為 NULL,就會安全地進入「找不到」的處理路徑。如果應該存在的鍵查詢結果卻是 NULL,範例也不會解參考該指標,並會回報結果。你可以依照應用程式需求調整訊息或回傳方式。範例輸出區塊中的 compiler: not found 是保留原樣的英文文字。
如果無法完成插入,hsearch 也會傳回 NULL,因此請在繼續執行前檢查每次 ENTER 的結果。範例遇到建立或插入失敗時,會將診斷訊息寫入 stderr;若資料表已建立,則先將其釋放,最後傳回失敗狀態。請在每次操作後立即檢查結果,確保後續程式只會在確認指標有效後才讀取項目。
釋放資料表並了解其限制
不再需要資料表時,請呼叫 hdestroy。它會釋放資料表,但項目所參照的動態配置鍵或值空間仍由呼叫端負責管理;請保留這些指標,並另行釋放由你管理的配置。本範例使用字串常值,因此沒有這類配置需要釋放。此處展示的 POSIX 介面沒有提供移除個別項目的操作。建立資料表時請選擇足夠的容量:將所需容量傳給 hcreate;本範例所示的操作流程中,此介面不提供調整容量的功能。