如何编写Lex程序检测并统计全大写单词?
解决Lex中全大写单词统计的正则表达式问题
你的原代码存在逻辑缺陷,会把混合大小写单词里的连续大写片段误判为全大写单词,比如"tODAY"里的"ODAY"会被错误计数。问题出在原正则[A-Z]+[^a-z][ \t\n]只检查了大写字母后面的字符不是小写字母+空白,但没确保整个单词从开头到结尾都是大写字母。
修正后的代码方案一(通用Lex兼容)
%{ int capital_count = 0; %} %% (^|[^a-zA-Z])[A-Z]+([^a-zA-Z]|$) { capital_count++; } .|\n ; // 忽略所有非目标字符,包括换行 %% int main() { yylex(); printf("Number of capital words: %d\n", capital_count); return 0; }
正则逻辑说明:
(^|[^a-zA-Z]):匹配行首,或者非字母字符,确保目标单词前面不是字母(避免截取混合单词的大写部分)[A-Z]+:匹配一个或多个连续大写字母,这是我们要统计的全大写单词主体([^a-zA-Z]|$):匹配非字母字符或行尾,确保目标单词后面不是字母(避免混合单词的后续部分干扰)
修正后的代码方案二(GNU Flex简化版)
如果使用GNU Flex(多数环境默认的Lex实现),可以利用内置的单词边界语法\<和\>,代码更简洁:
%{ int capital_count = 0; %} %% \<[A-Z]+\> { capital_count++; } .|\n ; // 忽略其他字符 %% int main() { yylex(); printf("Number of capital words: %d\n", capital_count); return 0; }
\<表示单词的起始边界(前面是非单词字符,如空格、标点、行首),\>表示单词的结束边界(后面是非单词字符),这样能精准匹配完全由大写字母组成的独立单词,不会误判混合大小写的情况。
内容的提问来源于stack exchange,提问作者Chunxin Tan
相关产品推荐
相关产品推荐

