制作一个简单的计算器

摘要: 本文通过制作一个简单的命令行计算器来学习flex/bison编译工具的使用。

1. 目标

  • 支持命令行输入表达式进行计算
  • 支持整数加减乘除四则运算
  • 支持绝对值运算
  • 支持括号运算

2. 使用工具

  • flex
  • bison
  • gcc

3. 源码

3.1 calc.l

%{
#include "calc.tab.h"
extern void yyerror(char* msg, ...);
%}

%%

" + "        { printf("ADD\n");  return ADD; }
" - "        { printf("SUB\n");  return SUB; }
" * "        { printf("MUL\n");  return MUL; }
" / "        { printf("DIV\n");  return DIV; }

"|"          { printf("ABS\n");  return ABS; }
[-+][0-9]+   { yylval = atoi(yytext);  printf("NUMBER %d\n", yylval); return NUMBER; }
[0-9]+       { yylval = atoi(yytext);  printf("NUMBER %d\n", yylval); return NUMBER; }

\n           { printf("EOL\n");  return EOL; }
[ \t]        { printf("SPA\n");              }
"("          { printf("LFT\n"); return LB;   }
")"          { printf("RGT\n"); return RB;   }
.            { yyerror("invalid character: %c!", *yytext); }

%%

3.2 calc.y

%{
#include <stdio.h>
#include "calc.tab.h"

extern int yylex(void);
extern void yyerror(char* msg);
%}

%token NUMBER
%token ADD SUB MUL DIV ABS LB RB
%token EOL

%%

prog:   exp EOL { printf("==> RESULT = %d\n",$1); }
      ;

exp:    exp ADD term { $$ = $1 + $3; printf("==> %d + %d = %d \n", $1, $3, $$); }
      | exp SUB term { $$ = $1 - $3; printf("==> %d - %d = %d \n", $1, $3, $$); }
      | term;

term:   term MUL factor { $$ = $1 * $3; printf("==> %d * %d = %d \n", $1, $3, $$); }
      | term DIV factor { $$ = $1 / $3; printf("==> %d / %d = %d \n", $1, $3, $$); }
      | factor

factor: NUMBER          { $$ = $1; }
      | ABS exp ABS     { $$ = $2 >= 0 ? $2: -$2; }
      | LB exp RB       { $$ = $2; }
      ;

%%

int main(int argc,char **argv)
{
    printf("Please enter a mathematics expression: ");
    yyparse();
	return 0;
}


void yyerror(char *s)
{
    fprintf(stderr,"error: %s\n",s);
}

3.3 makefile

cat makefile
calc : calc.tab.c calc.yy.c
	gcc -o calc calc.tab.c calc.yy.c -lfl

calc.tab.c : calc.y
	bison -d calc.y

calc.yy.c : calc.l
	flex -o calc.yy.c calc.l

4. 测试

命令行输入:./calc

测试用例1:

Please enter a mathematics expression: 1 + 2 * 3 + 4 * | 5 - 78| * 3
NUMBER 1
ADD
NUMBER 2
MUL
NUMBER 3
==> 2 * 3 = 6
ADD
==> 1 + 6 = 7
NUMBER 4
MUL
ABS
SPA
NUMBER 5
SUB
NUMBER 78
ABS
==> 5 - 78 = -73
==> 4 * 73 = 292
MUL
NUMBER 3
==> 292 * 3 = 876
EOL
==> 7 + 876 = 883
==> RESULT = 883

测试用例2:

1 - 2 * 3 / (1 + 2) + (1 - 2 + (|3 - 4| * 3))
NUMBER 1
SUB
NUMBER 2
MUL
NUMBER 3
==> 2 * 3 = 6
DIV
LFT
NUMBER 1
ADD
NUMBER 2
RGT
==> 1 + 2 = 3
==> 6 / 3 = 2
ADD
==> 1 - 2 = -1
LFT
NUMBER 1
SUB
NUMBER 2
ADD
==> 1 - 2 = -1
LFT
ABS
NUMBER 3
SUB
NUMBER 4
ABS
==> 3 - 4 = -1
MUL
NUMBER 3
==> 1 * 3 = 3
RGT
RGT
==> -1 + 3 = 2
EOL
==> -1 + 2 = 1
==> RESULT = 1
  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
package com.softeem.train.calculator; import java.util.Scanner; import java.io.*; public class Calculator { private int m; // 第一个输入的数字 private int n; // 第二个输入的数字 public Calculator() { this.m = 0; this.n = 0; } /* * public void use() { System.out.println("你是否继续使用?继续输入Y,退出输任意键?"); Scanner * in5= new Scanner(System.in); String zz=in5.next(); * if(zz.equals("Y")||zz.equals("y")) this.gui(); else System.exit(0); * * } */ public void graphic() { //3 System.out.println("=========================="); System.out.println("欢迎使用 So easy 计算机简易系统 "); System.out.println(" 请选择计算类型:"); System.out.println(" 1.加法"); System.out.println(" 2.减法"); System.out.println(" 3.乘法"); System.out.println(" 4.除法"); System.out.println(" 5.输入表达式计算"); System.out.println(" 6.退出"); System.out.println("=========================="); Scanner in3 = new Scanner(System.in); int n = in3.nextInt(); switch (n) { //4 case 1: this.add(); //8 break; case 2: this.sub(); break; case 3: this.mul(); break; case 4: this.div(); break; case 5: this.cal(); break; case 6: System.exit(0); default: break; } } public void add() // 实现加法的方法 { //5 System.out.println("欢迎使用加法操作"); this.in(); //7 int sum; sum = this.m + this.n; System.out.println("你输入的数据的和是:" + sum); // this.use(); } public void sub() // 实现减法的方法 { System.out.println("欢迎使用减法操作"); this.in(); int cha; cha = this.m - this.n; System.out.println("你输入的数据的差是:" + cha); // this.use(); } public void mul() // 实现乘法的方法 { System.out.println("欢迎使用乘法操作"); this.in(); int ji; ji = this.m * this.n; System.out.println("你输入的数据的积是:" + ji); // this.use(); } public void div() // 实现除法的方法 { System.out.println("欢迎使用除法操作"); this.in(); if (n == 0) { System.out.println("被除数不能为零!"); this.graphic(); } int shang; shang = this.m / this.n; System.out.println("你输入的数据的和是:" + shang); // this.use(); } public void cal() // 实现表达式运算方法 { String s = ""; // 接收表达式的字符串 String ss1 = ""; // 分离数字m的字符串 String ss2 = ""; // 分离数字n的字符串 char c1 = ' '; // 存放运算符 int m = 0; // 第一个数字 int n = 0; // 第二个数字 System.out.print("请输入一个表达式:"); try { BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); s = in.readLine(); } catch (IOException e) { } for (int i = 0; i < s.length(); i++) { if ((s.charAt(i) == '+') || (s.charAt(i) == '-') || (s.charAt(i) == '*') || (s.charAt(i) == '/')) { c1 = s.charAt(i); // 第一个数 for (int j = 0; j < i; j++) { ss1 += s.charAt(j); m = Integer.parseInt(ss1); } // 第二个数 for (int j = i + 1; j < s.length(); j++) { ss2 += s.charAt(j); n = Integer.parseInt(ss2); } break; } } if (c1 == '+') System.out.println(m + "+" + n + "=" + (m + n)); if (c1 == '-') System.out.println(m + "-" + n + "=" + (m - n)); if (c1 == '*') System.out.println(m + "*" + n + "=" + (m * n)); if (c1 == '/') System.out.println(m + "/" + n + "=" + (m / n)); } public void in() // 实现接收数据的方法 { //6 System.out.println("请输入第一个数:"); Scanner in1 = new Scanner(System.in); this.m = in1.nextInt(); System.out.println("请输入第二个数:"); Scanner in2 = new Scanner(System.in); this.n = in2.nextInt(); } public static void main(String[] args) throws java.io.IOException { //1 String ifquit = ""; // 用于接收是否退出 Calculator c = new Calculator(); do { //2 c.graphic(); // 调用界面方法 //9 System.out.println("你是否继续使用?继续输入Y,退出输任意键?"); Scanner in5 = new Scanner(System.in); ifquit = in5.nextLine(); //10 } while (ifquit.equals("Y") || ifquit.equals("y")); } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农心语

您的鼓励是我写作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值