• 2016012056+小学四则运算练习软件项目报告


    2016012056+小学四则运算练习软件项目报告

     

    写在前面:第一次看到作业要求时,觉得很难,一开始有种抗拒的心态。自己一直以来学习前端,对后端只是基本的了解而已。写的过程遇到了很多问题,虽然项目中还有许多不完善的地方,但通过此次作业,一个一个解决问题。经过这些天的“补课”,让我加深了后端的学习,虽然辛苦,但是收获了很多(所以说欠的债总是要还的)。

    项目克隆地址:https://git.coding.net/chenxin1998/calculate2.git

    一.需求分析

    小学生计算能力需要通过练习大量的运算题目得到锻炼,因此很多老师让家长每天给学生出相应的练习题。为了方便老师的教学任务,同时减轻家长的负担,现在需要一个可以出四则混合运算的小型软件。

    1.通过程序接受一个数字,产生N道加减乘除练习题。

    2.判断传入参数是否合法

    3.每个数字在0-100之间,运算符3-5个

    4.运算过程不能出现负数和非整数

    5.计算出练习题结果

    6.所有信息输出到txt文件

    二.功能设计

    基础功能:

    1. 程序可接收一个输入参数n,然后随机产生n道加减乘除练习题,每个数字在 0 和 100 之间,运算符在3个到5个之间。
    2. 为了让小学生得到充分锻炼,每个练习题至少要包含2种运算符。同时,由于小学生没有分数与负数的概念,你所出的练习题在运算过程中不得出现负数与非整数,比如不能出 3/5+2=2.6,2-5+10=7等算式。
    3. 练习题生成好后,将你的学号与生成的n道练习题及其对应的正确答案输出到文件“result.txt”中,不要输出额外信息,文件目录与程序目录一致。
    4. 当程序接收的参数为4时,以下为输出文件示例。 

    扩展功能:

    1. 支持有括号的运算式,包括出题与求解正确答案。注意,算式中存在的括号必须大于2个,且不得超过运算符的个数。
    2. 扩展程序功能支持真分数的出题与运算,例如:1/6 + 1/8 + 2/3= 23/24。注意在实现本功能时,需支持运算时分数的自动化简,比如 1/2+1/6=2/3,而非4/6。

    三.设计实现:

    1.在实现过程中,为了更好地实现模块化,我分了三个类,分别是:

    CreatProblem.java(随机创建一个运算过程不含负数和小数的四则算式);RandomArithmetic.java(主程序类操作,但操作隐藏);WriteResult.java(文件写入)

    2.用到的重要函数:

    产生四则运算:CreateProblem函数,其中Random随机产生3-5个运算符,且带括号的四则运算式子。若式子不符合要求,则用递归到合法为止。

    计算结果:getResult函数,在四则运算式生成后,计算每一部分的结果,且排除带有小数和负数的式子。

    启动程序:RandomAtithmetic函数,接收参数n,并判断其合法性。

    3.用两个Character栈存储数字和符号,然后用两个栈分别用作转换的缓冲栈和计算结果的缓冲栈

    4.一般Character里面的编码是ascii,但我没有那样做,就是一种新的编码,用ascii0-99表达0-99,而符号和数字冲突,所以符号是100-105

    优点:比用string省空间

    缺点:虽然有括号识别但随机生成算式没有括号(这是需要继续完善的地方)

     

    四.测试运行:

    进入src文件下,输入javac -encoding utf-8 RandomArithmetic.java 编译出相应的class文件,再输入java RandomArithmetic 10进行测试:

     

     

    注意:一开始进行测试的时候,在命令行会出现“找不到或无法加载主类”的情况。最后通过查阅博客,发现是由于JRE版本问题。这是由于我使用高版本的JDK编译的Java class文件试图在较低版本的JVM上运行,所报的错误。 因为,高版本的JDK生成的class文件使用的格式,可能与低版本的JDK的.class文件格式不同。这样,低版本的JVM无法解释执行这个.class文件。于是,问题就变成了“如何解决JDK和JRE版本不一致”,最后只是通过从新安装JDK和JRE,然后重配环境解决。

    里面还有一些原理没有弄懂,待以后开发。

    总结几个知识点吧~~

    JDK、JRE有什么区别:

    Jre   是java   runtime   environment的缩写,   是java程序的运行环境。既然是运行,当然要包含jvm,也就是大家熟悉的虚拟机啦, 还有所有java类库的class文件,都在lib目录下打包成了jar。大家可以自己验证。至于在windows上的虚拟机是哪个文件呢?  Javajdk jreinclient里面是不是有一个jvm.dll呢?那就是虚拟机。

    Jdk   是java   development   kit,是java的开发工具包,里面包含了各种类库和工具。当然也包括了另外一个Jre--------Javajre.  那么为什么要包括另外一个Jre呢?而且jdkjrein同时有client和server两个文件夹下都包含一个jvm.dll。   说明是有两个虚拟机的。

    Javajdkin这个bin下有各种java程序需要用到的命令,与Javajdkjrein或者Javajrein的bin目录最明显的区别就是Javajdkin下才有javac.exe,这一点很好理解,因为 jre只是一个运行环境而已。与开发无关,正因为如此,具备开发功能的jdk自己的jre下才会同时有client性质的jvm和server性质的 jvm, 而仅仅作为运行环境的jre下只需要client性质的jvm.dll就够了。

    我们用的java命令并不是 Javajdkin目录下的而是Javajdkjrein目录下的。不信可以做一个实验,大家可以把Javajdkin目录下的java.exe剪切到别的地方再运行 java程序,发现了什么?一切OK!

    如果java为了提供给大多数人使用,他们是不需要jdk做开发的,只需要jre能让java程序跑起来就可以了,那么每个客户还需要手动去设置环境变量多麻烦啊?

    所以安装jre的时候安装程序自动帮你把jre的java.exe添加到了系统变量中,因此去C:Windowssystem64下面去看看吧,发现有一个java.exe。

     五.核心代码:

    (1)JAVA用栈处理四则运算:

    一共分两步:

    1.中缀表达式转后缀表达式

    从左到右遍历中缀表达式的每一个数字和运算符。
    如果数字就输出(即存入后缀表达式);
    如果是右括号,则弹出左括号之前的运算符;
    如果优先级低于栈顶运算符,则弹出栈顶运算符,并将当前运算符进栈。
    遍历结束后,将栈则剩余运算符弹出。

    2.后缀表达式表达计算结果

    从左到右遍历后缀表达式,遇到数字就进栈,遇到符号,就将栈顶的两个数字出栈运算,运算结果进栈,直到获得最终结果。

     

    //创建若干个四则运算中缀表达式
    //////////////////////////////////////
    ///注意,为减小内存使用,ascii0-100表示数字0-99,100-103分别表示加减乘除,()为104,105
    ////////////////////////////////////////
    import java.util.Random;
    import java.util.*;//
    import java.lang.*;
    
    public class CreateProblem {
        private int numOfNum=3;//存储该表达式有几个运算数,默认3个
        private Stack<Character> infix= new Stack<Character>();//中缀表达式  
        private Stack<Character> suffix=new Stack<Character>();//后缀表达式
        private Stack<Character> stackOfOperation=new Stack<Character>();//计算后缀表达式所用栈
        private Stack<Integer> stackOfNum=new Stack<Integer>();//计算结果所用栈
        private int max=100;//运算数最大值,默认100
    

     (2)如何解决四则运算表达式中不能出现负数和小数的问题

    int getResult()//如果结果是-1,说明随机运算不满足要求,重新创建新的运算式
    	{
    		//根据后缀表达式计算并且检查算式是否合法,是否有小数或者负数在运算中出现,如果出现,重新创建新的表达式并相应转换
    		int i=0;
    		while(i<suffix.size())
    		{
    			int temp,temp0;
    			char c=suffix.get(i);
    			if(isDigit(c))  stackOfNum.push((int) c);//将所有字符数字转换为整数型并入栈
    			else if(c==100||c==101||c==102||c==103)
    			{
    				switch(c)
    				{
    				case 100:
    					temp=stackOfNum.pop();
    					temp0=stackOfNum.pop();
    					stackOfNum.push(temp0+temp);
    					break;
    					
    				case 101:
    					temp=stackOfNum.pop();
    					temp0=stackOfNum.pop();
    					if(temp0-temp<0) return -1;//不满足运算中不得出现负数的要求,因此结束程序
    					else stackOfNum.push(temp0-temp);
    					break;
    				case 102:
    						temp=stackOfNum.pop();
    						temp0=stackOfNum.pop();
    						stackOfNum.push(temp*temp0);
    						break;
    				case 103:
    						temp=stackOfNum.pop();
    						temp0=stackOfNum.pop();
    						if(temp0%temp==0) stackOfNum.push(temp0/temp);
    						else return -1;//不满足运算中不得出现小数的要求,因此结束程序
    						break;
    				}
    			}
    			i++;
    		}
    		if(!stackOfNum.empty()) return stackOfNum.pop();
    		else return -1;
    	}
    

     (3)一开始在写文件的时候出现了陷入循环无法出来的情况,错误代码如下:

    public static void write(CreateProblem problem) throws IOException
    	{
    		int i=0;
    		File file=new File("result.txt");
    		try (PrintWriter output=new PrintWriter(file);
    		)
    		{
    		while(i<problem.showInfix().size()) 
    		{
    			String str=new String("");
    			char ch=problem.showInfix().get(i);
    			switch(ch)
    			{
    			case 100:str+"+";break;
    			case 101:str+"-";break;
    			case 102:str+"*";break;
    			case 103:str+"/";break;
    			case 104:str+"(";break;
    			case 105:str+")";break;
    			default:str+((int)ch);break;
    			}
    			i++;
    		}
    		output.print('=');
    		output.print(problem.getResult());
    		output.print('
    ');
    		}
    		file.close();
    		output.close();
    	}
    	public static void write(String s) throws IOException
    	{
    		File file=new File("result.txt");
    		try (PrintWriter output=new PrintWriter(file);
    			
    		) {
    		output.println(s);
    		}
    		file.close();
    		output.close();
    	}
    }
    

    修改后的代码如下:

    import java.io.*;
    //写文件
    public class WriteResult
    {
    
    	public static void w1(String str) {
    		
    	    try {
    	    File f=new File("result.txt");
    	    FileWriter writer=new FileWriter(f,true);
    	    PrintWriter pw=new PrintWriter(writer);
    	    pw.append(str);
    	    pw.println("");
    	    pw.flush();
    	    pw.close();
    	    } catch (IOException e) {
    	      e.printStackTrace();
    	    }
    	}
        
    	public static void w2(CreateProblem problem)
    	{
    		int i=0;
    		String s=new String();
    		while(i<problem.showInfix().size()) 
    		{
    			char ch=problem.showInfix().get(i);
    			switch(ch)
    			{
    			case 100:s+="+";break;
    			case 101:s+="-";break;
    			case 102:s+="*";break;
    			case 103:s+="/";break;
    			case 104:s+="(";break;
    			case 105:s+=")";break;
    			default:s+=((int)ch);break;
    			}
    			i++;
    		}
    		 try {
    			    File f=new File("result.txt");
    			     FileWriter writer=new FileWriter(f,true);
    			     PrintWriter pw=new PrintWriter(writer);
    			      pw.append(s);
    			      pw.append('=');
    			      pw.println(problem.getResult());
    			      pw.flush();
    			      pw.close();
    			    } catch (IOException e) {
    			      e.printStackTrace();
    			    }
    	}
    }
    

    六.总结:

    在该小学四则运算小程序中主要分为三个类,其中RandomArithmetic类负责开启程序运行的入口,CreateProblem主要用于处理运算式,WriteResult用于文件写入,整个程序由这三个类块构成,实现了功能的模块化。其中在CreateProblem类中又分离出了private Stack<Integer> stackOfNum=new Stack<Integer>();//计算结果所用栈;private Stack<Character> suffix=new Stack<Character>();//后缀表达式private Stack<Character> stackOfOperation=new Stack<Character>();//计算后缀表达式所用栈;这样设计使得各功能再次模块化,使得程序更加的便于维护和扩展。

    最后,就是完成一个项目的喜悦了,所以从事我们这一行,还是要多看,多写,理论与实践结合。

     七.PSP总结

    PSP2.1

    任务内容

    计划完成需要的时间(h)

    实际完成的时间(h)

    Planning

    计划

     0.5  1

    ·   Estimate

    ·估计这个任务需要多少时间,并规划大致工作步骤

     3天  4天

    Development

    开发

     2天  3天

    ··  Analysis

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

     12  18

    ·   Design Spec

    ·生成设计文档

     0.5  0.5

    ·   Design Review

    ·设计复审 (和同事审核设计文档)

     0.6  0.8

    ·   Coding Standard

      代码规范 (为目前的开发制定合适的规范)

     0.5  0.6

    ·   Design

      具体设计

     3  3.5

    ·   Coding

      具体编码

     12  20

    ·   Code Review

    · 代码复审

     3  4

    ·   Test

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

     2  5

    Reporting

    报告

     3.5 4

    ··  Test Report

    · 测试报告

     1.5  2

    ·   Size Measurement

      计算工作量

     0.5  0.5

    ·  Postmortem & Process Improvement Plan

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

     1.5  1.5
  • 相关阅读:
    英语八大时态
    linux yum被占用
    文件上传ajaxfileupload.js插件
    jquery.qrcode.js生成二维码
    判断手机,pc方式登录
    点击小图轮播,点击显示大图
    图片预览功能
    Java Hash表 数据结构
    Java Tree 树 数据结构
    Java Queue 队列
  • 原文地址:https://www.cnblogs.com/chenyyxx/p/8639939.html
Copyright © 2020-2023  润新知