GitHub地址:
https://github.com/Sophur/four_arithmetic_operation
- 为了让小学生得到充分锻炼,每个练习题至少要包含2种运算符。同时,由于小学生没有分数与负数的概念,你所出的练习题在运算过程中不得出现负数与非整数,比如不能出 3/5+2=2.6,2-5+10=7等算式。
- 练习题生成好后,将你的学号
- 当程序接收的参数为4时,以下为输出文件示例。
功能设计:
输入数字n,随机生成n个包含至少两个运算符的式子以及相应的结果并输出到指定文件。
设计实现:
设计思路: 本次设计包含一个类Demo,共分为四个模块,分别为随机生成中缀表达式;将生成的中缀表达式转换为后缀表达式;计算后缀表达式的值;将第一个模块中生成中缀表达式以及第三个模块中计算出的相应的值输出到txt文件。
测试运行:
- 控制台输出:
- 文件输出:
- 命令行输出:
核心代码:
计算后缀表达式的值:
从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。
本次设计我先把中缀表达式转换为后缀表达式,再对后缀表达式求值。
//计算后缀表达式 public static int evaluateExpression(String expression) { Stack<Integer> operandStack = new Stack<Integer>();// 存放操作数的栈 Stack<Character> operatorStack = new Stack<Character>();// 存放运算符的栈 // 分割算术表达式 ArrayList<String> result = new ArrayList<String>(); String num = ""; for (int i = 0; i < expression.length(); i++) { if (Character.isDigit(expression.charAt(i))) { num = num + expression.charAt(i); } else { result.add(num); result.add(expression.charAt(i) + ""); num = ""; } } result.add(num); // 测试分割后的算术表达式 // for(String str:result){ // System.out.print(str+" "); // } // 后缀表达式 for (int i = 0; i < result.size(); i++) { if (result.get(i).equals("+") || result.get(i).equals("-")) { // 如果字符串为"+"或者"-",则执行栈中已存数据的加减乘除计算 while (!operatorStack.isEmpty() && (operatorStack.peek() == '+' || operatorStack.peek() == '-' || operatorStack.peek() == '*' || operatorStack.peek() == '/')) { processOneOperator(operandStack, operatorStack); } operatorStack.push(result.get(i).charAt(0));// 将操作符压入操作符栈中 } else if (result.get(i).equals("*") || result.get(i).equals("/")) { // 如果字符串为"*"或者"/",则执行栈中已存数据的乘除计算 while (!operatorStack.isEmpty() && (operatorStack.peek() == '*' || operatorStack.peek() == '/')) { processOneOperator(operandStack, operatorStack); } operatorStack.push(result.get(i).charAt(0)); } else if (result.get(i).equals("(")) { // 如果遇到左括号,则将左括号压入操作符栈中 operatorStack.push('('); } else if (result.get(i).equals(")")) { // 如果遇到右括号,则计算栈中的数据,直到遇到左括号为止 while (operatorStack.peek() != '(') { processOneOperator(operandStack, operatorStack); } operatorStack.pop();// 将进行过计算的左括号弹出 } else { // 如果遇到的是操作数,则将操作数直接压入操作数栈中 operandStack.push(Integer.parseInt(result.get(i))); } } // 对栈中数据进行计算,知道栈为空为止 while (!operatorStack.isEmpty()) { processOneOperator(operandStack, operatorStack); } // 此时操作数栈中的栈顶元素也就是计算结果 return operandStack.pop();
总结:
在看到项目的题目时觉得应该能轻松做出来,毕竟在学习C语言时学过有相关的例子,可以如法炮制。但是真正开始动手做时很艰难,原因有两点:其一,很长时间不使用java语言,基本的语法知识都已模糊,程序的开头定义一个ArrayList数组时都已忘记数组的基本格式,百度后重新学习后再去做已经花了很多时间,整个程序编码的过程基本伴随着不断的查询基本语法。其二:设计的功能过于简单,在后期完善阶段进行了很多次修改。通过这次项目的完成我真正意识到了在软件开发的过程中基础知识匮乏的致命性,几乎整个实现过程我都在处理低级的语法错误。
展示PSP:
PSP2.1 |
任务内容 |
计划完成需要的时间(min) |
实际完成需要的时间(min) |
Planning |
计划 |
20 |
15 |
· Estimate |
· 估计这个任务需要多少时间,并规划大致工作步骤 |
20 |
15 |
Development |
开发 |
600 |
500 |
·· Analysis |
需求分析 (包括学习新技术) |
60 |
60 |
· Design Spec |
· 生成设计文档 |
6 |
10 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
4 |
6 |
· Coding Standard |
代码规范 (为目前的开发制定合适的规范) |
5 |
5 |
· Design |
具体设计 |
10 |
12 |
· Coding |
具体编码 |
500 |
450 |
· Code Review |
· 代码复审 |
15 |
15 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
13 |
30 |
Reporting |
报告 |
15 |
20 |
·· Test Report |
· 测试报告 |
5 |
10 |
· Size Measurement |
计算工作量 |
10 |
13 |
· Postmortem & Process Improvement Plan |
· 事后总结 ,并提出过程改进计划 |
3 |
3 |