20172312『Java程序设计』课程 结对编程练习_四则运算第二周阶段总结
20172312『Java程序设计』课程 结对编程练习_四则运算第二周阶段总结
结对伙伴
-
学号 :20172315 20172318
-
姓名 :胡智韬 陆大岳
- 伙伴第一周博客地址:
-
对结对伙伴的评价:这俩人一开始各编各的还好,到后面就开始吵,从头吵到尾,陆大胖,胡志汪,还好到最后是把代码敲出来了,不容易不容易。
小组结对编程的照片(QQ群截图)
项目中自己负责的部分
代码的综合整理,错误查找,合并以及博客的撰写。
个人贡献度划分
彭霖:胡智韬:陆大岳=3:3:4
相关过程的截图
-
生成题目类驱动类的部分截图
-
最后运行结果截图
关键代码解释
1.运行分数计算的分数计算类
import chap4.RationalNumber;
import java.util.Stack;
import java.util.regex.Pattern;/**
* 将中缀表达式字符串转换为后缀表达式
*/
public class StringToArithmetic {
// 默认构造
public StringToArithmetic() {}
// 将中缀表达式字符串计算得到结果
public static double stringToArithmetic(String string) {
return suffixToArithmetic(infixToSuffix(string));
}// 将中缀表达式转换为后缀表达式
public static String infixToSuffix(String exp) {
// 创建操作符堆栈
Stack<Character> s = new Stack<Character>();
// 要输出的后缀表达式字符串
String suffix = "";
int length = exp.length(); // 输入的中缀表达式的长度
for (int i = 0; i < length; i++) {
char temp;// 临时字符变量
// 获取该中缀表达式的每一个字符并进行判断
char ch = exp.charAt(i);
switch (ch) {
// 忽略空格
case ' ':
break;
// 如果是左括号直接压入堆栈
case '(':
s.push(ch);
break;// 碰到'+' '-',将栈中的所有运算符全部弹出去,直至碰到左括号为止,输出到队列中去
case '+':
case '-':
while (s.size() != 0) {
temp = s.pop();
if (temp == '(') {
// 重新将左括号放回堆栈,终止循环
s.push('(');
break;
}
suffix += temp;
}
// 没有进入循环说明是当前为第一次进入或者其他前面运算都有括号等情况导致栈已经为空,此时需要将符号进栈
s.push(ch);
break;// 如果是乘号或者除号,则弹出所有序列,直到碰到加好、减号、左括号为止,最后将该操作符压入堆栈
case '×':
case '/':
case '÷':
while (s.size() != 0) {
temp = s.pop();
// 只有比当前优先级高的或者相等的才会弹出到输出队列,遇到加减左括号,直接停止当前循环
if (temp == '+' || temp == '-' || temp == '(') {
s.push(temp);
break;
} else {
suffix += temp;
}
}// 没有进入循环说明是当前为第一次进入或者其他前面运算都有括号等情况导致栈已经为空,此时需要将符号进栈
s.push(ch);
break;// 如果碰到的是右括号,则距离栈顶的第一个左括号上面的所有运算符弹出栈并抛弃左括号
case ')':
// 这里假设一定会遇到左括号了,此为自己改进版,已经验证可以过
// while ((temp = s.pop()) != '(') {
// suffix += temp;
// }
while (!s.isEmpty()) {
temp = s.pop();
if (temp == '(') {
break;
} else {
suffix += temp;
}
}
break;
// 默认情况,如果读取到的是数字,则直接送至输出序列
default:
suffix += ch;
break;
}}
while (s.size() != 0) {
suffix += s.pop();
}
//
return suffix;
}public static double suffixToArithmetic(String exp) {
String[] strings = exp.split("");
Stack<Double> stack = new Stack<Double>();
for (int i = 0; i < strings.length; i++) {
Pattern pattern = Pattern.compile("\\d+||(\\d+\\.\\d+)");
// 这里最好是进行判断彻底消除空格,在该数组的第一位为一个隐形的空格,这里一定要注意在使用exp.split("")剔除空白""
// 由于使用的是""截取导致在数组第一位上面的值为空白
if (strings[i].equals("")) {
continue;
}
// 如果遇到了数字则直接进栈
if (pattern.matcher(strings[i]).matches()) {
stack.push(Double.parseDouble(strings[i]));
}
// 如果是运算符,则弹出栈顶的两个数进行计算
else {
// !!!这里需要注意,先弹出的那个数其实是第二个计算数值,这里记作y!
// 自己书写的时候出错
double y = stack.pop();
double x = stack.pop();
// 将运算结果重新压栈
stack.push(calculate(x, y, strings[i]));
}
}
// 弹出栈顶元素就是最终结果
return stack.pop();
}
private static Double calculate(double x, double y, String string) {
// TODO Auto-generated method stub
// 其实使用case逻辑也可以
if (string.trim().equals("+")) {
return x + y;
}
if (string.trim().equals("-")) {
return x - y;
}
if (string.trim().equals("×")) {
return x * y;
}
if (string.trim().equals("÷")) {
return x / y;
}
if (string.trim().equals("/")){
return x / y;
}
return (double) 0;
}
}
2.在计算后缀表达式的类StringToArithmetic
- import java.util.Stack;
import java.util.regex.Pattern;
public class StringToArithmetic {
public StringToArithmetic() {
}
// 将中缀表达式字符串计算得到结果
public static double stringToArithmetic(String string) {
return suffixToArithmetic(infixToSuffix(string));
}
// 将中缀表达式转换为后缀表达式
public static String infixToSuffix(String exp) {
Stack<Character> s = new Stack<Character>();
String suffix = "";
int length = exp.length(); // 输入的中缀表达式的长度
for (int i = 0; i < length; i++) {
char temp;
char ch = exp.charAt(i);
switch (ch) {
case ' ':
break;
case '(':
s.push(ch);
break;
case '+':
case '-':
while (s.size() != 0) {
temp = s.pop();
if (temp == '(') {
s.push('(');
break;
}
suffix += temp;
}
s.push(ch);
break;
case '×':
case '÷':
while (s.size() != 0) {
temp = s.pop();
if (temp == '+' || temp == '-' || temp == '(') {
s.push(temp);
break;
} else {
suffix += temp;
}
}
s.push(ch);
break;
case ')':
//加减乘除以及括号(去除无意义括号较难没有处理)
while (!s.isEmpty()) {
temp = s.pop();
if (temp == '(') {
break;
} else {
suffix += temp;
}
}
break;
default:
suffix += ch;
break;
}
}
while (s.size() != 0) {
suffix += s.pop();
}
return suffix;
}
// 将后缀表达式的进行计算得到运算结果
public static double suffixToArithmetic(String exp) {
Pattern pattern = Pattern.compile("\\d+||(\\d+\\.\\d+)");
String[] strings = exp.split("");
Stack<Double> stack = new Stack<Double>();
for (int i = 0; i < strings.length; i++) {
if (strings[i].equals("")) {
continue;
}
if (pattern.matcher(strings[i]).matches()) {
stack.push(Double.parseDouble(strings[i]));
}
else {
double y = stack.pop();
double x = stack.pop();
stack.push(calculate(x, y, strings[i]));
}
}
return stack.pop();
}
private static Double calculate(double x, double y, String string) {
if (string.trim().equals("+")) {
return x + y;
}
if (string.trim().equals("-")) {
return x - y;
}
if (string.trim().equals("×")) {
return x * y;
}
if (string.trim().equals("÷")) {
return x / y;
}
return (double) 0;
}
}
遇到的困难及解决办法
-
问题一:这俩人一直在吵,从头吵到尾,尤其分数的时候,胡智韬表示不想有分数与整数混合运算,不然太过困难,而陆大岳则表示整数与分数混合运用,我个人同意胡智韬同学的意见,整数分数混合的题目生成过于复杂,工作量过大,最关键的是后缀表达式的分数计算。
-
问题一解决方法:最后是将分数作为除法算了,同归于尽吧!
-
问题二: 最后运行的时候出现了无限循环的情况,当时忘记了截图,大概就是:
-
生成4道题目:1+1+2=;1+1+1=;1-1-1=;1+2+3=;1-2+3=;......?!等下怎么无限循环了!
-
问题二解决方案:后来发现是代码中case后面忘记加入break。
码云项目链接