211606379王熙航 211606342 杨艺勇
MathExam V2.0
一、预估与实际
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 900 | 1010 |
• Estimate | • 估计这个任务需要多少时间 | 20 | 20 |
Development | 开发 | 300 | 300 |
• Analysis | • 需求分析 (包括学习新技术) | 60 | 60 |
• Design Spec | • 生成设计文档 | 30 | 30 |
• Design Review | • 设计复审 | 10 | 10 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
• Design | • 具体设计 | 120 | 180 |
• Coding | • 具体编码 | 60 | 60 |
• Code Review | • 代码复审 | 30 | 20 |
• Test | • 测试(自我测试,修改代码,提交修改) | 120 | 180 |
Reporting | 报告 | 30 | 30 |
• Test Repor | • 测试报告 | 30 | 30 |
• Size Measurement | • 计算工作量 | 40 | 40 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 40 | 40 |
合计 900 | 1010 |
二、需求分析
我通过客户提出需求的方式了解到,小学三年级数学有如下的几个特点:
- 特点1
- 运算符在2~4个
可以加括号
结果不能有负数
除数不能为0,不能有余数
三、设计
1. 设计思路
- 这个程序的关键就是能判断符号运算的优先级,并能判断括号的位置和括号起的限制作用
- 随机产生的括号如果加在优先级高的运算符上就没有意义,需要单独列出
2. 实现方案
- 先将其分成几种情况
1.运算符的个数可能是2,3,4个。分成3种情况分类随机生成符号以及数字并将其存入字符串中
2.运算结果利用逆波兰算法求结果
四、编码
1. 调试日志
- 一开始用循环随机来随机决定括号的位置,但是括号有时候会到算式的外面,后来是用来随机的数大了一位,导致括号外出
2. 关键代码
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
sc.close();
StringBuilder sb = new StringBuilder(); //结果
Stack<Character> opStack = new Stack(); //运算符栈
Map<Character,Integer> opMap = new HashMap(); //运算符优先级
opMap.put('(', 0);
opMap.put('+', 1);
opMap.put('-', 1);
opMap.put('*', 2);
opMap.put('/', 2);
//处理字符串
for(int i=0;i<input.length();i++){
if(input.charAt(i) == '('){ //如果是'('直接压栈
opStack.push('(');
}else if(isOperator(input.charAt(i))){ //如果是运算符
char curOp = input.charAt(i);
if(opStack.isEmpty()) //如果运算符栈是空,就直接压栈
opStack.push(curOp);
else if(opMap.get(curOp) > opMap.get(opStack.peek())) //运算符栈不为空,且当当前运算符的优先级比站内第一个运算符的优先级高的时候,压栈
opStack.push(curOp);
else{ //栈不为空,且运算符的优先级小于等于栈顶元素
for(int j = 0;j<=opStack.size();j++){
char ch = opStack.pop(); //弹出栈内第一个元素
sb.append(ch + " ");
if(opStack.isEmpty()){
opStack.push(curOp);
break;
}else if(opMap.get(curOp) > opMap.get(opStack.peek())){
opStack.push(curOp);
break;
}
}
}
}else if(input.charAt(i) == ')'){ //如果是')'就把站内'('上的元素都弹出栈
for(int j = 0;j<opStack.size();j++){
char c = opStack.pop();
if(c == '(')
break;
else
sb.append(c + " ");
}
}else{ //如果是数字就直接添加
sb.append(input.charAt(i)+" ");
}
}
//把栈内剩余的运算符都弹出站
for(int i = 0;i<=opStack.size();i++){
sb.append(opStack.pop() + " ");
}
System.out.println(sb);
}
private static boolean isOperator(char charAt) {
// TODO Auto-generated method stub
if(charAt == '+'||charAt=='-'||charAt=='*'||charAt=='/')
return true;
return false;
}
逆波兰算法,计算算式的值
3. 代码规范
- 代码中的命名均不能以下划线或美元符号开始,也不能一下划线或美元符号结束。
- 代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
- 方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵循驼峰形式。
- 常量命名全部大写,单词键用下划线隔开,力求语义表达完整,不要嫌名字长。
- 类型与中括号紧挨相连来定义数组。
- POJO类中布尔类型的标量,都不要加is前缀,否则部分框架解析会引起序列化错误。
- 包名统一是用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如有复数含义,类名可以使用复数形式。其实很多团队都会用公司官方网址的倒写作为包名。这些都是可以主观规定的。
- 杜绝完全不规范的缩写,避免忘文不知义。
五、测试
并人工检查代码是否符合规范
五、测试
只输入一个参数100 结果 错误
输入-n 10 -grade 1 结果正确
输入1000 -n -grade 2 结果 输入格式错误
输入-grade 3 -c 10 结果输入格式错误
输入-n 10 -grade 002 结果正确
六、总结
很多东西都还不会,写出的代码无法运行,不能熟练使用git,需要多加学习和练习。