news 2026/5/26 15:59:27

C语言实现英文词频统计功能

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言实现英文词频统计功能

项目背景详细介绍

词频统计(Word Frequency Count)是文本处理与自然语言处理(NLP)中最基础,也最重要的算法之一。其核心思想是:对一段英文文本进行扫描,识别其中所有单词,并统计每个单词出现的次数。

这一技术是许多上层应用的核心模块,例如:

1. 搜索引擎倒排索引构建

搜索引擎在分析网页文本时,必须统计每个词的出现次数,以便构建倒排索引(Inverted Index),用于查询加速。如果你能实现一个英文词频统计器,就完成了倒排索引的最基础部分。

2. 文本挖掘与 NLP 特征提取

包括:

  • TF(Term Frequency)
  • TF-IDF(Text Mining 的核心)
  • Bag-of-Words(词袋模型)
  • 语言模型(Language Model)

这些算法都依赖精确的词频统计。

3. 分析文档主题和作者习惯

例如:

  • 判断某文档属于哪个主题
  • 分析作者的写作风格
  • 频率最高的词是否是停用词(Stop Words)

4. 基于 C 语言的嵌入式文本处理应用

在嵌入式系统或性能要求极高的系统中,往往无法使用 Python 或 Java,因此需要使用 C 实现高性能文本分析模块。

5. 日志分析、服务器监控

如统计访问日志中:

  • IP 地址出现次数
  • URL 出现次数
  • 特定错误码连续出现情况

其底层仍然是字符串解析 + 词频统计。

因此,使用 C 语言实现一个功能完整、高性能、可扩展的英文词频统计器,对理解文本分析的整体流程至关重要。

项目需求详细介绍

本项目实现一个强大的英文词频统计程序,要求包括:

1. 输入英文文本

来源可以是:

  • 文件读取
  • 标准输入(stdin)
  • 程序内部字符串(本示例使用文件读取)

2. 自动识别单词

单词必须满足:

  • A–Z / a–z 字母组成
  • 大小写不敏感(Hello 与 hello 视为同一个词)
  • 忽略数字、符号、标点
  • 支持长单词(如 "internationalization")

3. 统计每个单词出现次数

必须能记录:

  • 单词内容
  • 出现次数

4. 采用适合的存储结构(哈希表)

为了高效率,本项目使用链地址法哈希表(Hash Table + Linked List)

5. 输出词频统计结果

如:

the : 135 and : 87 hello : 12 computer : 7

支持按字典序或出现次数排序(本项目提供二者示例)。

6. 详细注释,适合教学

每段代码必须含有详细注释,便于课堂讲解。

7. 可扩展性强

如:

  • 忽略停用词(stop words)
  • 输出前 N 高频词
  • 导出 JSON 文件
  • 分析多文件

相关技术详细介绍

本项目涉及到多项关键 C 语言技术:

1. 字符分类与处理

使用:

  • isalpha()
  • tolower()

用于识别英文单词。

2. 字符串缓冲区

为了组装单词,需要一个动态缓冲区或固定大小数组,用来读入单词。

3. 哈希表(Hash Table)

使用链地址法(每个桶是一条链表):

  • 哈希函数采用 BKDR Hash
  • 冲突由链表解决
  • 插入效果好,查询时间 O(1)

4. 动态内存管理

包括:

  • malloc
  • realloc
  • free
  • strdup(复制字符串)

必须确保无内存泄漏。

5. 文件 IO

使用:

  • fopen
  • fgets / fgetc
  • fclose

实现逐字符解析。

6. 排序(qsort)

为了按词频排序,需要使用 C 标准库排序函数。

实现思路详细介绍

完整算法步骤如下:

步骤 1:读取文件

使用fgetc()每次读取一个字符。

步骤 2:识别单词

我们维护一个字符缓冲区wordbuf

如果字符是字母,追加到缓冲区

如果字符不是字母:

  • 当前缓冲区非空 → 说明得到了一个完整单词
  • 将单词转换为小写
  • 将单词插入哈希表
  • 清空缓冲区

步骤 3:哈希表插入逻辑

插入过程:

  • 根据哈希计算桶 index
  • 在桶的链表中查找单词是否存在
  • 若已存在:count++
  • 若不存在:创建新节点,加入链表头部

步骤 4:统计结束后输出所有词频

遍历哈希表,将所有节点存入数组,使用 qsort 排序。

步骤 5:按字典序或词频排序并输出

提供两种排序方式:

  • 字典序(lexicographical)
  • 按出现次数降序

完整实现代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

/************************************************************

* C语言实现英文词频统计(Word Frequency Count)

* 结构:哈希表 + 链地址法

* 文件:word_count.c

************************************************************/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>

#define HASH_SIZE 10007 // 哈希表大小(质数效果更好)

#define WORD_MAX_LEN 256 // 单词最大长度

/************************************************************

* 单词节点结构体:用于链表存储哈希冲突项

************************************************************/

typedefstructWordNode {

char* word;// 单词

intcount;// 出现次数

structWordNode* next;// 下一个节点

} WordNode;

/************************************************************

* 哈希表(链地址法)

************************************************************/

WordNode* hashtable[HASH_SIZE];

/************************************************************

* BKDR Hash 哈希函数

************************************************************/

unsignedintBKDRHash(constchar* str)

{

unsignedintseed = 131;

unsignedinthash = 0;

while(*str) {

hash = hash * seed + (*str++);

}

returnhash % HASH_SIZE;

}

/************************************************************

* 向哈希表插入一个单词(若存在则 count++)

************************************************************/

voidinsert_word(constchar* word)

{

unsignedintindex = BKDRHash(word);

WordNode* p = hashtable[index];

while(p) {

if(strcmp(p->word, word) == 0) {

p->count++;

return;

}

p = p->next;

}

WordNode* newNode = (WordNode*)malloc(sizeof(WordNode));

newNode->word = strdup(word);

newNode->count = 1;

newNode->next = hashtable[index];

hashtable[index] = newNode;

}

/************************************************************

* 从文件读取单词并统计

************************************************************/

voidcount_words(constchar* filename)

{

FILE* fp =fopen(filename,"r");

if(!fp) {

printf("无法打开文件: %s\n", filename);

return;

}

charch;

charwordbuf[WORD_MAX_LEN];

intwlen = 0;

while((ch =fgetc(fp)) != EOF) {

if(isalpha(ch)) {

if(wlen < WORD_MAX_LEN - 1) {

wordbuf[wlen++] =tolower(ch);

}

}else{

if(wlen > 0) {

wordbuf[wlen] ='\0';

insert_word(wordbuf);

wlen = 0;

}

}

}

if(wlen > 0) {

wordbuf[wlen] ='\0';

insert_word(wordbuf);

}

fclose(fp);

}

/************************************************************

* 排序结构

************************************************************/

typedefstruct{

char* word;

intcount;

} WordEntry;

intcmp_count(constvoid* a,constvoid* b)

{

return((WordEntry*)b)->count - ((WordEntry*)a)->count;

}

intcmp_alpha(constvoid* a,constvoid* b)

{

returnstrcmp(((WordEntry*)a)->word, ((WordEntry*)b)->word);

}

/************************************************************

* 打印所有词频(按词频或字典序排序)

************************************************************/

voidprint_words(intsort_mode)

{

WordEntry* arr = NULL;

inttotal = 0;

for(inti = 0; i < HASH_SIZE; i++) {

WordNode* p = hashtable[i];

while(p) {

total++;

p = p->next;

}

}

arr = (WordEntry*)malloc(sizeof(WordEntry) * total);

intidx = 0;

for(inti = 0; i < HASH_SIZE; i++) {

WordNode* p = hashtable[i];

while(p) {

arr[idx].word = p->word;

arr[idx].count = p->count;

idx++;

p = p->next;

}

}

if(sort_mode == 0)

qsort(arr, total,sizeof(WordEntry), cmp_alpha);

else

qsort(arr, total,sizeof(WordEntry), cmp_count);

for(inti = 0; i < total; i++) {

printf("%s : %d\n", arr[i].word, arr[i].count);

}

free(arr);

}

/************************************************************

* 主函数:接受文件名并统计

************************************************************/

intmain()

{

charfilename[256];

printf("请输入英文文本文件名:");

scanf("%s", filename);

count_words(filename);

printf("\n--- 按词频排序 ---\n");

print_words(1);

printf("\n--- 按字典序排序 ---\n");

print_words(0);

return0;

}

代码详细解读

1. WordNode 结构体

用于存储单词和出现次数,链表解决哈希冲突。

2. hashtable 数组

固定大小 10007,每项是一个链表头指针。

3. BKDRHash

经典哈希函数:

  • 冲突概率低
  • 性能高

4. insert_word()

作用:

  • 查找单词是否已存在
  • 存在 → 次数 +1
  • 不存在 → 创建新节点

5. count_words()

作用:

  • 按字符读取文件
  • 遇到字母 → 缓冲区存储
  • 遇到非字母 → 形成一个单词并插入哈希表
  • 自动转小写

6. 排序函数 cmp_count 和 cmp_alpha

支持 2 种排序:

  • 按出现次数
  • 按字典序

7. print_words()

将哈希表内容复制到数组,排序后输出。

8. main()

询问文件名 → 调用统计函数 → 打印排序结果。

项目详细总结

本项目实现了一个完整的英文词频统计系统,具有:

1. 结构清晰

采用:

  • 哈希表
  • 链地址法
  • 文件流读取
  • 自定义排序

2. 性能高

哈希查找 O(1),读取与插入速度极快。

3. 扩展性强

可以轻松加入:

  • 停用词过滤
  • 输出前 N 高频词
  • 支持多文件处理
  • 生成可视化统计结果
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/26 15:58:09

TVA凭什么成为具身机器人的“类人智眼“(系列)

重磅预告&#xff1a;本专栏将独家连载系列丛书《智能体视觉技术与应用》部分精华内容&#xff0c;该书是世界首套系统阐述“因式智能体”视觉理论与实践的专著&#xff0c;特邀美国 TypeOne 公司首席科学家、斯坦福大学博士 Bohan 担任技术顾问。Bohan先生师从美国三院院士、“…

作者头像 李华
网站建设 2026/5/26 15:57:50

国产多模态大模型:如何重塑电商推荐的未来?

国产多模态大模型&#xff1a;如何重塑电商推荐的未来&#xff1f; 引言 在电商竞争日益激烈的今天&#xff0c;如何更精准地理解用户、更生动地展示商品&#xff0c;成为平台的核心竞争力。传统的推荐系统主要依赖文本和用户行为数据&#xff0c;仿佛只通过“听其言”和“观其…

作者头像 李华
网站建设 2026/5/26 15:53:32

Web反爬不是防工具,而是建访问控制体系

1. 这不是“防爬”而是“防滥用”&#xff1a;先搞清你真正要保护什么很多人一看到“防止网站被爬虫抓取”&#xff0c;第一反应就是加个 robots.txt、封几个IP、再套个验证码——结果忙活半天&#xff0c;该被薅的API还是被刷爆&#xff0c;商品价格还是被实时盯梢&#xff0c…

作者头像 李华
网站建设 2026/5/26 15:52:32

OBS浏览器插件架构深度解析与高级配置指南

OBS浏览器插件架构深度解析与高级配置指南 【免费下载链接】obs-browser CEF-based OBS Studio browser plugin 项目地址: https://gitcode.com/gh_mirrors/ob/obs-browser OBS浏览器插件基于Chromium Embedded Framework&#xff08;CEF&#xff09;技术栈&#xff0c;…

作者头像 李华