在C语言中使用字典(附示例)
文章目录
- 在C语言中使用字典(附示例)
- 一、引言
- 二、字典的基本概念
- 1. 数据结构定义
- 2. 实现方式
- 三、C语言中字典的实现
- 1. 定义基本结构
- 2. 哈希函数(字符串哈希)
- 3. 插入键值对
- 4. 查找键值
- 5. 销毁字典释放内存
- 四、字典的应用场景及示例代码
- 场景一:配置管理器(读取配置键值对)
- ✅ 应用描述:
- ✅ 示例代码:
- ✅ 配置文件 `config.txt` 内容:
- 场景二:单词计数器(统计词频)
- ✅ 应用描述:
- ✅ 示例代码:
- 五、使用哈希表实现字典
- 1. 核心设计思路
- 2. 核心代码
- 3. 测试验证程序
- 六、结语
一、引言
在现代编程中,字典(Dictionary) 是一种非常重要的数据结构,它以 键值对(Key-Value Pair) 的形式存储数据,并通过键快速查找对应的值。虽然 C 语言本身没有内置的字典类型(如 Python 中的 dict
或 Java 中的 HashMap
),但我们可以使用 结构体 + 哈希表 的方式手动实现一个高效的字典。
本文将详细介绍:
- 字典的基本概念和原理;
- C语言中如何自定义实现字典;
- 字典的常见应用场景;
- 提供完整的可编译运行的 C 示例代码。
二、字典的基本概念
1. 数据结构定义
字典是一种关联数组(Associative Array),由一组键值对组成,其中:
- 键(Key) 是唯一的,用于标识对应的数据项。
- 值(Value) 是与键相关联的数据。
例如:
Key | Value |
---|---|
“name” | “Alice” |
“age” | 25 |
“email” | “alice@abc.com” |
2. 实现方式
C语言中可以通过以下结构实现字典:
- 使用 哈希表(Hash Table) 来提升查找效率。
- 每个哈希桶(Bucket)是一个链表节点,解决冲突问题(拉链法)。
三、C语言中字典的实现
1. 定义基本结构
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define TABLE_SIZE 100typedef struct Entry {char* key;char* value;struct Entry* next;
} Entry;typedef struct Dictionary {Entry* table[TABLE_SIZE];
} Dictionary;
2. 哈希函数(字符串哈希)
unsigned int hash(const char* key) {unsigned long int value = 0;while (*key)value = value * 37 + *key++;return value % TABLE_SIZE;
}
3. 插入键值对
void dict_set(Dictionary* dict, const char* key, const char* value) {unsigned int index = hash(key);Entry* entry = dict->table[index];// 如果已存在该键,更新值while (entry != NULL) {if (strcmp(entry->key, key) == 0) {free(entry->value);entry->value = strdup(value);return;}entry = entry->next;}// 否则创建新条目Entry* newEntry = (Entry*)malloc(sizeof(Entry));newEntry->key = strdup(key);newEntry->value = strdup(value);newEntry->next = dict->table[index];dict->table[index] = newEntry;
}
4. 查找键值
char* dict_get(Dictionary* dict, const char* key) {unsigned int index = hash(key);Entry* entry = dict->table[index];while (entry != NULL) {if (strcmp(entry->key, key) == 0)return entry->value;entry = entry->next;}return NULL; // 未找到
}
5. 销毁字典释放内存
void dict_destroy(Dictionary* dict) {for (int i = 0; i < TABLE_SIZE; i++) {Entry* entry = dict->table[i];while (entry != NULL) {Entry* tmp = entry;entry = entry->next;free(tmp->key);free(tmp->value);free(tmp);}}
}
四、字典的应用场景及示例代码
场景一:配置管理器(读取配置键值对)
✅ 应用描述:
从文本文件中读取配置项并存入字典,便于后续程序调用。
✅ 示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 此处插入上述字典定义和函数int main() {FILE* fp = fopen("config.txt", "r");if (!fp) {printf("无法打开配置文件\n");return 1;}Dictionary config;memset(&config, 0, sizeof(config));char line[256];while (fgets(line, sizeof(line), fp)) {char* key = strtok(line, "=");char* value = strtok(NULL, "\n");if (key && value) {dict_set(&config, key, value);}}fclose(fp);printf("host: %s\n", dict_get(&config, "host"));printf("port: %s\n", dict_get(&config, "port"));dict_destroy(&config);return 0;
}
✅ 配置文件 config.txt
内容:
host=localhost
port=8080
username=admin
password=secret
📌 编译命令:
gcc -o config_reader config_reader.c
场景二:单词计数器(统计词频)
✅ 应用描述:
读取一段英文文本,统计每个单词出现的次数。
✅ 示例代码:
#include <ctype.h>int main() {Dictionary word_count;memset(&word_count, 0, sizeof(word_count));char text[] = "hello world hello c programming is fun and hello world";char* token = strtok(text, " ");while (token != NULL) {char* count_str = dict_get(&word_count, token);int count = count_str ? atoi(count_str) : 0;char buffer[10];sprintf(buffer, "%d", count + 1);dict_set(&word_count, token, buffer);token = strtok(NULL, " ");}for (int i = 0; i < TABLE_SIZE; i++) {Entry* entry = word_count.table[i];while (entry != NULL) {printf("%s: %s\n", entry->key, entry->value);entry = entry->next;}}dict_destroy(&word_count);return 0;
}
📌 编译命令:
gcc -o word_counter word_counter.c
五、使用哈希表实现字典
1. 核心设计思路
我们将构建以下组件:
组件 | 描述 |
---|---|
Entry | 存储键值对的节点结构 |
HashTable | 哈希表结构,包含多个桶(bucket) |
hash() | 哈希函数,计算字符串键对应的索引 |
ht_put() | 插入或更新键值对 |
ht_get() | 获取指定键的值 |
ht_remove() | 删除指定键 |
ht_destroy() | 销毁哈希表并释放内存 |
2. 核心代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 定义哈希表大小
#define TABLE_SIZE 128// 单个键值对结构体
typedef struct Entry {char* key;char* value;struct Entry* next; // 冲突解决:拉链法
} Entry;// 哈希表结构体
typedef struct HashTable {Entry* table[TABLE_SIZE];
} HashTable;// 哈希函数:简单字符串哈希算法
unsigned int hash(const char* key) {unsigned long int value = 0;while (*key)value = value * 37 + *key++;return value % TABLE_SIZE;
}// 创建新条目
Entry* create_entry(const char* key, const char* value) {Entry* entry = (Entry*)malloc(sizeof(Entry));entry->key = strdup(key);entry->value = strdup(value);entry->next = NULL;return entry;
}// 初始化哈希表
HashTable* ht_create() {HashTable* table = (HashTable*)malloc(sizeof(HashTable));for (int i = 0; i < TABLE_SIZE; ++i)table->table[i] = NULL;return table;
}// 插入或更新键值对
void ht_put(HashTable* table, const char* key, const char* value) {unsigned int index = hash(key);Entry* current = table->table[index];// 如果键已存在,更新值while (current != NULL) {if (strcmp(current->key, key) == 0) {free(current->value);current->value = strdup(value);return;}current = current->next;}// 否则插入新条目Entry* new_entry = create_entry(key, value);new_entry->next = table->table[index];table->table[index] = new_entry;
}// 查找键对应的值
char* ht_get(HashTable* table, const char* key) {unsigned int index = hash(key);Entry* current = table->table[index];while (current != NULL) {if (strcmp(current->key, key) == 0)return current->value;current = current->next;}return NULL; // 未找到
}// 删除指定键
void ht_remove(HashTable* table, const char* key) {unsigned int index = hash(key);Entry* current = table->table[index];Entry* prev = NULL;while (current != NULL) {if (strcmp(current->key, key) == 0) {if (prev == NULL)table->table[index] = current->next;elseprev->next = current->next;free(current->key);free(current->value);free(current);return;}prev = current;current = current->next;}
}// 销毁整个哈希表
void ht_destroy(HashTable* table) {for (int i = 0; i < TABLE_SIZE; ++i) {Entry* current = table->table[i];while (current != NULL) {Entry* tmp = current;current = current->next;free(tmp->key);free(tmp->value);free(tmp);}}free(table);
}
3. 测试验证程序
下面是一个完整的测试程序,演示如何使用上述哈希表字典:
int main() {HashTable* table = ht_create();// 插入键值对ht_put(table, "name", "Alice");ht_put(table, "age", "30");ht_put(table, "email", "alice@example.com");// 修改已有键ht_put(table, "age", "31");// 查找键printf("name: %s\n", ht_get(table, "name"));printf("age: %s\n", ht_get(table, "age"));printf("email: %s\n", ht_get(table, "email"));// 删除键ht_remove(table, "email");// 尝试获取被删除的键printf("email after remove: %s\n", ht_get(table, "email")); // 应为 NULL// 释放资源ht_destroy(table);return 0;
}
📌 编译命令(GCC / MinGW):
gcc -o hash_table_dict hash_table_dict.c
📌 运行结果:
name: Alice
age: 31
email: alice@example.com
email after remove: (null)
六、结语
虽然 C 语言没有内置字典结构,但通过结构体和哈希表可以高效地实现这一功能。掌握字典的底层实现原理,有助于我们编写更高效、灵活的程序。希望本篇博客能帮助你理解并掌握 C 语言中字典的设计与应用!
研究学习不易,点赞易。
工作生活不易,收藏易,点收藏不迷茫 :)