第二次作业

GitHub地址

https://git.coding.net/songofjoy/softwareProject.git

PSP

PSP2.1

Personal Software Process Stages

预估耗时(分钟)

实际耗时(分钟)

Planning

计划

20

10

·Estimate

· 预估时间

10

10

Development

开发

370

330

·Analysis

· 需求分析(包括学习新技术)

30

40

·Design Spec

· 生成设计文档

10

30

·Design Review

· 设计复审

20

30

·Coding Standard

· 代码规范

40

30

·Design

· 具体设计

60

100

·Coding

· 具体编码

220

180

·Code Review

· 代码复审

30

40

·Test

· 测试(自我测试,修改代码,提交修改)

140

170

Reporting

报告

250

250

·Test Report

· 测试报告

220

220

·Size Measurement

· 计算工作量

20

20

·Postmortem&Process Improvement Plan

· 事后总结并提出过程改进计划

20

30

合计

 

630

830

需求分析

目标

做一个多功能的四则混合运算器

特性

1.支持分数的四则运算

2.可以实现打分功能

3.计时功能

4.储存历史得分记录

5.实现了中英文繁体的切换

面向用户

主要用于小学生使用,通过这样的一个四则运算工具,可以进行打分测评,可以用来训练计算准确率

假定约束

开发方法:面向对象的开发技术
开发语言:Java
开发期限:1周

需求规定

1.表达式计算:在文本框输入一个表达式,可以返回结果

2.表达式计算判断功能:在文本框输入一个含有=的式子,可以返回是否计算正确

3.中英简繁体转化功能:可以实现java语言的国际化

4.计分功能:可以用来记录历史得分情况

5.计时功能:可以用来计时

6.GUI用户界面:可以更方便的进行用户操作

 

运行环境规定

设备:PC
支持:PC支持Windows操作系统
控制:本软件主要GUI界面运行

详细设计

设计思路

1.将表达式进行数字运算符分离,存入数组

2.通过1中的数组进行一个中缀到逆波兰表达式额转换,运用了双栈来完成

3.分别编写加减乘除等函数

4.根据辗转相除法实现一个求最大公约数、最小公倍数的函数

5.编写判断函数,判断式子是否正确

6.读写文件的函数实现,关闭系统时可以将计算正确率、正确题目等信息保存至文件,下次打开自动调用

7.计时功能、计算正确率统计,中英文繁体转换的函数实现

8.用户交互界面:制作了一个简单的UI界面,使操作更加方便。

 

用户交互界面展示

 

 

 

界面说明

1.右下角是可以实现简体繁体英文的切换。

2.左下角是历史的正确率、正确题目和错误题目,关闭系统数据依然保留。

3.“重置”按钮是使正确率、正确题目和错误题目归0

4.“清除”按钮是使TextField清空。

5.“退格”按钮是使TextField删除末尾的字符。

6.’=’=的区别:

1’=’指在TextField添加一个’=’字符到末尾。

2= 指运算或者判断对错,如果TextField里面没有含=,则计算表达式的结果;如果TextField里面含=,就判断该式子是否正确。

7.“计”实现了计时功能,第一次点击是开始计时,第二此点是停止,第三次点是清0.

 

核心代码说明

 

ComputeController.java 加减乘除计算控制器

package calculator;

 

 

/**

 * 加减乘除计算

 * 冒号:表示一个分数,左边是分子,右边是分母

 *

 * @author Song

 *

 */

public class ComputeController {

 

/**

 * 执行计算

 * @param data1

 * @param data2

 * @param sign

 * @return

 */

public static String exec(String a1,String a2,String sign){

 

String retString="";

switch (sign) {

case "+":retString=add(a1, a2);break;

case "-":retString=substract(a1, a2);break;

case "×":retString=mutiply(a1, a2);break;

case "÷":retString=devide(a1, a2);break;

}

return retString;

 

}

 

/**

 * 是否是加减乘除运算符

 * @param string

 * @return

 */

public static boolean isSign(String string){

 

if(string.equals("+")||string.equals("-")||

string.equals("×")||string.equals("÷")){

return true;

}

return false;

}

/**

 * 求最大公约数

 * @param a1

 * @param a2

 * @return

 */

public static int gcd(int a1,int a2){

 

if(a1==0||a2==0){System.out.println("Error:the data is zero.");}

int min=a1;

int max=a1;

if(a1<a2){

max=a2;

}

else{

min=a2;

}

if(max%min==0){

return min;

}

int temp=max%min;

max=min;

min=temp;

while(max%min!=0){

temp=max%min;

max=min;

min=temp;

}

return min;

}

/**

 * 求最小公倍数

 * @param a1

 * @param a2

 * @return

 */

public static int lcm(int a1,int a2){

 

if(a1==0||a2==0){System.out.println("Error:the data is zero.");}

int gcd=gcd(a1,a2);

 

return a1/gcd*a2;

}

/**

 * stringdata转化为分数的表示形式

 * @param data

 * @return

 */

public static int [] string2fac(String data){

int [] retfac=new int[2];

if(data.contains("/")){

String strings[]=data.split("/");

retfac[0]=Integer.valueOf(strings[0]);

retfac[1]=Integer.valueOf(strings[1]);

}

else{

int integer=Integer.valueOf(data);

retfac[0]=integer;

retfac[1]=1;

}

return retfac;

}

DoubleStack.java 处理计算优先级(双栈和逆波兰表达式)

package calculator;

 

import java.util.ArrayList;

import java.util.Stack;  

 

/**

 * 高级软件工程

 * @author Song

 *

 */

public class DoubleStack {  

 

private ArrayList<String> testString=new ArrayList<>();

    private Stack<String> stack = null;  

    private ArrayList<String> createStrings=new ArrayList<>();

    

    public DoubleStack(String testString) {  

        this.testString = string2array(testString);  

        this.stack = new Stack<String>();  

    }  

    /**

     * 打印逆波兰表达式和

     */

    public void printCreString(){

     System.out.println(createStrings);

    }

    /**

     * 根据逆波兰表达式计算值

     */

    public String compute(){

    

     String ERRORINFO="The Function Is Wrong!";

     try{

         if(createStrings==null||createStrings.size()==0){

         return ERRORINFO;

         }

         while(createStrings.size()!=1){

         int i;

         for(i=0;i<createStrings.size();i++){

         if(ComputeController.isSign(createStrings.get(i))){

         if(i-2<0){return ERRORINFO;}

         String compute=ComputeController.exec(createStrings.get(i-2), createStrings.get(i-1), createStrings.get(i));

         createStrings.set(i-2, compute);

         createStrings.remove(i);

         createStrings.remove(i-1);

         break;

         }

         else if(i==createStrings.size()-1){return ERRORINFO;}

         }

         }

     }

     catch(Exception e){

     return ERRORINFO;

     }

    

     return createStrings.get(0);

    }

    /**

     * 逆波兰 双栈

     */

    public ArrayList<String> analysisString() {  

        for (int i = 0; i < testString.size(); i++) {  

            String c = testString.get(i);  

            if (c.equals("+") || c.equals("-")) {  

                if (stack.isEmpty() || stack.peek().equals("(")) {  

                    stack.push(c);  

                } else {  

                    while (!stack.isEmpty()  

                            && (stack.peek().equals("×") || stack.peek().equals("÷")  

                                    || stack.peek().equals("+") || stack.peek().equals("-"))) {  

                     createStrings.add(stack.pop());

                    }  

                    stack.push(c);  

                }  

            } else if (c.equals("×")|| c.equals("÷")) {  

                if (stack.isEmpty() || stack.peek().equals("+")

                        || stack.peek().equals("-") || stack.peek().equals("(")) {  

                    stack.push(c);  

                } else {  

                    while (!stack.isEmpty()  

                            && (stack.peek().equals("÷") || stack.peek().equals("×"))) {  

                      createStrings.add(stack.pop());

                    }  

                    stack.push(c);  

                }  

            } else if (c.equals("(")) {  

                stack.push(c);  

            } else if (c.equals(")") ){  

                String temp = "";  

                while (!(temp = stack.pop()).equals("(")) {  

                  createStrings.add(temp);

                }  

            } else {  

             createStrings.add(c);

            }  

        }  

        if (!stack.isEmpty()) {  

            while (!stack.isEmpty()) {  

             createStrings.add(stack.pop());

            }  

        }  

        return createStrings;

    }  

    /**

     * stringarray

     * @param input

     * @return

     */

    public static ArrayList<String> string2array(String input){

    

     String curString="";

     ArrayList<String> strings=new ArrayList<>();

     for(int i=0;i<input.length();i++){

     char curchar=input.charAt(i);

     if(curchar<58&&curchar>47||curchar=='/'){curString+=curchar;}

     else{

     if(!curString.equals("")){strings.add(curString);}

     strings.add(""+curchar);curString="";

     }

     }

     if(!curString.equals("")) {strings.add(curString);}

     return strings;

    }

    

  

}  

Frame.java 简易GUI用户界面

package calculator;

 

import java.awt.EventQueue;

 

public class Frame extends JFrame {

 

/**

 *

 */

private static final long serialVersionUID = 1L;

private JPanel contentPane;

private JTextField textField;

 

    JLabel lblNewLabel_1 = new JLabel("0");

JLabel label_2 = new JLabel("0");

JLabel label_3 = new JLabel("0.0%");

 

static JLabel lblNewLabel = new JLabel("正确题目");

static JLabel label = new JLabel("错误题目");

static JLabel label_1 = new JLabel("正确率");

static JButton button_20 = new JButton("重置");

static JButton button_19 = new JButton("清除");

static JButton button_18 = new JButton("退格");

static JButton button_23 = new JButton("简");

static JButton button_21 = new JButton("繁");

static JButton button_22 = new JButton("英");

 

static final String EN="resource_english";

static final String CH="resource_zh_CN_1";

static final String HARD="resource_hard";

 

static Score curScore=new Score();

DecimalFormat df= new DecimalFormat("######0.0");   

 

/**

 * 字体中英繁切换

 * @param resource

 */

public static void changeCharacter(String resource){

 

ResourceBundle rb = ResourceBundle.getBundle(resource);

lblNewLabel.setText(rb.getString("rightAmount"));

label.setText(rb.getString("wrongAmount"));

label_1.setText(rb.getString("radioAmount"));

button_20.setText(rb.getString("reset"));

button_19.setText(rb.getString("clear"));

button_18.setText(rb.getString("back"));

button_23.setText(rb.getString("simply"));

button_21.setText(rb.getString("hard"));

button_22.setText(rb.getString("english"));

 .......

}

 

 

Score.java 评分模型

package calculator;

 

public class Score {

 

private int rightAmount;

private int wrongAmount;

private double radioAmount;

 

public int getRightAmount() {

return rightAmount;

}

public void setRightAmount(int rightAmount) {

this.rightAmount = rightAmount;

}

public int getWrongAmount() {

return wrongAmount;

}

public void setWrongAmount(int wrongAmount) {

this.wrongAmount = wrongAmount;

}

public double getRadioAmount() {

return radioAmount;

}

public void setRadioAmount(double radioAmount) {

this.radioAmount = radioAmount;

}

}

 

Util.java 公共类(文件的读取写入)

package calculator;

 

import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.io.InputStreamReader;

import java.text.ParseException;

import java.util.Date;

 

 

public class Util {

 

static String FILENAME="score.dat";

public static String SPLITSTRING = "&HHS&";

//创建Score

public static void createScore() throws IOException {

 

Score score=new Score();

 

FileWriter writer = new FileWriter(FILENAME);

writer.write(score.getRightAmount() + SPLITSTRING);

writer.write(score.getWrongAmount() + SPLITSTRING);

writer.write(score.getRadioAmount() + SPLITSTRING);

writer.close();

}

//读取分数

public static Score readScore() throws IOException, ParseException {

 

Score score=new Score();

BufferedReader reader = new BufferedReader(new FileReader(FILENAME));

String line = reader.readLine();

String []infos=line.split(SPLITSTRING);

score.setRightAmount(Integer.valueOf(infos[0]));

score.setWrongAmount(Integer.valueOf(infos[1]));

score.setRadioAmount(Double.valueOf(infos[2]));

 

return score;

 

}

//写分数

public static void saveScore(Score score) throws IOException, ParseException {

 

FileWriter writer = new FileWriter(FILENAME);

writer.write(score.getRightAmount() + SPLITSTRING);

writer.write(score.getWrongAmount() + SPLITSTRING);

writer.write(score.getRadioAmount() + SPLITSTRING);

 

writer.close();

}

 

/**

 *

 * 获取目录下的所有文件名 By Hhs

 */

public static String[] getFileName(String path) {

File file = new File(path);

String[] fileName = file.list();

return fileName;

}

}

 

resource_zh_CN_1.properties等配置文件

 

实现了java语言的国际化,可以实现中文英文简体繁体的切换。

 

项目小结

这个作业功能是实现了,但是有些细节还需要改进,比如当计算结果取=时,如果输入下一个式子,TextField里面的内容不会自动清空,后期可以对这个进行一个优化,加一个字段的判断,如果按下=,该字段置为true,表示下个字符如果是数字就首先把TextField清空再放入数据。

在测试的时候出现一些小bug,比如对负数的处理等等,会得到令人意想不到的结果,当输入的表达式不合法时也加入了一个异常处理,返回The Function is Wrong!给前台界面,后期可以对此做改进,将异常返回做的细一点,比如是分母不能为0或者是数字太大或者是表达式里面有特殊字符,将错误信息尽可能细的返回给用户。

posted on 2017-09-28 22:13  songofjoy  阅读(153)  评论(7编辑  收藏  举报