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

Flex/Bison程序适配文件输入与浮点数解析问题求助

解决Flex/Bison程序的两个问题:文件输入与浮点数解析

一、实现文件输入功能

不用替换printf为cout,Flex/Bison默认生成C代码,直接用C标准库的文件操作即可实现从指定文件读取输入。修改bison.y的main函数,通过命令行参数接收输入文件名,并用Flex提供的全局文件指针yyin打开文件:

修改后的main函数代码:

int main(int argc, char *argv[]) {
  if (argc > 1) {
    yyin = fopen(argv[1], "r");
    if (!yyin) {
      perror("Failed to open input file");
      return 1;
    }
  }
  
  if (yyparse() == 0)
     fprintf(stderr, "Successful parsing.\n");
  else
     fprintf(stderr, "error found.\n");
  
  if (yyin != stdin) fclose(yyin);
  return 0;
}

编译运行时,直接把输入文件名作为参数传入即可:

./your_program input.txt

二、实现浮点数解析

当前代码无法解析浮点数的原因有两个:一是用atoi只转换整数,二是yylval默认是int类型,无法存储浮点数。需要修改Bison的类型定义和Flex的转换逻辑:

步骤1:修改bison.y的类型定义

添加%union定义指定支持的数值类型,同时标记NUMBER和Expr的类型为浮点型:

%{
    #include <stdlib.h>
    #include <stdio.h>
%}

// 添加类型联合体
%union {
    double num;
}

%token CREATE RECORD 
%token MONO CREATELIST RECORDNUMBER
%token <num> NUMBER  // 标记NUMBER携带double类型值
%token PLUS MINUS MULT DIV PARL PARR
%token END TAB

%left PARL PARR
%left MULT DIV
%left PLUS MINUS

%type <num> Expr  // 标记Expr返回double类型值

%start Input

步骤2:修改表达式计算和输出的格式

把所有整数相关的输出和计算改为浮点型:

Line:
 END
 | Expr END { printf("Result: %.2f \n", $1); }  // 用%f输出浮点数
 | Create_table END { printf("Create Table ! \n"); }
 | Create_record_data END { printf("Record Data Created ! \n"); }
;

Expr:
 NUMBER {$$ = $1;}
 | Expr PLUS Expr {$$=$1+$3;}
 | Expr MINUS Expr {$$=$1-$3;}
 | Expr MULT Expr {$$=$1*$3;}
 | Expr DIV Expr {$$=$1/$3;}  // 浮点除法
 | PARL Expr PARR {$$=$2;}
 ; 

步骤3:修改flex.l的NUMBER转换逻辑

用atof替换atoi,并赋值给yylval.num:

[0-9]+(\.[0-9]+)? {yylval.num = atof(yytext); return NUMBER;}

注意:原正则里的[\".\"]是错误写法,直接写\.即可匹配小数点。


修改后的完整代码

flex.l

%option noyywrap
%option yylineno

%{
    #include <stdlib.h>
    #include "bison.tab.h"
    #define YYDEBUG 1
%}

%%
create_table {return CREATE;}
[ ][a-z]+ {return MONO;}
([ ][a-z]+[ ][&])+ {return CREATELIST;}

create_record_data {return RECORD;}
([ ][a-z]+)([ ]#[0-9]{1,2}) {return RECORDNUMBER;}

[0-9]+(\.[0-9]+)? {yylval.num = atof(yytext); return NUMBER;}
"+" {return PLUS;}
"-" {return MINUS;}
"*" {return MULT;}
"/" {return DIV;}
"\n" {printf("Line : %d \n",yylineno);  return END;}
"\t" {return TAB;}
"(" {return PARL;}
")" {return PARR;}

%%

bison.y

%{
    #include <stdlib.h>
    #include <stdio.h>
%}

%union {
    double num;
}

%token CREATE RECORD 
%token MONO CREATELIST RECORDNUMBER
%token <num> NUMBER
%token PLUS MINUS MULT DIV PARL PARR
%token END TAB

%left PARL PARR
%left MULT DIV
%left PLUS MINUS

%type <num> Expr

%start Input
%%

Input:
 | Input Line
;

Line:
 END
 | Expr END { printf("Result: %.2f \n", $1); }
 | Create_table END { printf("Create Table ! \n"); }
 | Create_record_data END { printf("Record Data Created ! \n"); }
;

Expr:
 NUMBER {$$ = $1;}
 | Expr PLUS Expr {$$=$1+$3;}
 | Expr MINUS Expr {$$=$1-$3;}
 | Expr MULT Expr {$$=$1*$3;}
 | Expr DIV Expr {$$=$1/$3;} 
 | PARL Expr PARR {$$=$2;}
 ; 

Create_table:
 CREATE MONO { printf("Create Table Single! \n"); } 
 | CREATE CREATELIST { printf("Create Table List ! \n"); }
 ;

Create_record_data:
 RECORD RECORDNUMBER Expr { printf("Record Created \n"); }
 ;

%%

int yyerror(char *s) {
  printf("%s \n", s);
}

int main(int argc, char *argv[]) {
  if (argc > 1) {
    yyin = fopen(argv[1], "r");
    if (!yyin) {
      perror("Failed to open input file");
      return 1;
    }
  }
  
  if (yyparse() == 0)
     fprintf(stderr, "Successful parsing.\n");
  else
     fprintf(stderr, "error found.\n");
  
  if (yyin != stdin) fclose(yyin);
  return 0;
}

内容的提问来源于stack exchange,提问作者Thanos Rom

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 01:47:22