第二次作业——MathExamLv2
MathExamLv2——林志松 211406285 李明康 211606314
一、预估与实际
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
• Estimate | • 估计这个任务需要多少时间 | 20 | 30 |
Development | 开发 | ||
• Analysis | • 需求分析 (包括学习新技术) | 60 | 240 |
• Design Spec | • 生成设计文档 | 20 | 40 |
• Design Review | • 设计复审 | 5 | 5 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
• Design | • 具体设计 | 20 | 40 |
• Coding | • 具体编码 | 120 | 780 |
• Code Review | • 代码复审 | 30 | 20 |
• Test | • 测试(自我测试,修改代码,提交修改) | 60 | 300 |
Reporting | 报告 | ||
• Test Repor | • 测试报告 | 60 | 70 |
• Size Measurement | • 计算工作量 | 5 | 5 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 10 | 10 |
合计 | 420 | 1590 |
二、需求分析
我通过作业要求的方式了解到,小学三年级数学有如下的几个特点:
特点1
- 运算符在2~4个
特点2
- 可以加括号
特点3
- 减法运算的结果不能有负数
特点4
- 除法运算除数不能为0,不能有余数
经过分析,我认为,这个程序应当:
在作业一的基础上新增带括号的四则运算。
通过调度场和逆波澜算法来实现运算。
三、设计
1. 设计思路
程序有一个类,十二个方法:
private static void transferToPostfix(LinkedList《string》 list) //中缀表达式转为后缀表达式
private static void calculate() //根据后缀表达式计算结果
private static boolean isOperator(String oper) //判断是否操作符
private static int priority(String s) //计算操作符的优先级
private static int cal(int num1,int num2,String operator) //进行计算
private static void gradeOne(int n) //一年级的题目
private static void gradeTwo(int n) //二年级的题目
private static void gradeThree(int n) //三年级的题目
private static BufferedReader in() //输入方法
private static void out(String str) //输出方法
private static void wrongJudgement(String[] args, int n, int grade) //除错处理
public static void main(String[] args) //传说中的main函数~~~~
算法的关键:
调度场算法。
逆波澜算法。
以上算法参考来自于This link
另外附上 calculate()方法的程序流程图:
2. 实现方案
准备工作:先在Github上创建仓库,克隆到本地。
技术关键点:
如何令用户在输入 -n n -grade grade 和 -grade grade -n n 的时候都可以成功运行。
如何在四则运算中添加括号。
如何实现调度场算法
如何实现逆波澜算法
1. 调试日志
添加括号时括号是否存在与四则运算本身毫无影响,后续通过if来判定只有同时出现“-+”和“*/”括号才满足条件出现。
括号的添加位置产生错误,出现类似 100 ( + 200 ) * 300的错误四则运算,后续通过indexOf的方法来查找 “+-”的位置然后向左和向左查询空格的下标来添加括号。
调度场算法的判断运算符优先级时理解错误,但是运算符栈的输入错误,后续通过修改transferToPostfix(LinkedList《string》 list)中的if来修正。
逆波澜算法的多次运算问题,用于保存答案的String sum[i]数组和保存四则运算的StringBuilder sb 字符串没有置空导致答案出现混乱。
2. 关键代码
private static void transferToPostfix(LinkedList<String> list){
Iterator<String> it=list.iterator();
while (it.hasNext()) {
String s = it.next();
if (isOperator(s)) {
if (operators.isEmpty()) {
operators.push(s);
}
else {
//如果读入的操作符为非")"且优先级比栈顶元素的优先级高,则将操作符压入栈
if (priority(operators.peek())<priority(s)&&!s.equals(")")) {
operators.push(s);
}
//否则执行讲栈顶元素弹出后再将操作符入栈
else if(!s.equals(")")&&priority(operators.peek())>=priority(s)){
while (operators.size()!=0&&priority(operators.peek())>=priority(s)
&&!operators.peek().equals("(")) {
if (!operators.peek().equals("(")) {
String operator=operators.pop();
sb.append(operator).append(" ");
output.push(operator);
}
}
operators.push(s);
}
//如果读入的操作符是")",则弹出从栈顶开始第一个"("及其之前的所有操作符
else if (s.equals(")")) {
while (!operators.peek().equals("(")) {
String operator=operators.pop();
sb.append(operator).append(" ");
output.push(operator);
}
//弹出"("
operators.pop();
}
}
}
//读入的为非操作符
else {
sb.append(s).append(" ");
output.push(s);
}
}
//将字符链接成后缀表达式
if (!operators.isEmpty()) {
Iterator<String> iterator=operators.iterator();
while (iterator.hasNext()) {
String operator=iterator.next();
sb.append(operator).append(" ");
output.push(operator);
iterator.remove();
}
}
calculate();
//Collections.reverse(output);
}
private static void calculate(){
LinkedList<String> mList=new LinkedList<>();
String[] postStr=sb.toString().split(" ");
//逐个对字符进行判断
for (String s:postStr) {
if (isOperator(s)){
if (!mList.isEmpty()){
int num1=Integer.valueOf(mList.pop());
int num2=Integer.valueOf(mList.pop());
//如果除数等于0,则抛弃这道题
if (s.equals("/") && num1==0){
answer="wrong";
sb.setLength(0);
return;
}
//如果相除后有余数,则抛弃这道题
if (s.equals("/")&& (num2%num1!=0)){
answer="wrong";
sb.setLength(0);
return;
}
//如果相减后为负数,则抛弃这道题
if (s.equals("-")&& num2<=num1){
answer="wrong";
sb.setLength(0);
return;
}
int newNum=cal(num2,num1,s);
mList.push(String.valueOf(newNum));
}
}
else {
//数字则压入栈中
mList.push(s);
}
}
if (!mList.isEmpty()){
answer=mList.pop();
}
sb.setLength(0);
}
3. 代码规范
请给出本次实验使用的代码规范:
- 第一条:驼峰式命名风格
- 第二条:不允许任何魔法值(即未经预先定义的常量)直接出现在代码中。
- 第三条:大括号的使用约定。如果是大括号内为空,则简介地写成{}即可,不需要换行;如果是非空代码块则:左大括号前不换行。左大括号后换行。右大括号前换行。右大括号后还有 else 等代码则不换行;表示终止的右大括号后必须换行。
- 第四条:单行字符数限制不超过120个
- 第五条:没有必要增加若干空格来是耨一行的字符与上一行对应位置的字符对齐。
- 第六条:在一个switch块内,每一个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且放在最后,即使空代码。
- 第七条:在 if/else/for/while/do 语句中必须使用大括号。
- 第八条:避免采用取反逻辑运算符。
五、测试
输入测试 | 预期结果 | 实际结果 |
---|---|---|
java MathExamLv2 -n 100 -grade 1 | 成功执行 | 成功执行 |
java MathExamLv2 -n 100 -grade 2 | 成功执行 | 成功执行 |
java MathExamLv2 -n 100 -grade 3 | 成功执行 | 成功执行 |
java MathExamLv2 -grade 1 -n 100 | 成功执行 | 成功执行 |
java MathExamLv2 -grade 2 -n 100 | 成功执行 | 成功执行 |
java MathExamLv2 -grade 3 -n 100 | 成功执行 | 成功执行 |
java MathExamLv2 -n 100 | 请按照 -n n -grade grade 或者 -grade grade -n n的方式输入4个参数! | 请按照 -n n -grade grade 或者 -grade grade -n n的方式输入4个参数! |
java MathExamLv2 -grade 100 | 请按照 -n n -grade grade 或者 -grade grade -n n的方式输入4个参数! | 请按照 -n n -grade grade 或者 -grade grade -n n的方式输入4个参数! |
java MathExamLv2 -grade 3 -n 1000000000000000000 | 输入的题目数量太多了! | 输入的题目数量太多了! |
java MathExamLv2 -grade 4 -n 100 | grade只能取1~3! | grade只能取1~3! |
六、总结
通过这一段时间的结对编程,我发现编程耗时最多的方面就是debug。在我得出设计思路,写成代码之后,由于个人的疏忽,输入的错误,以及设计思路的偏差,往往会让我的程序陷入无止尽的BUG海洋中,有些只是很简单的小BUG,但是自己却难以发现,导致消耗我大量的时间。但是由于身边有个领航员角色的存在,在编写代码时,一旦出现输入错误,就会有人及时的提醒。并且,在设计代码时,有个同伴可以一起讨论,融合两个人不同的见解和观点,我们可以得出简单高效的设计书思路。
而且结对编程可以很大程度上提高编程效率,而且两人轮流编程,不会太过疲惫。我现在十分乐于进行结对编程,这回极大的提高我编程的效率,是编程不再那么枯燥,debug之路也不会那么恐怖。
第二次作业——MathExamLv2的更多相关文章
- 耿丹CS16-2班第二次作业汇总
-- Deadline: 2016-09-28 12:00 -- 作业内容:http://www.cnblogs.com/huangjunlian/p/5891726.html -- 第二次作业总结: ...
- JAVA第二次作业展示与学习心得
JAVA第二次作业展示与学习心得 在这一次作业中,我学习了复选框,密码框两种新的组件,并通过一个邮箱登录界面将两种组件运用了起来.具体的使用方法和其他得组件并没有什么大的不同. 另外我通过查阅资料使用 ...
- 20169212《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...
- 软件工程(QLGY2015)第二次作业点评(随机挑选20组点评)
相关博文目录: 第一次作业点评 第二次作业点评 第三次作业点评 说明:随机挑选20组点评,大家可以看看blog名字,github项目名字,看看那种是更好的,可以学习,每个小组都会反应出一些问题,希望能 ...
- 程序设计第二次作业<1>
面向对象程序设计第二次作业<1> Github 链接:https://github.com/Wasdns/object-oriented 题目: <1>第一次尝试 我立马认识到 ...
- homework-02,第二次作业——寻找矩阵最大子序列和
经过漫漫漫~~~~~~~~~~~~~~长的编译和调试,第二次作业终于告一段落了 先放出源码,思路后面慢慢道来 #include<stdio.h> #include<stdlib.h& ...
- 20169210《Linux内核原理与分析》第二周作业
<Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...
- SQL 第二章 作业
/*第二章 作业*/ create table S ( sno char(2) NOT NULL UNIQUE, sname char(3), city char(2) ); alter table ...
- 软件工程(GZSD2015)第二次作业小结
第二次作业,从4月7号开始,陆续开始提交作业.根据同学们提交的作业报告,相比第一次作业,已经有了巨大改变,大家开始有了完整的实践,对那些抽象的名词也开始有了直观的感受,这很好.然后有一些普遍存在的问题 ...
随机推荐
- Java的IO流各个类的使用原则
参考:http://blog.csdn.net/ilibaba/article/details/3955799 Java IO 的一般使用原则(花多眼乱,其实每个类都有专门的作用): 这里有详细介绍: ...
- 【STL】count_if
功能 返回满足条件的元素个数 模版 template <class InputIterator, class Predicate> typename iterator_traits< ...
- npm update常用命令使用
一.更新 npm-check检查更新 npm install -g npm-check npm-check 2. npm-upgrade更新 npm install -g npm-upgrade np ...
- Messenger和MVVM中的View Services
在前面的文章IoC容器和MVVM中, 介绍了IoC容器如何在大量用户类中帮助创建和分配用户类的实例.本文将介绍IoC容器如何帮助应用程序解耦,比如那些根据MVVM模式开发的应用.此模 式广泛应用在基于 ...
- 推荐几款基于Bootstrap的响应式后台管理模板
1.Admin LTE 该模版开源免费. AdminLTE - 是一个完全响应式管理模板.基于Bootstrap3的框架.高度可定制的,易于使用.支持很多的屏幕分辨率适合从小型移动设备到大型台式机. ...
- net core 发布到服务器的方式
---恢复内容开始(15:05:15)--- using (var scope = ServiceProvider.CreateScope()){ var aSubscriber = Activato ...
- CSS 文字超长省略显示并隐藏超长部分
1.包含文字的元素必须是块级元素,不是块级元素使用display:block使其具有块级元素属性: 2.具备上述基本条件后,css样式如下: { display: block; max-width: ...
- css三栏布局方案整理
日常开发中,经常会用到css三栏布局,现将工作中常用的css 三栏布局整理如下: 什么是三栏布局: 三栏布局,顾名思义就是两边固定,中间自适应. 一. float布局 <!DOCTYPE htm ...
- 2017年12月13日 LinQ用法基本的增删改查
LinQ是什么? LinQ是语言集成的查询,是用于C#跟Vb的扩展语言 LinQ的用法 新建一个App_Code文件夹,在文件夹下添加一个数据LinQ to SQL类,可以直接直接点击服务器管理器然后 ...
- Mybatis插入、查询自定义的数据类型的方式
1.首先创建JavaBean对象 package com.zuo.Mybatis.bean; public class PhoneNumber { private String countryCode ...