You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu下GNU make示例中Flex Scanner陷入无限循环求助

问题描述

在Ubuntu系统中复现《Managing projects with GNU make》第5页的Flex Scanner示例时,执行./count_words This is a test fue后出现空白输出,疑似陷入无限循环。已确认Flex和libfl.a已安装,补充了书中遗漏的stdlib.h,添加了推荐的.\n规则,但问题仍未解决。

相关代码如下:

count_words.c(应用源码)

#include <stdio.h>
#include <stdlib.h> 

extern int fee_count, fie_count, foe_count, fum_count; 
extern int yylex( void ); 

int main( int argc, char ** argv )
{
 yylex();
 printf( "%d %d %d %d\n", fee_count, fie_count, foe_count, fum_count );
 exit( 0 );
}

lexer.l(Flex Scanner输入文件)

int fee_count = 0;
        int fie_count = 0;
        int foe_count = 0;
        int fum_count = 0;

%%
fee fee_count++;
fie fie_count++;
foe foe_count++;
fum fum_count++;

Makefile

count_words: count_words.o lexer.o -lfl
	gcc count_words.o lexer.o -lfl -ocount_words
count_words.o: count_words.c
	gcc -c count_words.c
lexer.o: lexer.c
	gcc -c lexer.c
lexer.c: lexer.l
	flex -t lexer.l > lexer.c

故障原因
  1. 未处理命令行参数:当前代码里yylex()默认从标准输入(stdin)读取内容,但执行时传入的命令行参数(比如This is a test fue)完全没被程序处理,程序会卡在那里等待键盘输入,看起来像无限循环,实际是在等待输入。
  2. 缺少终止逻辑与默认规则:原lexer.l没有定义非目标文本的处理规则,且Flex生成的扫描器需要yywrap()函数判断输入是否结束,原代码缺失该函数,加上输入源未正确指定,导致扫描器无法正常退出。

修复方案

方案1:修改代码处理命令行参数

Flex生成的扫描器用yyin作为输入文件指针,我们可以在main函数里把命令行参数拼接后传入:

修改后的count_words.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern int fee_count, fie_count, foe_count, fum_count;
extern int yylex( void );
extern FILE *yyin; // Flex内置的输入文件指针

int main( int argc, char ** argv )
{
    if (argc > 1) {
        // 把所有命令行参数写入临时文件,供扫描器读取
        FILE *temp_file = tmpfile();
        for (int i = 1; i < argc; i++) {
            fprintf(temp_file, "%s ", argv[i]);
        }
        rewind(temp_file); // 回到文件开头
        yyin = temp_file;
    }
    yylex();
    printf( "%d %d %d %d\n", fee_count, fie_count, foe_count, fum_count );
    exit( 0 );
}

方案2:完善lexer.l的规则与终止逻辑

在lexer.l里添加默认规则忽略非目标字符,同时补充yywrap()函数让扫描器能正常结束:

修改后的lexer.l:

int fee_count = 0;
        int fie_count = 0;
        int foe_count = 0;
        int fum_count = 0;

%%
fee         fee_count++;
fie         fie_count++;
foe         foe_count++;
fum         fum_count++;
.|\n        ; // 忽略所有不匹配的字符(包括换行)
%%

// Flex需要这个函数判断输入是否结束,返回1表示结束
int yywrap(void) {
    return 1;
}

方案3:不修改代码,用管道传入输入

如果不想改代码,直接通过管道把内容传给程序:

echo "This is a test fee fie foe fum" | ./count_words

内容的提问来源于stack exchange,提问作者yossi-matkal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 07:15:16