一、需求分析(描述自己对需求的理解,以及后续扩展的可能性)
- 实现一个命令行程序,要求:
- 自动生成小学四则运算题目(加,减,乘,除)
- 支持整数
- 支持多运算符(比如生成包含100个运算符的题目)
- 支持真分数
- 统计正确率 - 扩展需求
- 文件:
- 处理生成题目并输出到文件
- 完成题目后从文件读入并判断
- 多语言支持:简体中文
,繁體中文
,English
- 生成题目去重
本周完成进度 :可以进行除括号外的四则运算,可以生成100个运算符的题目,已经完成中缀转后缀以及后缀的计算,但还不能算出真分数。
二、设计思路(同时输出UML类图)
- 首先要输入生成题目的数目m
- 计算机根据输入的数目生成m道题
- 每道题生成的数字要随机且在0~100之间
- 生成的字符也要随机且字符数在1~100之间,字符不止加减乘除,还有括号 - 用户输入值和计算机原本结果进行对比
- 如果正确,则输出正确
- 如果错误,则输出错误,正确答案为:输出答案,还应包括真分数计算 - 答题结束后,计算机自动计算答题正确率
三、实现过程中的关键代码解释
- 计算生成题目,不包括括号运算符
package CaculateSystem;
import java.util.Random;
public class ProduceProblem {
public int ProduceProblem () {
String s = "";
Random shu = new Random();//每个运算式的随机数
int count = 1; //记录符号;
char[] operator = new char[]{'+', '-', '*', '/'};
int m = 2 + (int) (Math.random() * 6); //每个运算式数目的个数
for (int j = 0; j < m; j++) {
int num = shu.nextInt(10);
s = s +" "+ num;
if (count < m) {
int c = shu.nextInt(4);
s = s +" "+ operator[c];
count++;
}
}
String [] str = s.split(" ");
System.out.println(s + "=");
Translate t = new Translate(str);
return t.flag;
}
}
- 将中缀转换为后缀
package CaculateSystem;
import java.util.Stack;
public class Translate extends Judge{
int flag;
public Translate (String[] args) {
Stack<String> z = new Stack<String>();
String jieguo = "";
String t = "";
for (int i = 0; i < args.length; i++) {
switch (args[i]) {
case "(":
z.push(args[i]);
break;
case "+":
case "-":
while(z.empty() != true) {
t = z.pop();
if (t.equals("(")) {
z.push(t);
break;
}
jieguo = jieguo + t + " ";
}
z.push(args[i]);
break;
case "*":
case "/":
while(z.empty() != true) {
t = z.pop();
if (t.equals("+") || t.equals("-") || t.equals("(")) {
z.push(t);
break;
}
jieguo = jieguo + t + " ";
}
z.push(args[i]);
break;
case ")":
while (z.empty()== false) {
t = z.pop();
if (t.equals("(")) {
break;
} else {
jieguo = jieguo + t + " ";
}
}
break;
case" ":
break;
default:
jieguo = jieguo + args[i] + " ";
break;
}
}
while (z.empty() == false) {
jieguo = jieguo + z.pop() + " ";
}
String [] str = jieguo.split(" ");
Count py = new Count(str);
int answer = py.answer;
flag = A(answer);
}
public Translate() {
}
}
- 后缀计算(不包括真分数)
package CaculateSystem;
import java.util.Stack;
public class Count{
int answer;
public Count (String[] args) {
Stack<String> z = new Stack<String>();
int num1,num2,d;
for(int i=0;i<args.length;i++) {
switch (args[i]){
case"+":
num2 = Integer.valueOf(z.pop());
num1 = Integer.valueOf(z.pop());
d = num1+num2;
z.push(String.valueOf(d));
break;
case"-":
num2 = Integer.valueOf(z.pop());
num1 = Integer.valueOf(z.pop());
d = num1-num2;
z.push(String.valueOf(d));
break;
case"*":
num2 = Integer.valueOf(z.pop());
num1 = Integer.valueOf(z.pop());
d = num1*num2;
z.push(String.valueOf(d));
break;
case"/":
num2 = Integer.valueOf(z.pop());
num1 = Integer.valueOf(z.pop());
d = num1/num2;
z.push(String.valueOf(d));
break;
case"":
case" ":
break;
default:
z.push(args[i]);
break;
}
}
while (z.empty() == false) {
answer = Integer.valueOf(z.pop());
}
}
}
四、测试方法
五、运行过程截图
六、代码托管地址
https://gitee.com/wpywbb/20175225zyr
七、遇到的困难及解决方法
1.最开始看题目时觉得挺简单的,不就是四则运算吗,后来才发现要一大堆程序,而对于自己这样的菜鸡,就不知道从哪里开始,无从下手。
解决方法:因为程序太多了,所以我们把程序分为了生成题目、中缀转后缀、后缀计算、比较结果、计算正确率四个部分,然后再对每一个部分进行分析,这样环环相扣,一点一点地解决程序。
2.在生成题目时要求随机生成计算符,对这个陌生的问题一筹莫展。
解决方法:小伙伴提议可以用数字来代替运算符,用03分别代表加减乘除,然后随机生成03的数就先当于随机生成运算符。
3.中缀转后缀是全新的知识,刚开始接触时什么都不懂,看老师的教程也不明白。
解决方法:在网上查找关于相关知识,了解到了关于栈的一些用法:还通过看别人写的程序从而进一步了解中缀转后缀的过程。
栈名.pop()表示将栈顶元素弹出
栈名.push(x)表示将x压入栈中
八、对结对的小伙伴做出评价(重点指出需要改进的地方)
首先我应该进行自我反省,由于学识浅薄,我成了一个拖油瓶,很多都是在小伙伴的帮助下完成的。我的小伙伴很棒,他总是能总领全局,遇见程序首先将它剖析成几个部分,然后再挨个解决,他总是能在我无助的时候帮助我,让我在绝望的时候还能看到希望,和他结对很愉快。
九、总结
本次编程对我来说真的是一次很难忘的经历,最开始接触时真的无从下手,只能干瞪眼,在脑子里一堆浆糊,后来还是在小伙伴带领下将程序划分为几个部分,然后挨个击破,把每个部分要解决的都写出来,所以还是实践出真知,不管怎么想,还是应该多动手,有些东西写着写着可能就出来了,所以应该加强实践能力。选择结对是非常明智的,因为我自己不会的可以找小伙伴讨论,也许小伙伴也不会,那我们就共同解决、共同进步,虽然实验还未完成,但我希望我们能够保持这种状态,完成任务。
十、参考引用
http://www.cnblogs.com/math/p/se-tools-001.html
http://www.cnblogs.com/vertextao/p/6593339.html
http://www.cnblogs.com/Vivian517/p/8762830.html
https://blog.csdn.net/newgrammer/article/details/757522
https://en.wikipedia.org/wiki/Polish_notation