Java實現四則運算---任路乾,樂滔
1、GitHub地址:https://github.com/3116004700/ruanjiangongcheng
2、項目需求:
- 生成的題目中計算過程不能產生負數(完成)
- 生成的題目中如果存在形如e1 ÷ e2的子表達式,那麽其結果應是真分數。(完成)
- 程序一次運行生成的題目不能重復,生成的題目存入執行程序的當前目錄下的Exercises.txt文件(完成)
- 每道題目中出現的運算符個數不超過3個(完成)
- 在生成題目的同時,計算出所有題目的答案,並存入執行程序的當前目錄下的Answers.txt文件(完成)
- 程序應能支持一萬道題目的生成。(完成)
- 程序支持對給定的題目文件和答案文件,判定答案中的對錯並進行數量統計。(完成)
3、解題思路描述:
? 拿到這個項目首先想到的是和上一個項目的區別,都會涉及到IO的輸出,因為Java裏面IO的相關方法使用起來比較簡便,所以兩次的實現語言都是Java。
? 這次的項目有幾個要註意的地方:四則表達式的生成,要保證隨機;項目要求結果不能為負數;要判斷答案中的對錯,並且統計數量。這些問題的解決辦法會在後面詳細說明,這裏就不多贅述了。
4、設計實現過程:
? 整個項目總共有7個類,每個類裏面有不同的方法。(類列表如下圖)
基本的方法是GetCalculation類裏面的Get_Calculation()方法,這個方法生成了最基本的算術表達式。GetSymbol類是main()所在的類,用來啟動函數。
? 主要類之間具體的調用過程:
5、代碼說明:
因為代碼的量比較大,所以只是展示一部分關鍵代碼,完整的代碼可以去GitHub自行查看。
思路:這只是生成算數表達式的代碼的一部分,整個的算術表達式分成了很多種情況,要解決的問題就是將隨機得到的數字和運算符拼接成一個完整的、格式統一的算術表達式。其實這個只需要字符串的拼接就行了,真正的問題是如何保證得到的表達式的結果不為負數。這裏使用的方法就是利用運算符的下標位置進行判斷,因為只有減號才會出現負數,所以在減號出現的表達式裏都會對減號之前的數值和減號之後的數值進行比較,如果前者小於後者,那麽舍棄這個算式,重新生成新的算式。
public static String Get_Calculation1(int m) { String strings=String.valueOf(Getnum.Get_num(m))+" "+GetSymbol.Get_Symbol()+" "+String.valueOf(Getnum.Get_num(m))+" "+"="; String answer=null; String string =strings.replaceAll(" ", ""); String[] news=string.split("\\-|\\=|\\+|\\×|\\÷"); int a=Integer.parseInt(news[0]); int b=Integer.parseInt(news[1]); if(string.contains("-")) { if(a<b) { return Get_Calculation1(m); } else { answer=String.valueOf(GetResult.Num_sub_Num(a, b)); return strings+"&"+answer; } } if (string.contains("+")) { answer=String.valueOf(GetResult.Num_add_Num(a, b)); return strings+"&"+answer; } if (string.contains("×")) { answer=String.valueOf(GetResult.Num_mul_Num(a, b)); return strings+"&"+answer; }else { answer=GetResult.Num_div_Num(a, b); return strings+"&"+answer; } } public static String Get_Calculation2(int m) { String strings=String.valueOf(Getnum.Get_num(m))+" "+GetSymbol.Get_Symbol()+" "+Getnum.Get_Frac(m)+" "+"="; String string =strings.replaceAll(" ", ""); String[] string1=string.split("\\+|\\-|\\×|\\÷|\\="); String answer=null; int n=Integer.parseInt(string1[0]); String string2=string1[1]; if(string.contains("-")) { answer=GetResult.Num_sub_Fra(n, string2); if (answer.contains("-")) { return Get_Calculation2(m); } else if (!answer.contains("-")) { return strings+"&"+answer; } } if(string.contains("+")) { answer=GetResult.Num_add_Fra(n, string2); return strings+"&"+answer; } if (string.contains("×")) { answer=GetResult.Num_mul_Fra(n, string2); return strings+"&"+answer; } else { answer=GetResult.Num_div_Fra(n, string2); return strings+"&"+answer; } }
檢查答案正誤的方法:
思路:因為之前得到算數表達式的時候對格式嚴格要求了,所以在判斷正誤的時候就簡單了很多,題目文件中的內容和答案文件中的內容就只是差了答案這一部分,所以在判斷正誤的時候readline每一行,並且進行比較,把equals的結果記錄下來就是最終需要統計的數據。
package Com.software;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class Check {
WriteStringToFile ws = new WriteStringToFile();
void checkAnswer(File exercises,File answers) throws IOException{
BufferedReader br_e = new BufferedReader(new FileReader(exercises));
BufferedReader br_a = new BufferedReader(new FileReader(answers));
String line_e = null;
String line_a = null;
File fileGrade = new File("Grade.txt");
int numTrue = 0;
int numFalse = 0;
if(fileGrade.exists())fileGrade.delete();
while((line_e = br_e.readLine()) != null && (line_a = br_a.readLine()) != null){
if(!line_e.equals(line_a)){
ws.writeToFile("Grade.txt", line_e);
ws.writeToFile("Grade.txt", "\n");
// System.out.println(line_e);
numFalse++;
}else{
numTrue++;
}
}
br_e.close();
br_a.close();
String resultCheck = "一共做錯"+numFalse+"道,做對"+numTrue+"道。";
// System.out.println("共有"+num+"道錯題");
ws.writeToFile("Grade.txt", resultCheck);
}
}
寫入文件的IO 方法:
思路:為了保證程序多次運行時生成文件裏的內容會一直刷新,所以每次程序運行都會刪掉之前的文件,重新建立一個新的文件來存儲題目和答案。
package Com.software;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class WriteStringToFile {
public void writeToFile(String filePath,String string){
FileOutputStream fos = null;
try {
fos = new FileOutputStream(filePath,true);
} catch (FileNotFoundException e) {
// TODO 自動生成的 catch 塊
e.printStackTrace();
}
//true表示在文件末尾追加
try {
fos.write(string.getBytes());
// fos.write("\n".getBytes());
} catch (IOException e) {
// TODO 自動生成的 catch 塊
e.printStackTrace();
}
try {
fos.close();
} catch (IOException e) {
// TODO 自動生成的 catch 塊
e.printStackTrace();
}
}
}
6、測試運行:
控制臺輸入:
生成文件:
代碼覆蓋率:
7、PSP表格:
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | 10 | 5 |
· Estimate | · 估計這個任務需要多少時間 | 800 | 1200 |
Development | 開發 | 480 | 630 |
· Analysis | · 需求分析 (包括學習新技術) | 60 | 30 |
· Design Spec | · 生成設計文檔 | 60 | 80 |
· Design Review | · 設計復審 (和同事審核設計文檔) | 30 | 45 |
· Coding Standard | · 代碼規範 (為目前的開發制定合適的規範) | 30 | 30 |
· Design | · 具體設計 | 30 | 60 |
· Coding | · 具體編碼 | 120 | 360 |
· Code Review | · 代碼復審 | 30 | 45 |
· Test | · 測試(自我測試,修改代碼,提交修改) | 120 | 120 |
Reporting | 報告 | 120 | 120 |
· Test Report | · 測試報告 | 60 | 30 |
· Size Measurement | · 計算工作量 | 30 | 30 |
· Postmortem & Process Improvement Plan | · 事後總結, 並提出過程改進計劃 | 30 | 30 |
合計 | 1200 | 1610 |
8、項目小結:
? 這個項目最大的一個特點不是項目本身,而是項目的開發模式,結對編程是之前沒有接觸過的一種編程方式,也是以後工作可能會經常使用的一種開發模式。這次的項目與樂滔同學一起完成,分工方面樂滔同學完成了項目的四則表達式的生成部分(其中包含了對各種運算符的判斷問題以及括號的添加位置和結果的非負性保證)和答案的生成部分,我主要完成的是文件的IO讀寫操作(之前樂滔同學在寫的時候使用的控制臺輸出),以及最後的答案判斷問題。代碼數量方面樂滔同學編寫的代碼要遠遠大於我編寫的代碼數量。問題探討方面只要體現在對於四則表達式生成方法以及答案判斷正誤的部分,雙方各自表達了自己的觀點,每個人負責自己的部分,遇到的困難解決起來也就方便了很多。
Java實現四則運算---任路乾,樂滔