| GIT地址 | 我的GITHUB地址 |
|---|---|
| GIT用戶名 | NyimaC |
| 學號后五位 | 61111 |
| 博客地址 | 我的博客地址 |
| 作業鏈接 | 鏈接 |
Part1.環境配置
因為之前已經用JAVA寫過程序,所以環境是已經配好了的,在此沒有遇到太大的問題。
JAVA版本是JAVA8.0 編譯器使用的是IDEA



Part2.代碼編寫
編碼題目:
阿超家里的孩子上小學一年級了,這個暑假老師給家長們布置了一個作業:家長每天要給孩子出一些合理的,但要有些難度的四則運算題目,並且家長要對孩子的作業打分記錄。
作為程序員的阿超心想,既然每天都需要出題,那何不做一個可以自動生成小學四則運算題目與解決題目的命令行 “軟件”呢。他把老師的話翻譯一下,就形成了這個軟件的需求:
程序接收一個命令行參數 n,然后隨機產生 n 道加減乘除(分別使用符號+-*/來表示)練習題,每個數字在 0 和 100 之間,運算符在 2 個 到 3 個之間。
由於阿超的孩子才上一年級,並不知道分數。所以軟件所出的練習題在運算過程中不得出現非整數,比如不能出現 3÷5+2=2.6 這樣的算式。
練習題生成好后,將生成的 n 道練習題及其對應的正確答案輸出到一個文件 subject.txt 中。
使用語言:JAVA
與題目不同的地方的聲明:
1、運算符存在差異。題目上的是(+-*/) 我的是(+-×÷)
2、我的文件名為“題目.txt”
編碼思路:
思維導圖:

代碼部分(主要部分):
"Talk is cheap. Show me the code."
結構

生成題目的類
public class FormulaMakerTest {
/**
* 生成題目的類
*/
public LinkedList<String> questionMaker(int total)
{
//用於存放生成的運算式
String[] formulas = new String[total];
LinkedList<String> questionList = new LinkedList<>();
Numbers numbers = new Numbers();
OperationImpl operation = new OperationImpl();
OperationStringImpl operationString = new OperationStringImpl();
//循環開始的參數(一個用於外循環,一個用於循環)
int start1;
int start2;
//用於保存每次運算的結果
int result;
//用於標識運算是否會出現小數
int judge = 0;
for(start1=0; start1<total; start1++) {
//標識結果集的下標
//生成隨2~3個的運算符
numbers.operationNumber = (int)(2+Math.random()*(3-2+1));
//存放每次運算的結果集
//生成3~4個參與運算的數字
numbers.numbers = new Integer[numbers.operationNumber+1];
for(start2=0; start2<=numbers.operationNumber; start2++) {
numbers.numbers[start2] = (int)(0+Math.random()*(100-0+1));
}
//生成運算符
numbers.operations = new Integer[numbers.operationNumber];
for(start2=0; start2<numbers.operationNumber; start2++) {
numbers.operations[start2] = (int)(1+Math.random()*(4-1+1));
}
//運算此表達式的運算結果(重點)
//1、判斷此算式是否滿足條件(主要看除法是否滿足)
for(start2=0; start2<numbers.operationNumber; start2++){
if(numbers.operations[start2] == 4) {
if(!operation.judgeDivision(numbers.numbers[start2], numbers.numbers[start2+1])) {
//不滿足 重新生成算式
judge++;
}else {
continue;
}
}
}
//若滿足除法后無小數,則此算式成立
//算式中沒有小數,可以生成表達式並打印
if(judge == 0) {
//算式中沒有小數,可以生成表達式並打印
formulas[start1] = operationString.operationSplicing(numbers.operationNumber, numbers.numbers, numbers.operations);
System.out.println(formulas[start1]);
}else {
judge = 0;
start1--;
continue;
}
//調用計算函數計算結果
CalculateMaker maker = new CalculateMaker();
java.util.Queue<String> queue = new LinkedList<>();
queue = maker.calculateResult(numbers.numbers, numbers.operations);
result = maker.calculate(queue);
formulas[start1] += String.valueOf(result);
questionList.add(formulas[start1]);
}
return questionList;
}
}
棧進行四則運算的類
public class CalculateMaker {
/**
* 用於獲得后綴表達式
* @return
*/
public Queue<String> calculateResult(Integer[] num, Integer[] operations) {
//用於存放之前的算式
Queue<String> queue1 = new LinkedList<>();
//用於存放后綴表達式
Queue<String> queue2 = new LinkedList<>();
int i;
//把運算式放入隊列
for(i=0; i<num.length; i++) {
queue1.offer(String.valueOf(num[i]));
if(i<operations.length){
switch (operations[i]){
case 1:
queue1.add("+");
break;
case 2:
queue1.add("-");
break;
case 3:
queue1.add("×");
break;
case 4:
queue1.add("÷");
break;
default:
break;
}
}
}
//用於存放運算符
Stack<String> stack = new Stack<>();
//用於標注隊列中運算符的位置
i = 2;
while(!queue1.isEmpty()) {
//此位置是運算符
if(i%2==1) {
i++;
int num1, num2;
//把運算符放進去
if(stack.empty()) {
stack.push(queue1.poll());
}else {
//取隊首元素的值(用Unicode碼來判斷,加減號的值小於100,乘除號的值大於100)
num1 = Translate.translateToInt(queue1.poll());
if(num1<100) {
while (!stack.isEmpty()) {
queue2.offer(stack.pop());
}
stack.push(Translate.translateToString(num1));
}else {
num2 = Translate.translateToInt(stack.peek());
if(num2<100) {
stack.push(Translate.translateToString(num1));
}else {
queue2.offer(stack.pop());
if(stack.isEmpty()) {
stack.push(Translate.translateToString(num1));
}else {
while(!stack.isEmpty()) {
if(stack.isEmpty()) {
stack.push(Translate.translateToString(num1));
break;
}
num2 = Translate.translateToInt(stack.peek());
if(num2<100) {
stack.push(Translate.translateToString(num1));
break;
}else {
queue2.offer(stack.pop());
}
}
}
}
}
}
}else {
i++;
queue2.offer(queue1.poll());
if(queue1.isEmpty()){
while(!stack.isEmpty()) {
queue2.offer(stack.pop());
}
}
}
}
//打印后綴表達式並返回
return queue2;
}
/**
* 根據后綴表達式計算結果
* @param queue2
* @return
*/
public int calculate(Queue queue2) {
/**
* 用於進行后綴計算
*/
OperationImpl operation = new OperationImpl();
//保存計算結果
int x = 0;
int y = 0;
int result = 0;
Stack<String> stack = new Stack<>();
stack.push((String)queue2.poll());
while(!queue2.isEmpty()) {
String str = (String) queue2.poll();
//遇到運算符,出棧運算,結果入棧
if(!operation.judgeOperation(str)) {
stack.push(str);
}else {
y = Integer.valueOf(stack.pop());
x = Integer.valueOf(stack.pop());
result = operation.calculateNumber(x, y, str);
stack.push(String.valueOf(result));
//如果最終只有一個元素,則為計算的結果
if(stack.size() == 1 && queue2.isEmpty()) {
return Integer.valueOf(stack.pop());
}
}
}
return y;
}
}
主函數
public static void main(String[] args) {
//輸入想要的題目數
System.out.println("請輸入想要創建題目的數目:");
//生成題目的數目
Scanner scanner = new Scanner(System.in);
int total = scanner.nextInt();
//生成題目生成器
FormulaMakerTest maker = new FormulaMakerTest();
//題目集
LinkedList<String> questionList = maker.questionMaker(total);
System.out.println(questionList);
//將題目存入文件中
FileWriting writing = new FileWriting();
writing.WriteStringToFile(questionList);
}
控制台打印的題目

文件中保存的題目

Part3.使用github克隆項目以及提交代碼
下載與安裝
官網上下確實有點慢,找同學要的其他資源下的。


配置個人信息
指令:
git config --global user.name "用戶名"
git config --global user.email 郵箱
克隆項目
進入這里
點這里,復制這里的url


在Git的文件夾下創建一個新的文件夾,在新的文件夾內右鍵選擇Git Bash Here, 然后再在界面上輸入git clone + 剛才復制網址,即 https://github.com/Cherish599/AchaoCalculator


提交代碼
成功后便會多出一個文件夾,在里面創建一個和自己github用戶名一致的文件,將程序源碼放進去。


然后轉到AchaoCalculator文件目錄下(cd 文件的路徑)
然后輸入git add . , 再輸入git commit -m "分支名稱",最后輸入 輸入 git push,在這里會彈出框讓你輸入GitHub的用戶名和密碼即可

最后在GitHub上就能看到你提交的文件啦

遇到的問題
1、第一次接觸GitHub,大多是看着教程操作的,以后需要多多熟悉
2、很多指令不熟悉,有的教程上的地方我用起來會出現錯誤,在其他地方找了解決的辦法
Part4.單元測試
因為在編程過程中有很多需要單元測試的地方,也有很多bug需要及時修改,所以沒有細致的記錄,在此簡單的描述一下
JAVA的單元測試可以基於Junit,並需要在測試的方法前加上@Test注解且測試方法不能存在參數

同時也可以基於main()方法來測試,並在需要的地方輸出語句

主要遇到的問題
1、表達式的生成(字符串的拼接)出現錯誤。因為運算符是運用1~4的隨機數來保存的,所以生成算式時需要轉化為加減乘除對應的符號,思考后得以解決。
2、后綴表達式生成出現錯誤。因為對中綴表達式轉化為后綴表達式的理解還存在一些偏差。在仔細閱讀概念,並不斷得打印后綴表達式后,找出了代碼中出現的問題,最后得以解決
3、得到后綴表達式后計算結果出現錯誤。后綴表達式存在一個隊列中,隊列中元素的出隊,以及數字元素的壓棧、出棧操作出現問題。在條件語句中多次進行打印操作后,找出了錯誤出現的位置,找到原因,最終得以解決。
4、如果除法存在小數如何解決。我才用的方法是將此次循環作廢,即將循環因子的值減一,並不進行拼接操作。
Part5.回歸測試
單元測試時會存在許多問題,解決了這些問題,也就是進行了回歸測試,同樣在編程過程中有很多的回歸測試,所以沒有過多去記錄
這是進行單元測試后,再進行回歸測試才得出的判斷運算結果是否為小數的方法。

得出的判斷方法:看兩個整數相除后的結果與其強轉成浮點型后的結果是否一樣,一樣則是整數,反之則是小數
Part6.總結
說實話感覺這次作業還是很有難度的。主要是編寫代碼部分就需要大量的時間與精力。數據結構在學棧的部分學習過四則運算優先級判斷,但是當時沒有用代碼實現,所以還花時間去學習了一下。
學習Git的使用過程中,好在有很多文章可以參考,雖然陌生但是操作起來還是比較容易。
環境因為是以前就配好的,同時單元測試和回歸測試其實在代碼的編寫中以及有所使用了,這方面進行的還是比較順利。
總之這次作業還是讓我收獲頗豐,無論是對編程語言JAVA,還是數據結構中棧和隊列,以及Git的使用都得到了很好的練習
