小数点后的数字在 bison 和 flex 中替换为 0

问题描述

我是野牛和 flex 的新手。我分配浮点值假设 a=12.34 。但是当我打印值时我发现 12.000000。请帮助我。提前致谢。lex 文件 ruturn 浮点值很好。我打印了值在代码的不同位置,那没问题。但是当在变量中分配值时就会出现问题,然后将小数点后的值替换为).

这是我的野牛文件

    /*C declarations (types,variables,functions,preprocessor commands)*/

    %{
        #include<stdio.h>
        # include <stdlib.h>
        # include <stdarg.h>
        # include <string.h>
        # include <math.h>
        
        int yylex(void);
        int check[100],int_val[1000],var_type[1000];
        float float_val[1000];
        char char_val[1000];
        int caseD,caseV;
        
        
        
        
    %}
    /* Bison declarations (grammar symbols,operator precedence decl.,attribute data type) */
    %error-verbose

       %union{
      int intVal;
      char* variable;
      char* strVal;
      float floatVal;
      char charVal;
    }
     
     
     %token Begin INTEGER FLOAT CHAR END COLON SEMICOLON ASSIGN COMMA  FORWARD_ARROW SHOW 
     %token BACKWARD_ARROW TAKE PLUS SUB MULT DIV MOD OTB CTB POW SIN COS TAN LOG LOG10 OP CP 
     %token LESS_THAN GREATER_THAN LESS_EQUAL GREATER_EQUAL IF ELSE_IF ELSE EQUAL NOT_EQUAL INC
     %token DEC FOR IN FOR_INC FOR_DEC EVEN_ODD FACTORIAL SUM GCD LCM SWITCH
     %token DEFAULT WHILE OSB CSB
     
     %token<intVal>INT_VAL
     %token<floatVal>FLOAT_VAL
     %token<charVal>CHAR_VAL
     %token<intVal>VARIABLE
     %token<strVal>STRING_VAL

     
     %type<intVal>expression statements cdeclare condition cstatements number
   

    %%

    program:Begin COLON cstatements END   {printf("\n\t\t\t\t\tCompilation Done Succesfully!!!\n");
                                                
                                          
                                          }
           ;
    cstatements:/* Empty */           {}
               |SEMICOLON                       {printf("\n\t\t\t\tEmpty statement\n");}
               |cstatements cdeclare SEMICOLON  
               |cstatements statements
               
               
              
               ;
    cdeclare:FLOAT float_id {}
            
                
            ;
   
    float_id:float_id1 COMMA float_id 
      |float_id1
      ;
    float_id1:VARIABLE      {
                                if(check[$1]==1)
                                 {
                                   printf("\n\t\t\t\tCompilation error-> %c is redeclared \n",$1+97);
                                 }
                                else{
                                var_type[$1]=1;
                                check[$1]=1;
                                printf("\n\t\t\t\t%c is declared successfully\n",$1+97);
                               }
                            }
        |VARIABLE ASSIGN expression {   
                                        if(check[$1]==1)
                                         {
                                           printf("\n\t\t\t\tCompilation error-> %c is redeclared \n",$1+97);
                                         }
                                        else{
                                        var_type[$1]=1;
                                        check[$1]=1;
                                        float_val[$1]=$3;
                                        printf("\n\t\t\t\t%c is declared and assigned by %f successfully\n",$1+97,(float)($3));
                                       }
                                
                               }
        
        ;
        
   
                               
        
        

    statements:SHOW FORWARD_ARROW VARIABLE SEMICOLON       { 
                                                                if(check[$3] == 1) 
                                                                    {
                                                                     if(var_type[$3]==0)
                                                                        printf("\n\t\t\t\tValue of %c is: %d\n",$3+97,int_val[$3]);
                                                                     else if(var_type[$3]==1)
                                                                        printf("\n\t\t\t\tValue of %c is: %f\n",float_val[$3]);   
                                                                     else if(var_type[$3]==2)
                                                                        printf("\n\t\t\t\tValue of %c is: %c\n",char_val[$3]);                                                                        
                                                                    }
                                                                else
                                                                {
                                                                
                                                                    printf("\n\t\t\t\tCompilation error-> %c was not declared\n",$3+97);
                                                                }

                                                            }
            
                                                        
              |VARIABLE ASSIGN expression SEMICOLON         {                                                           
                                                                if(check[$1] == 1)
                                                                {
                                                                    if(var_type[$1]==0)
                                                                        {
                                                                          int_val[$1]=$3;
                                                                          printf("\n\t\t\t\t%c is assigned by %d successfully\n",$3); 
                                                                        }
                                                                     else if(var_type[$1]==1)
                                                                       {
                                                                         float_val[$1]=$3;
                                                                         printf("\n\t\t\t\t%c is assigned by %f successfully\n",(float)($3));
                                                                       }
                                                                      else if(var_type[$1]==2)
                                                                       {
                                                                         float_val[$1]=$3;
                                                                         printf("\n\t\t\t\t%c is assigned by %c successfully\n",$3);
                                                                       }
                                                                }
                                                                else
                                                                {
                                                                  printf("\n\t\tCompilation error-> %c was not declared\n",$1+97);
                                                                }
                                                        }
             
              ;


    expression: number{ $$ = $1;  
                       //printf("%f\n",$1);
                      }
             

    number:INT_VAL {$$=$1;}
          |FLOAT_VAL {$$=$1;
                      //printf("%f\n",$1);
                     }
          |CHAR_VAL  {$$=$1;}
        
          ;
              
    %%


    int yywrap(){
    return 1;
    }
    int yyerror(char *s)
    {
    fprintf(stderr,"%s\n",s);
    }
    int main()
    {
    freopen("input.txt","r",stdin);
    yyparse();
    }

如果我给 m_float a:=12.45.那么输出应该是 12.45.但是程序给了我 12.000000.

解决方法

您已声明

%type<intVal>expression … number

因此,当您从 number 创建 FLOAT_VAL 时,会将其转换为整数。但是您的所有变量都是浮点数,因此您稍后将此整数存储为浮点数。效果真的跟下面没什么区别:

float value = 12.45;
int number = value;
int expr = number;
float a = expr:
printf("a = %f\n",a);

我希望原因很明显 该 C 片段将打印出 a = 12.000000

创建具有多种数据类型的计算器并不容易。您不能使用简单的 C 原始类型来保存可能是各种不同类型之一的内容。你需要某种有区别的联合,这需要做更多的工作

一个常见的解决方案(例如由 JavaScript 使用)是使用 double 作为唯一的数字类型。 (通常,您应该使用 double 而不是 floatfloat 对于许多计算来说不够准确。)double 可以精确地表示任何 32 位整数值,因此使用 double 保存整数不会丢失任何精度。

不过,这对字符串类型的表达式没有帮助。如果你想要多种数据类型,你肯定需要一个可区分的联合类型。

在典型平台上,double 的精度为 53 位,因此您可以使用比 int 能容纳的稍大的整数,但不能大到 long long 能容纳的程度。有时,您确实需要 64 位整数。如果是这样,那么唯一的解决方案是区分联合类型。