如何使用Flex和Bison统计单词中的字符重复次数
Flex+Bison实现单词字符重复次数统计实现思路
整个实现不需要设计复杂的语法规则,核心把词法切分、计数逻辑拆到Flex、Bison两层分别实现即可,具体落地步骤如下:
Flex层(词法分析)实现
- 核心负责切分输入流,把非单词内容全部过滤:匹配空白符(空格、换行、制表符)、常用标点时直接跳过,不向Bison传递任何token
- 匹配连续字母组成的单词序列时,将匹配到的字符串通过
yylval传递给Bison,对应token标记为WORD即可 - 匹配到输入结束符
<<EOF>>时返回0,通知Bison输入处理完成 - 记得实现
yywrap函数返回1,避免编译时出现链接错误
Flex端核心规则代码参考:
%{ #include "y.tab.h" %} %% [a-zA-Z]+ { yylval.str = strdup(yytext); return WORD; } [ \t\n\r,.!?;:"'()\[\]{}]+ { /* 跳过所有单词分隔符、标点符号 */ } <<EOF>> { return 0; } %% int yywrap() { return 1; }
Bison层(语法处理+统计逻辑)实现
- 前置定义:将
yylval的联合体类型中增加字符串指针成员,用于接收Flex传递的单词内容;定义长度为256的整型数组作为计数器,对应ASCII全字符集的出现次数,初始值全部置0 - 语法规则做极简设计即可:产生式只需要定义输入为0个或多个
WORD的序列,每匹配到一个WORD,就遍历字符串的每一个字符,对应计数器下标的值累加1,遍历完成后释放Flex通过strdup分配的字符串内存,避免内存泄漏 - 所有输入解析完成后,遍历计数器数组,输出所有出现次数≥2的字符及其出现次数即可
Bison端核心代码参考:
%{ #include <stdio.h> #include <string.h> #include <stdlib.h> // 字符出现次数计数器,下标对应ASCII值 int char_cnt[256] = {0}; void yyerror(const char *err) { fprintf(stderr, "解析错误: %s\n", err); } %} %union { char *str; } %token <str> WORD %% input: | input WORD { char *cur = $2; while (*cur != '\0') { char_cnt[(unsigned char)*cur]++; cur++; } free($2); } ; %% int main() { yyparse(); printf("=== 字符重复统计结果 ===\n"); for (int i = 0; i < 256; i++) { if (char_cnt[i] >= 2) { printf("字符 '%c' 重复出现,总次数: %d\n", i, char_cnt[i]); } } return 0; }
适配调整说明
如果你的需求是统计单个单词内部的字符重复次数,而非全局所有文本的字符总重复次数,只需要调整计数器的重置时机:每次匹配到新的WORD时先把计数器数组全量置0,遍历完当前单词的所有字符后立刻打印该单词的统计结果,再继续处理下一个单词即可。
编译执行的命令参考:
bison -d count.y flex count.l gcc lex.yy.c y.tab.c -o char_count -lfl # 执行后直接输入文本,按Ctrl+D触发EOF即可输出统计结果 ./char_count
内容的提问来源于stack exchange,提问作者Deaa Jahjah
相关产品推荐
相关产品推荐

