1. 程式人生 > 實用技巧 >Invalid byte tag in constant pool: 19

Invalid byte tag in constant pool: 19

此作業要求參見:https://edu.cnblogs.com/campus/nenu/2020Fall/homework/11245

結對夥伴:花名(朱航序)

倉庫地址:


國慶節你去探望初中數學老師,她感嘆你當年真是個優秀學生啊,從來不報怨作業多,然後關切地問,“你現在學啥呢?”你說學計算機呢,她要求你舉個例子證明你學的知識有用。你的回答她一直不懂。

你回家後連夜編了個程式,展示你的水平。程式準備幫助她給初中生出四則運算題目,學生答題後,自動判斷對錯。你第二天去找老師獻寶。

功能1. 四則運算

支援出題4個數的四則運算題目,所有題目要求作者有能力正確回答 (提示:1/3 != 0.33333333333333333333333333333333,而是無限長)。

為了快出成果,你快速造個控制檯的版本,包括以後改版成更優秀介面的核心功能,並考慮到擴充套件。

你在老師面前作如下表演 (數字你用excel驗算過了,UI的賣萌部分你還沒有想好) 。

> f4
1+2*3+4=
?11
答對啦,你真是個天才!
1+2*3+5=
?11
再想想吧,答案似乎是12喔!
1+2/4-5=
?-3.5
答對啦,你真是個天才!
...(一共20道題)

你一共答對4道題,共20道題。

功能2. 支援括號

老師看了你的表演,大大讚賞了你。然後她說,"你的題庫裡怎麼都是沒有括號的題呢,我記得你當初括號就掌握得不好啊。"你的臉紅了,對老師說,"給我2個小時時間,我給你一個新版本,有括號的。"

你拿出筆記本,偷偷微信你們《構建之法》班的學霸,她說肯定能行,但是細節訊號不好你聽不清,只捕捉到隱約幾個詞"逆波蘭""字尾表示式""堆疊""我看好你""資料結構"。

兩小時後,在老師面前你在控制檯下輸入f4,然後回車。

> f4
1+2*(3+4)=
?15
答對啦,你真是個天才!
(1+2)*3+5=
?11
再想想吧,答案似乎是14喔!
((1/2)-4)*5=
?-17.5
答對啦,你真是個天才!
...(一共20道題)

你一共答對4道題,共20道題。

功能3. 限定題目數量,"精美"列印輸出,避免重複

"就這點兒題,像你當年做得那麼快,一會兒就完成啦!"老師說,"另外,我想打印出來,上課也不能帶臺機器。又另外,你把答案也打出來唄,我把答案剪掉,題目給學生做。"

一看需求這麼多,你生怕她會說,"這都是很簡單的功能,你一定能完成吧"。你知道如果承諾今晚,明早交工的時候她一定想出了更多可怕的需求,你趕緊說,"老師我現在就做。"

你忘記怎麼呼叫印表機了,就把答案與題目橫向對齊,輸出在檔案的右邊。告訴老師txt檔案可以用WORD開啟,也能列印。她滿意而意味深長地笑了,表示同意。

你輸入命令執行的時候,腦袋比手指頭還疼。

>f4 -c 3
1+2*(3+4)=                     15
(1+2)*3+5=                     14
((1/2)-4)*5=                   17.5

你指著螢幕對老師說,">"是提示符,實際執行時可能是"C:\Users\Young>","f4"是程式的名字,它真正的名字是"f4.exe","-c 3"是命令列引數。按下回車,此時程式開始執行。"-c"這個引數後面輸入多少,就生成多少題目。老師輸入

>f4 -c -200
題目數量必須是 正整數。
>f4 -c 3.5
題目數量必須是 正整數。
>f4 -c test
題目數量必須是 正整數。

老師欣慰的笑了。你怔怔地看著她,心下懷疑她真的是教初中數學的那位麼。

老師在你的指導下試用了一下,打印出來的題目堪稱精美。老師讓你做一次試試看能得多少分。你不敢借口四則運算忘光了,只好提起笑來開始答。剛做一半,你發現有幾道題目是相同的,心中暗罵隨機數不靠譜。又有幾道雖然不完全相同,但是可以通過交換律、結合律、分配律變換為同一道題。比如

1*2+3*2
2*(1+3)+0

你暗叫慚愧,說有個小錯誤修正一下,除錯了半晌,終於解決。

功能4. 支援分數出題和運算

國慶節後,你終於又回到美麗優雅並且正常的東北師範大學淨月校區,在去食堂的路上偶遇你心目中的女神 (或男神,請自行替換)。她說,"哎呀,這跟我們《構建之法》課上的題目要求一樣啊,真是巧合。"

"不要客氣,程式碼拿去!反正我也沒用。"你說,"如果有需求變更或擴充套件,儘管找我。"

你伏筆埋得不錯。女神馬上說,"對啊,有一點兒點兒不一樣,你午飯時間加加班幫我改出來吧。"

她的題目還要求支援分數運算,你不禁想到了功能1中你特意規避了一些題目不出。她想要的是下面的樣子:

>f4 -c 3
1/3+2/3+1+1=                   3
1/2+2/3+1+2=                   4 1/6
7/5+3/4*2-3                    -1/10

你想到越難的題目就越能表現你的能力,欣然應允了,轉身跑向實驗室,路上就開始給師兄打電話。背後傳來女神的聲音,"提示1:別忘了約分。提示2:帶分數,即 一又二分之一 表示 1 1/2。"

完成這個功能,女神對你的青睞+200。

這個題目太難了,接電話的師兄說他一點思路也沒有。你提出有好酒肉一頓,他幽幽地說,又回憶起點什麼,傳說去年還是前年有位姓張的大神完成了,如果你求助於他或他的部落格 (但不是抄襲,而是學習後獨立實現) ,請主動說明,女神的青睞改為+150。他還回憶道,有本神書縮寫名為SICP,中文名《計算機程式的構造和解釋》第2.1.1節 例項:有理數算術運算,就是以此為例,不過,是scheme語言的,他也沒有聽說過。參考此書,請主動說明,女神的青睞改為+180。

(在你的心中,女神的要求並不像昔日的老師那麼重要。此題選作,不完成此題不倒扣分。)

功能5 未來

還有可能把程式改造成GUI版,把程式改造為web版,把程式移植為android/ios版。今天留好介面,明天就不發愁。 (0分)

要求1 參考《構建之法》第4章兩人合作,結對程式設計上述功能,要求每人釋出隨筆1篇 (程式碼是共同完成的,隨筆有以下兩種方式:(①允許兩人寫一份,得一份分數,二人均分;②如果每人寫一份,內容不得抄襲,體會需要是自己的,分別得到自己部落格的分數)。 (1) 給出每個功能的重點、難點、程式設計收穫。(2)給出結對程式設計的體會,以及 (3) 至少5項在編碼、爭論、複審等活動中花費時間較長,給你較大收穫的事件。 (10分)

要求2 給出結對開發的截圖證據,要求截圖能夠證明你們是在結對程式設計。 (5分)

要求3 使用coding.net做版本控制。checkin 前要求清理 臨時檔案、可執行程式,通常執行 build-clean可以達到效果。(25分)

雖然只有5分,但此題如果做錯,因為教師得不到你的程式碼,所以會導致“功能實現”為負分。
程式碼要求在 coding.net 做版本控制。要求push&pull時使用git客戶端,不允許使用web頁面。
要求頻繁checkin。要求在PSP中記錄的每次離開鍵盤30分鐘以上,需要checkin。如果你持續長達4小時不離開鍵盤,教師要求展示此項能力。量化的可考核的指標要求: 每個功能,要求有4次以上 checkin,展示(1)逐步實現功能和(2)修復bug時的過程; 每次checkin都要求可以成功編譯。
推薦git客戶端tortoisgit。


題目要求隨機生成4個數的帶括號的四則運算,並計算其結果。我們沒有采用常用的逆波蘭表示式來計算,而是採用深度為2的滿二叉樹來生成和計算四則運算。

二叉樹的葉子結點儲存數字,父節點用來儲存運算子。中序遍歷的結果(1*2+3/4)就是四則運算的式子。當父節點返回的時候對運算式進行計算。

父節點返回的時候將左右括號帶上,這樣四則運算就帶括號了。

生成四則運算主要程式碼:

public void createBTree() {
    TreeNode lchild, rchild, lnode, rnode;
    if (num == 1) {
        lchild = new TreeNode(String.valueOf(Utils.getNumber(10)), null, null);
        rchild = new TreeNode(String.valueOf(Utils.getNumber(10)), null, null);
        root = new TreeNode(String.valueOf(Utils.getOperator()), lchild, rchild);
    } else {
        int num1 = 0;
        int n = getDeep() - 3;
        boolean[] place = Utils.getChildPlace(num);
        root = new TreeNode(String.valueOf(Utils.getOperator()), null, null);
        opeList.add(root);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < (int) Math.pow(2, i); j++, num1++) {
                lchild = new TreeNode(String.valueOf(Utils.getOperator()), null, null);
                rchild = new TreeNode(String.valueOf(Utils.getOperator()), null, null);
                opeList.get(j + num1).setChild(lchild, rchild);
                opeList.add(lchild);
                opeList.add(rchild);
            }
        }
        for (int i = 0; i < place.length; i++) {
            if (place[i]) {
                lnode = new TreeNode(String.valueOf(Utils.getNumber(10)), null, null);
                rnode = new TreeNode(String.valueOf(Utils.getNumber(10)), null, null);
                if (i % 2 == 0) {
                    lchild = new TreeNode(String.valueOf(Utils.getOperator()), lnode, rnode);
                    opeList.add(lchild);
                    opeList.get(num1).setLchild(lchild);
                } else {
                    rchild = new TreeNode(String.valueOf(Utils.getOperator()), lnode, rnode);
                    opeList.add(rchild);
                    opeList.get(num1).setRchild(rchild);
                }
            } else {
                if (i % 2 == 0) {
                    lchild = new TreeNode(String.valueOf(Utils.getNumber(10)), null, null);
                    opeList.get(num1).setLchild(lchild);
                } else {
                    rchild = new TreeNode(String.valueOf(Utils.getNumber(10)), null, null);
                    opeList.get(num1).setRchild(rchild);
                }
            }
            num1 = num1 + i % 2;
        }
    }
}

計算主要程式碼:

public String getResult() {
    if (hasChild()) {
        switch (str) {
            case "+":
                return String.valueOf(Integer.parseInt(getLchild().getResult()) + Integer.parseInt(getRchild().getResult()));
            case "-":
                return String.valueOf(Integer.parseInt(getLchild().getResult()) - Integer.parseInt(getRchild().getResult()));
            case "*":
                return String.valueOf(Integer.parseInt(getLchild().getResult()) * Integer.parseInt(getRchild().getResult()));
            case "/":
                if (getRchild().getResult().equals("0")) {
                    while (str.equals("/")) {
                        str = String.valueOf(Utils.getOperator());
                    }
                    return this.getResult();
                } else if (Integer.parseInt(getLchild().getResult()) % Integer.parseInt(getRchild().getResult()) != 0) {
                    while (str.equals("/")) {
                        str = String.valueOf(Utils.getOperator());
                    }
                    return this.getResult();
                } else
                    return String.valueOf(Integer.parseInt(getLchild().getResult()) / Integer.parseInt(getRchild().getResult()));
        }
    }
    return str;
}

功能一和功能二執行截圖:

功能三執行截圖:


功能一難點:二叉樹的生成和父節點的運算

功能二的難點:中序遍歷二叉樹,返回父節點是帶上左右括號

功能三難點:對命令列引數進行判斷,檔案格式化輸出

程式設計收穫:複習了二叉樹的知識點,複習了檔案格式化輸出,對面對物件程式設計有了更深的理解

結對程式設計體會:

  • 程式設計思路:1+1>2,兩個人一起想問題比一個人快很多
  • 兩個人找bug效率很高,更容易找到對方寫的bug
  • 思想碰撞使人進步,以後要多進行技術上的交流