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. 调试日志

  1. 添加括号时括号是否存在与四则运算本身毫无影响,后续通过if来判定只有同时出现“-+”和“*/”括号才满足条件出现。

  2. 括号的添加位置产生错误,出现类似 100 ( + 200 ) * 300的错误四则运算,后续通过indexOf的方法来查找 “+-”的位置然后向左和向左查询空格的下标来添加括号。

  3. 调度场算法的判断运算符优先级时理解错误,但是运算符栈的输入错误,后续通过修改transferToPostfix(LinkedList《string》 list)中的if来修正。

  4. 逆波澜算法的多次运算问题,用于保存答案的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的更多相关文章

  1. 耿丹CS16-2班第二次作业汇总

    -- Deadline: 2016-09-28 12:00 -- 作业内容:http://www.cnblogs.com/huangjunlian/p/5891726.html -- 第二次作业总结: ...

  2. JAVA第二次作业展示与学习心得

    JAVA第二次作业展示与学习心得 在这一次作业中,我学习了复选框,密码框两种新的组件,并通过一个邮箱登录界面将两种组件运用了起来.具体的使用方法和其他得组件并没有什么大的不同. 另外我通过查阅资料使用 ...

  3. 20169212《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...

  4. 软件工程(QLGY2015)第二次作业点评(随机挑选20组点评)

    相关博文目录: 第一次作业点评 第二次作业点评 第三次作业点评 说明:随机挑选20组点评,大家可以看看blog名字,github项目名字,看看那种是更好的,可以学习,每个小组都会反应出一些问题,希望能 ...

  5. 程序设计第二次作业<1>

    面向对象程序设计第二次作业<1> Github 链接:https://github.com/Wasdns/object-oriented 题目: <1>第一次尝试 我立马认识到 ...

  6. homework-02,第二次作业——寻找矩阵最大子序列和

    经过漫漫漫~~~~~~~~~~~~~~长的编译和调试,第二次作业终于告一段落了 先放出源码,思路后面慢慢道来 #include<stdio.h> #include<stdlib.h& ...

  7. 20169210《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...

  8. SQL 第二章 作业

    /*第二章 作业*/ create table S ( sno char(2) NOT NULL UNIQUE, sname char(3), city char(2) ); alter table ...

  9. 软件工程(GZSD2015)第二次作业小结

    第二次作业,从4月7号开始,陆续开始提交作业.根据同学们提交的作业报告,相比第一次作业,已经有了巨大改变,大家开始有了完整的实践,对那些抽象的名词也开始有了直观的感受,这很好.然后有一些普遍存在的问题 ...

随机推荐

  1. javascript通过class获取元素

    1.getElementsByClassName 非IE6,7,8可以直接用自带的属性 getElementsByClassName,如果需要兼容 function getElementsByClas ...

  2. 快速部署简单私有云CloudStack(上)

    前言: 亲身用了大半年,没出过重大毛病,也就是服务挂了,跟服务器也没啥关系.如果想更深入学习cloudstack可以试试高级网络,我是一直用的简单网络(扁平网络). 由来:CloudStack的前身是 ...

  3. 我Java学习时的模样(三)

    读Java源码 平常使用Java的时候,那些集合类使用起来很顺手,但是有没有想过这些集合内部的实现原理是怎样的,它的添加移除都有哪些操作? 有了一些工作经验之后,必须要读一读Java包中的源码,需要知 ...

  4. jQuery 小练习-拖拉画面

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 在centos linux上安装docker

    前置条件 64-bit 系统 kernel 3.10+ 1.检查内核版本,返回的值大于3.10即可. $ uname -r 2.确保yum是最新的 $ yum update 3.安装 Docker y ...

  6. Timer 控件

    1. 设置属性 Enable = true  或调用 start方法后, *_Tick 方法不会立即执行,会先等待一个时间间隔 2.timer1不管你上次的事情是否做完,它都会每个一个时间间隔做它应该 ...

  7. sql创建表变量,转百分数

    declare @tab table( ID nt identity(1,1) primary key, --从1开始,每次自增1 ,Name nvarchar(200) ) declare a fl ...

  8. JMS - 基于JMS的RPC

    现在试试通过JMS,在应用程序之间发送消息.先看看spring提供的RPC方案(其实还有其他方案,只是没见过谁用).需要使用到这两个类:·org.springframework.jms.remotin ...

  9. Vue-Router的使用(一)

    1.首先,安装vue-router npm install vue-router --save-dev 2.创建一个route.js文件 // 1. 定义路由组件 // 可以自己写的,或者导入的,大部 ...

  10. JavaScript switch语句

    JavaScriptswitch语句 switch语句用于基于不同的条件来执行不同的动作. JavaScript switch 语句 使用switch语句可以进行多项选择. 语法: switch( 变 ...