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. CentOS6.4 安装Redis

    按照下面步骤依次执行1.检查依赖,安装依赖 [root@ecs-3c46 ~]# whereis gcc gcc: /usr/bin/gcc /usr/lib/gcc /usr/libexec/gcc ...

  2. bzoj 3512: DZY Loves Math IV

    Description 给定n,m,求 模10^9+7的值. Solution 设 \(S(n,m)\) 表示 \(\sum_{i=1}^{m}\phi(n*i)\) \(Ans=\sum_{i=1} ...

  3. Delphi下OpenGL2d绘图(02)-画点

    一.前言 图形的绘制可以使用glBegin().glEnd()之间完成,绘制的框架代码可以使用 Delphi下OpenGL2d绘图(01)-初始化 中的代码.修改的部份为 Draw 函数的内容. 二. ...

  4. redis(7)LRU缓存

    一.LRU简介 LRU是Least Recently Used的缩写,即:最近最少使用. 它是内存管理中的一种页面置换算法,对于在内存中但是又不用的数据块,操作系统会根据哪些数据属于LRU而将其移除内 ...

  5. ps命令详解加例子

    Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信 ...

  6. Hibernate 脏检查和刷新缓存机制

    刷新缓存: Session是Hibernate向应用程序提供的操作数据库的主要接口,它提供了基本的保存,更新,删除和加载java对象的方法,Session具有一个缓存,可以管理和追踪所有持久化对象,对 ...

  7. JS实现九九乘法表和时间问候语

    编码 小练习,练习使用循环实现一个九九乘法表 第一步,最低要求:在Console中按行输出 n * m = t 然后,尝试在网页中,使用table来实现一个九九乘法表 <!DOCTYPE htm ...

  8. JS原型链继承

    继承普通版 继承逻辑上都差不多,普通版调用方式比较繁琐,不利于反复大量的使用: (function (){ //创建一个人员类 function Person(name){ this.name = n ...

  9. webapi下载文件

    [HttpGet] public IHttpActionResult ExportData() { ... var dt = ExcelHelper.ListToDataTable(list); va ...

  10. 01_Nginx入门

    [Nginx概述] Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-Like协议下发行.其特点是占有内存少,并发能力强,事实上Nginx ...