github地址:https://github.com/myGitHub1018/Student_comput
一、需求分析
1、由用户输入参数n,然后随机产生n道加减乘除练习题;
2、每个数字在 0 和 100 之间,运算符在3个到5个之间;
3、运算过程中不得出现负数与非整数,比如不能出 3/5+2=2.6,2-5+10=7等算式;
4、将学号与生成的n道练习题及其对应的正确答案输出到文件“result.txt”中,文件目录与程序目录一致。
例如:当程序接收的参数为4时,输出如下:
软件附加功能要求如下:
- 支持有括号的运算式,包括出题与求解正确答案。算式中存在的括号必须大于2个,且不得超过运算符的个数。
- 扩展程序功能支持真分数的出题与运算,例如:1/6 + 1/8 + 2/3= 23/24。注意在实现本功能时,需支持运算时分数的自动化简,比如 1/2+1/6=2/3,而非4/6。
二、设计实现
1、由用户输入参数n,保存练习题的数量;
2、当输入不合理时,提示重新输入;
3、随机产生3-5个加减乘除运算符以及1-100之间的随机数;
4、运算结果不能为负数和非整数;
5、将学号与生成的n道练习题及其对应的正确答案输出到文件“result.txt”中。
三、功能实现
程序流程图:
四、测试运行
1、项目名称为Suanfa_l,路径如下(包括result.txt文件):
2、测试异常输入:
当输入的数据不是1-1000之间的数字时,输出提示语句,用户重新输入,结果如下。当输入符合要求时,输出四则运算表达式及正确答案,如下图所示:
3、Eclipse执行情况和result.txt文件的输入情况:
五、核心代码
1、文件定义
(1)第一行代码是使用JDK自带的类调用JS,实现执行字符串中的运算公式的功能。JAVA使用ScriptEngine解析脚本,ScriptEngineManager是一个工厂的集合,可以通过name或者tag的方式获取某一个脚本的
工厂,并且生成一个脚本的ScriptEngine,ScriptEngine是一个脚本引擎,包含eval操作方法;
(2)定义文件,如果没有则自己创建文件。
1 ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript"); 2 File file = new File("result.txt"); //生成保存结果的文件 3 FileOutputStream fop = new FileOutputStream(file); 4 5 //如果没有文件,自己创建 6 if (!file.exists()) { 7 file.createNewFile(); 8 }
2、异常处理
接受用户输入的参数x,使用while判断x是否在1-1000之间,若不在则抛出异常,重新输入;若符合则将x作为要生成的题目的数量。
1 String s = ""; 2 int x=-1; //题目数量 3 System.out.println("请输入题目的数量:"); 4 Scanner scan2 = new Scanner(System.in); 5 while(x < 1 || x > 1000) 6 { 7 try{ 8 x = scan2.nextInt(); 9 }catch(Exception e){ 10 System.out.println("输入不符合要求,请重新输入"); 11 scan2.next(); 12 x=-1; 13 } 14 if((x < 1 || x > 1000) && x != -1) 15 System.out.println("输入不符合要求,请重新输入"); 16 }
3、产生运算式以及结果的计算和处理
(1)定义num保存算式的结果;定义q保存算式,类型为字符串;定义a、b、c、d、e产生1-100之间的五个随机数;
(2)定义z保存一个3-5之间的随机数,用来设定运算式的数值个数,分类讨论;每种情况下都产生了一个1-4之间的随机数,每个数代表一个运算符,使用switch来判断;
(3)代码19-48行是z=3的情况,有三个运算数,两个运算符;代码50-89行是z=4的情况,有四个运算数,三个运算符;代码91-141行是z=5的情况,有五个运算数,四个运算符;
(4)142行代码调用eval方法,识别运算式,可自动识别优先级,计算出结果存入hush变量中,hush为String类型;
(5)143行将结果hush转换为Double类型,存到变量result中;
(6) 145-148处理结果是否为负数和非整数,将算式和结果写入文件,并在Eclipse中打印;
(7)149行将变量重置,进行下一次循环。
1 int a = 0;//运算式的第一个随机数 2 int b = 0;//运算式的第二个随机数 3 int c = 0;//运算式的第三个随机数 4 int d = 0;//运算式的第四个随机数 5 int e = 0;//运算式的第五个随机数 6 7 int num = 0;//结果 8 String q=""; //保存运算式 9 Random random = new Random(); 10 int i=0; 11 while(i<x){ 12 a = (int) (Math.random()*100+1); 13 b = (int) (Math.random()*100+1); 14 c = (int) (Math.random()*100+1); 15 d = (int) (Math.random()*100+1); 16 e = (int) (Math.random()*100+1); 17 18 int z = random.nextInt(5)%(5-3+1) + 3;//产生一个3-5之间的随机数,用来设定运算式的数值个数 19 if(z == 3){ 20 //3个数,则产生两个运算符 21 int A = random.nextInt(4)%(4-1+1) + 1; 22 switch(A){ 23 case 1: num = a + b; 24 q = a + "+" + b; 25 break; 26 case 2: num = a - b; 27 q = a + "-" + b; 28 break; 29 case 3: num = a * b; 30 q = a + "*" + b; 31 break; 32 default : 33 num = a / b; q = a + "/" + b; 34 break; 35 } 36 int B = random.nextInt(4)%(4-1+1) + 1; 37 switch(B){ 38 case 1: num = num + c; q = q + "+" + c; 39 break; 40 case 2: num = num - c; q = q + "-" + c; 41 break; 42 case 3: num = num * c; q = q + "*" + c; 43 break; 44 default : 45 num = num / c; q = q + "/" + c; 46 break; 47 } 48 } 49 50 if(z == 4){ 51 //4个数,则产生三个运算符 52 int A = random.nextInt(4)%(4-1+1) + 1; 53 switch(A){ 54 case 1: num = a + b; q = a + "+" + b; 55 break; 56 case 2: num = a - b; q = a + "-" + b; 57 break; 58 case 3: num = a * b; q = a + "*" + b; 59 break; 60 default : 61 num = a / b; q = a + "/" + b; 62 break; 63 } 64 int B = random.nextInt(4)%(4-1+1) + 1; 65 switch(B){ 66 case 1: num = num + c; q = q + "+" + c; 67 break; 68 case 2: num = num - c; q = q + "-" + c; 69 break; 70 case 3: num = num * c; q = q + "*" + c; 71 break; 72 default : 73 num = num / c; q = q + "/" + c; 74 break; 75 } 76 77 int C = random.nextInt(4)%(4-1+1) + 1; 78 switch(C){ 79 case 1: num = num + d; q = q + "+" + d; 80 break; 81 case 2: num = num - d; q = q + "-" + d; 82 break; 83 case 3: num = num * d; q = q + "*" + d; 84 break; 85 default : 86 num = num / d; q = q + "/" + d; 87 break; 88 } 89 } 90 91 if(z == 5){ 92 //5个数,则产生4个运算符 93 int A = random.nextInt(4)%(4-1+1) + 1; 94 switch(A){ 95 case 1: num = a + b; q = a + "+" + b; 96 break; 97 case 2: num = a - b; q = a + "-" + b; 98 break; 99 case 3: num = a * b; q = a + "*" + b; 100 break; 101 default : 102 num = a / b; q = a + "/" + b; 103 break; 104 } 105 int B = random.nextInt(4)%(4-1+1) + 1; 106 switch(B){ 107 case 1: num = num + c; q = q + "+" + c; 108 break; 109 case 2: num = num - c; q = q + "-" + c; 110 break; 111 case 3: num = num * c; q = q + "*" + c; 112 break; 113 default : 114 num = num / c; q = q + "/" + c; 115 break; 116 } 117 int C = random.nextInt(4)%(4-1+1) + 1; 118 switch(C){ 119 case 1: num = num + d; q = q + "+" + d; 120 break; 121 case 2: num = num - d; q = q + "-" + d; 122 break; 123 case 3: num = num * d; q= q + "*" + d; 124 break; 125 default : 126 num = num / d; q = q + "/" + d; 127 break; 128 } 129 int D = random.nextInt(4)%(4-1+1) + 1; 130 switch(D){ 131 case 1: q = q + "+" + e; 132 break; 133 case 2: q = q + "-" + e; 134 break; 135 case 3: q = q + "*" + e; 136 break; 137 default : 138 num = num / d; q = q + "/" + e; 139 break; 140 } 141 } 142 String hush=String.valueOf(jse.eval(q)); 143 Double result=Double.parseDouble(hush); 144 145 if(result<0 || result%1!=0) { continue; } //结果不能为负数和非整数 146 fop.write((q+"=" + jse.eval(q)).getBytes()); //写入表达式 147 fop.write("\r\n".getBytes()); //换行 148 System.out.println(q+"="+jse.eval(q)); 149 q=""; result=(double) 0; i++; //重新置为空,重新开始 150 }
六、总结
这次设计主要包括三个部分,文件的产生和定义、异常处理以及运算式的产生以及结果的计算和处理。设计时最困难的就是运算式的产生和结果的处理,最后调用eval方法使得
运算式计算时不需要考虑优先级,实现简单了很多。
七、PSP展示
PSP2.1 | 任务内容 | 计划完成的时间(min) | 实际完成需要的时间(min) |
---|---|---|---|
PLanning | 计划 | 20 | 20 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 20 | 40 |
Developmet | 开发 | 240 | 320 |
Analysis | 需求分析(包括学习新技术) | 20 | 30 |
Design Spec | 生成设计文档 | 5 | 5 |
Design Revie | 设计复审(和同事审核设计文档) | 5 | 4 |
Coding Standard | 代码规范 | 2 | 2 |
Design | 具体设计 | 40 | 50 |
Coding | 具体编码 | 120 | 140 |
Code Review | 代码复审 | 5 | 5 |
Test | 测试(自我测试,修改代码,提交修改) | 30 | 45 |
Reporting | 报告 | 30 | 40 |
Test Report | 测试报告 | 8 | 10 |
Size Measurement | 计算工作量 | 3 | 3 |
Postmortem & Process Improvement Plan | 事后总结,并提出过程改机计划 | 10 | 15 |
项目总结:
本次项目在刚开始分析问题时觉得不是特别困难,但实际设计时发现要考虑的问题很多,其中问题最多的就是运算式的产生和结果的处理,刚开始运算符的优先级一直有问题,
导致结果不正确,最后使用ScriptEngine解析脚本,调用eval方法处理结果,不用再对运算符进行优先级处理,比较投机取巧,使得代码比较之前简化了很多,节省了大量的时间。
这次代码写的比较简单,由于能力有限,没有实现附加功能,以后会继续努力,希望自己做的更好。
原文地址:https://www.cnblogs.com/nwnu-liul/p/8615076.html