实现一个命令行程序,要求:git
从题目要求可知,咱们须要实现如下几个功能:express
现阶段已实现要求二、3,要求4虽已初步实现但仍存在一些问题,咱们将会在下一阶段中实现全部项目要求的功能,并可拓展如下功能:编程
根据需求,考虑程序须要定义方法来实现中缀表达式转后缀表达式、后缀式计算的功能,将结果转换为分数以及须要定义调用以上三种种方法并进行输入输出的主类,因而我将前两种方法放入MyDC的类中,真数的支持放入Rational类中,主类设置为MyDCTester。数组
运用老师在博客中提供的法则:post
public String trans(String before){ int i,j=0; char step[] = before.toCharArray();//将中缀式字符串转化为字符数组 char after[] = new char[step.length];//用于接收转化后的后缀式表达式 for(i=0;i<step.length;i++) { if (step[i] >= '0' && step[i] <= '9') {//遇到数字 after[j] = step[i]; j++; if(i==(step.length)-1){//读到了输入的末尾 while(stacktwo.empty()==false) { after[j]=stacktwo.pop(); j++; } } } else if(stacktwo.empty()||step[i]=='('||stacktwo.peek()=='('||stacktwo.peek()==')') {//遇到非数字且栈为空或者该符号为左括号或者栈顶元素为括号 stacktwo.push(new Character(step[i])); if(i==(step.length)-1){ while(stacktwo.empty()==false) { after[j]=stacktwo.pop(); j++; } } } else if(step[i]==')') {//遇到一个右括号 while (stacktwo.peek() != '(') { after[j] = stacktwo.pop(); j++; } stacktwo.pop(); if(i==(step.length)-1){ while(stacktwo.empty()==false) { after[j]=stacktwo.pop(); j++; } } } else {//遇到运算符号且栈非空 switch (step[i]) { case ADD: case SUBTRACT: { while(stacktwo.peek()=='*'||stacktwo.peek()=='/'||stacktwo.peek()=='+'||stacktwo.peek()=='-'){ after[j]=stacktwo.pop(); j++; if(stacktwo.empty()){ break; } } stacktwo.push(step[i]); break; } case MULTIPLY: case DIVIDE: { while(stacktwo.peek()=='*'||stacktwo.peek()=='/'){ after[j]=stacktwo.pop(); j++; if(stacktwo.empty()){ break; } } stacktwo.push(step[i]); break; } } if(i==(step.length)-1){ while(stacktwo.empty()!=false) { after[j]=stacktwo.pop(); j++; } } } } String str = new String(after); return str;//将字符数组转化为字符串后返回 }
老师给的连接中已经明确给出了计算的方法,方法以下:学习
public int evaluate(String expr) {//计算后缀式的值 int op1, op2, result = 0,i; char token[]=expr.toCharArray();//将后缀式字符串转化为字符数组 for(i=0;i<token.length;i++){ if (token[i]=='+' || token[i]=='-' || token[i]=='*' || token[i]=='/') {//对每一个字符进行分析,若是是运算符就取出栈顶开始的两个数 op2 = stack.pop(); op1 = stack.pop(); result = evalSingleOp(token[i], op1, op2);//将栈中取出的两个数进行运算 stack.push(new Integer(result));//将结果压栈 } else//为数字时直接进栈 stack.push(new Integer((int)(token[i]-'0'))); } return result;//返回计算结果 } private int evalSingleOp(char operation, int op1, int op2) {//对栈中取出的两个数进行四则运算,operation为后缀式中的运算符号 int result = 0; switch (operation) { case ADD: result = op1 + op2; break; case SUBTRACT: result = op1 - op2; break; case MULTIPLY: result = op1 * op2; break; case DIVIDE: result = op1 / op2; } return result;//返回运算结果 }
咱们经过学习教材上第100页的例子22封装了有理数类Rational,实现了对真分数的支持。
代码以下:测试
public class Rational { int numerator = 1;//分子 int denominator = 1;//分母 void setNumerator(int a) {//设置分子 int c = f(Math.abs(a), denominator);//计算最大公约数 numerator = a / c; denominator = denominator / c; if (numerator < 0 && denominator < 0) { numerator = -numerator; denominator = -denominator; } } void setDenominator(int b) {//设置分母 int c = f(numerator, Math.abs(b));//计算最大公约数 numerator = numerator / c; denominator = b / c; if (numerator < 0 && denominator < 0) { numerator = -numerator; denominator = -denominator; } else if (numerator > 0 && denominator < 0) { numerator = -numerator; denominator = -denominator; } } int getNumerator() { return numerator; } int getDenominator() { return denominator; } int f(int a, int b) {//求a,b的最大公约数 if (a == 0) { return 1;//c为分母不能为0 } if (a < b) {//令a>b int c = a; a = b; b = c; } int r = a % b; while (r != 0) { a = b; b = r; r = a % b; } return b; } Rational add(Rational r) {//加法运算 int a = r.getNumerator();//返回有理数r的分子 int b = r.getDenominator();//返回有理数r的分母 int newNumerator = numerator * b + denominator * a;//计算出新分子 int newDenominator = denominator * b;//计算出新分母 Rational result = new Rational(); result.setNumerator(newNumerator); result.setDenominator(newDenominator); return result; } Rational sub(Rational r) {//减法运算 int a = r.getNumerator(); int b = r.getDenominator(); int newNumerator = numerator * b - denominator * a; int newDenominator = denominator * b; Rational result = new Rational(); result.setNumerator(newNumerator); result.setDenominator(newDenominator); return result; } Rational muti(Rational r) {//乘法运算 int a = r.getNumerator(); int b = r.getDenominator(); int newNumerator = numerator * a; int newDenominator = denominator * b; Rational result = new Rational(); result.setNumerator(newNumerator); result.setDenominator(newDenominator); return result; } Rational div(Rational r) {//除法运算 int a = r.getNumerator(); int b = r.getDenominator(); Rational result = new Rational(); if (a == 0) { System.out.println("分母不能为0"); result.setNumerator(0); System.exit(0); } else { int newNumerator = numerator * b; int newDenominator = denominator * a; result.setNumerator(newNumerator); result.setDenominator(newDenominator); } return result; } }
现阶段为减小程序调试的难度,咱们使用了老师在博客中提供的代码,但老师提供的代码没法实现随机生成题目、支持真分数以及统计正确率的功能,因而咱们作出了修改,使得程序能够支持分数输出,在接下来的编程中咱们会根据需求对这部分代码进行从新编写。编码
public class MyDCTester { public static void main(String[] args) { String expression, again; Rational result=new Rational(); try { Scanner in = new Scanner(System.in); do { MyDC evaluator = new MyDC(); System.out.println("Enter a valid postfix expression: "); expression = in.nextLine();//输入运算表达式 result = evaluator.evaluate(evaluator.trans(expression));//调用trans方法以及evaluate方法进行转化以及输出计算结果 System.out.println(); int a=result.getNumerator(); int b=result.getDenominator(); if (b==1){//分数转换 System.out.println("result="+a); } else{ System.out.println("result="+a+"/"+b); } System.out.print("Evaluate another expression [Y/N]? ");//询问用户是否再次计算 again = in.nextLine(); System.out.println(); } while (again.equalsIgnoreCase("y")); } catch (Exception IOException) { System.out.println("Input exception reported"); }
我已在设计思路部分给出了设计思路并对关键代码进行了注释。lua
码云连接命令行
到目前为止的困难主要在于实现中缀表达式转化为后缀表达式以及分数的转化,我将一些细节的问题写在了下面。
-Xlint:deprecation
命令进行编译,找到问题并修改。个人结对搭档是江野,在合做的过程当中我是牵头人,他也积极响应个人号召,在编程过程当中咱们互相学习,在遇到困难时一块儿讨论解决办法。但愿能在之后的任务中继续合做,也但愿搭档能更加积极地参与到项目中。
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
· Estimate | · 估计这个任务须要多少时间 | 15 | 30 |
Development | 开发 | ||
· Analysis | · 需求分析 (包括学习新技术) | 25 | 35 |
· Design Spec | · 生成设计文档 | 30 | 30 |
· Design Review | · 设计复审 (和同事审核设计文档) | 20 | 30 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 35 | 45 |
· Design | · 具体设计 | 60 | 80 |
· Coding | · 具体编码 | 150 | 200 |
· Code Review | · 代码复审 | 30 | 35 |
· Test | · 测试(自我测试,修改代码,提交修改) | 20 | 35 |
Reporting | 报告 | 60 | 80 |
· Size Measurement | · 计算工做量 | 10 | 20 |
· Postmortem & Process Improvement Plan | · 过后总结, 并提出过程改进计划 | 20 | 20 |
合计 | 475 | 640 |