OOP三次大作業(yè)總結(jié)-BLOG-1
面向?qū)ο蟪绦蛟O(shè)計三次大作業(yè)總結(jié)
一、前言。
第一次作業(yè)共有九道題目,都是考察Java的基礎(chǔ)語法,我認為是用來讓我們適應(yīng)從C語言到Java的轉(zhuǎn)變的(雖然我沒做全對),沒有運用上Java特色:類與對象;
第二次作業(yè)共四道題,隨著學習進度的前進,我們也迎來了對象和類的學習,第二次作業(yè)用上了對象和類,還有方法,相對難度大大增加。其中,7-1和7-2的菜單計價程序,滲透到了面向?qū)ο蟮倪^程,類和對象的使用以及方法的構(gòu)造等。主要難點在于:1.類的設(shè)計與使用:要根據(jù)題目要求設(shè)計出合適的類,每個類具有不同的屬性、方法及構(gòu)造方法,在程序中實例化這些類并調(diào)用其方法實現(xiàn)功能;2.字符串處理:輸入的菜名和份額信息需要通過字符串處理來提取和解析數(shù)據(jù),以便后續(xù)的計算和輸出;3.控制流語句:程序需要正確地選擇和執(zhí)行分支語句、循環(huán)語句和跳轉(zhuǎn)語句,以實現(xiàn)正確的用戶交互和求解過程。7-4的小明走格子,我怎么都過不了運行超時的坎,后來通過查閱資料,發(fā)現(xiàn)可以用字符流輸入(即一次只輸入一個字符)實現(xiàn)該題,可以通過調(diào)用Scanner類的next()方法從控制臺讀取下一個單詞,并將該字符串轉(zhuǎn)化為一個字符數(shù)組char[] input。然后將該字符數(shù)組作為參數(shù)傳遞給countWays方法,開始遞歸計算從起點到終點的所有走法總數(shù)。
第三次作業(yè)共七道題,第一題菜單我沒寫出來(冷汗冷汗),7-3去掉重復的數(shù)字運用了輸入緩沖流方法,使用Java中的Set集合來實現(xiàn)去重,以及使用StringBuilder來進行字符串的拼接。Set是Java集合框架中的一種數(shù)據(jù)結(jié)構(gòu),它是一個不包含重復元素的集合,需要注意的是,當元素存在重復時,Set會自動去重,因此最終的結(jié)果不會包含任何重復元素。這種去重方法也比較高效,尤其適用于對大量數(shù)據(jù)進行去重的情況。7-5面向?qū)ο缶幊蹋ǚ庋b性)則主要是對封裝性的理解(說實話挺難理解的)。
二、設(shè)計與分析。
三道菜單計價程序問題的設(shè)計與分析:
1.菜單計價程序-1
1)類圖:

2)題目:
某飯店提供4種菜,每種菜品的基礎(chǔ)價格如下:
西紅柿炒蛋 15
清炒土豆絲 12
麻婆豆腐 12
油淋生菜 9
設(shè)計點菜計價程序,根據(jù)輸入的訂單,計算并輸出總價格。
訂單由一條或多條點菜記錄組成,每條記錄一行,最后以"end"結(jié)束
每條點菜記錄包含:菜名、份額兩個信息。
份額可選項包括:1、2、3,分別代表小、中、大份)
不同份額菜價的計算方法:
小份菜的價格=菜品的基礎(chǔ)價格。
中份菜的價格=菜品的基礎(chǔ)價格1.5。
小份菜的價格=菜品的基礎(chǔ)價格2。
如果計算出現(xiàn)小數(shù),按四舍五入的規(guī)則進行處理。
3)分析:
Dish類:表示一個餐品,包括名字和單價等屬性。其中 getPrice(int portion) 方法用于根據(jù)不同的食物數(shù)量計算對應(yīng)的價格。
Menu類:表示菜單類,包括添加餐品,以及通過名稱查找餐品等方法。
Record類:表示一條記錄,即某個餐品和對應(yīng)的數(shù)量組成的記錄。其中 getPrice() 方法調(diào)用了 Dish 的 getPrice(int portion) 方法計算當前記錄的價格。
Order類:表示訂單類,包含記錄數(shù)組,可以根據(jù)輸入的餐品名稱、數(shù)量以及菜單信息創(chuàng)建新的 Record 對象,并將其加入到記錄數(shù)組中。同時,還提供了計算訂單總價的 getTotalPrice() 方法。
2.菜單計價程序-2
1)類圖:

2)題目:
設(shè)計點菜計價程序,根據(jù)輸入的信息,計算并輸出總價格。
輸入內(nèi)容按先后順序包括兩部分:菜單、訂單,最后以"end"結(jié)束。
菜單由一條或多條菜品記錄組成,每條記錄一行
每條菜品記錄包含:菜名、基礎(chǔ)價格 兩個信息。
訂單分:點菜記錄和刪除信息。每一類信息都可包含一條或多條記錄,每條記錄一行。
點菜記錄包含:序號、菜名、份額、份數(shù)。
份額可選項包括:1、2、3,分別代表小、中、大份。
刪除記錄格式:序號 delete
標識刪除對應(yīng)序號的那條點菜記錄。
不同份額菜價的計算方法:
小份菜的價格=菜品的基礎(chǔ)價格。
中份菜的價格=菜品的基礎(chǔ)價格1.5。
小份菜的價格=菜品的基礎(chǔ)價格2。
如果計算出現(xiàn)小數(shù),按四舍五入的規(guī)則進行處理。
3)分析:
Menu 類:此類負責管理菜單項,其中 addDish 方法可用于將新的餐品(具有名稱和價格)添加到菜單列表中。另外, findDishByName 方法可用于查找指定名稱的餐品。
Dish 類: 表示某一道菜品,包含了名稱、單價等基本屬性及操作方法。
Record 類:表示購物車中的一條記錄,即某個餐品和對應(yīng)數(shù)量組成的記錄。其中 price 方法用于計算當前條目的總價格。
Order 類:表示訂單,可以通過菜單和記錄列表來創(chuàng)建一個 Order 對象。addARecord 和 delARecordByOrderNum 兩個方法可用于添加或刪除錯誤的記錄。getTotalPrice 方法可用于獲取整個訂單的總價值。
3.菜單計價程序-3
1)類圖:

2)題目:
設(shè)計點菜計價程序,根據(jù)輸入的信息,計算并輸出總價格。
輸入內(nèi)容按先后順序包括兩部分:菜單、訂單,最后以"end"結(jié)束。
菜單由一條或多條菜品記錄組成,每條記錄一行
每條菜品記錄包含:菜名、基礎(chǔ)價格 兩個信息。
訂單分:桌號標識、點菜記錄和刪除信息、代點菜信息。每一類信息都可包含一條或多條記錄,每條記錄一行或多行。
桌號標識獨占一行,包含兩個信息:桌號、時間。
桌號以下的所有記錄都是本桌的記錄,直至下一個桌號標識。
點菜記錄包含:序號、菜名、份額、份數(shù)。份額可選項包括:1、2、3,分別代表小、中、大份。
不同份額菜價的計算方法:小份菜的價格=菜品的基礎(chǔ)價格。中份菜的價格=菜品的基礎(chǔ)價格1.5。小份菜的價格=菜品的基礎(chǔ)價格2。如果計算出現(xiàn)小數(shù),按四舍五入的規(guī)則進行處理。
刪除記錄格式:序號 delete
標識刪除對應(yīng)序號的那條點菜記錄。
如果序號不對,輸出"delete error"
代點菜信息包含:桌號 序號 菜品名稱 份額 分數(shù)
代點菜是當前桌為另外一桌點菜,信息中的桌號是另一桌的桌號,帶點菜的價格計算在當前這一桌。
程序最后按輸入的先后順序依次輸出每一桌的總價(注意:由于有代點菜的功能,總價不一定等于當前桌上的菜的價格之和)。
每桌的總價等于那一桌所有菜的價格之和乘以折扣。如存在小數(shù),按四舍五入規(guī)則計算,保留整數(shù)。
折扣的計算方法(注:以下時間段均按閉區(qū)間計算):
周一至周五營業(yè)時間與折扣:晚上(17:00-20:30)8折,周一至周五中午(10:30--14:30)6折,其余時間不營業(yè)。
周末全價,營業(yè)時間:9:30-21:30
如果下單時間不在營業(yè)范圍內(nèi),輸出"table " + t.tableNum + " out of opening hours"
3)分析:
代碼的主要功能是管理餐廳點餐、結(jié)賬以及生成報表。程序在輸入過程中通過 Scanner 類來獲取控制臺上的輸入信息,處理完成后將結(jié)果輸出到控制臺。
具體來說,該程序包含一個 Dish 類和一個 Table 類,Dish 類用于存儲菜品名稱和價格,而 Table 類用于存儲桌號、日期、時間和訂單信息等。程序主函數(shù)采用 while 循環(huán)來不斷讀取輸入,根據(jù)用戶輸入執(zhí)行相應(yīng)的操作,直到用戶輸入 end 或 table 命令結(jié)束程序。
程序主體部分主要實現(xiàn)了以下功能:
-
解析輸入并存儲菜品信息:整個程序最開始先解析用戶輸入得到菜名及其對應(yīng)的價格,并按輸入順序存儲到 dishes 數(shù)組中。
-
獲取輸入中的桌號、日期、時間等信息:程序從輸入中獲取桌號、日期、時間等信息,并存儲在 tables 數(shù)組中。
-
處理訂單:程序讀取用戶輸入中的“訂單編號-菜品名稱-份數(shù)-數(shù)量”信息,并按照特定的格式存儲在 order 數(shù)組中,同時計算每個訂單的總價并打印在控制臺上。
-
結(jié)賬:當用戶輸入 end 命令時,程序先遍歷所有 tables,統(tǒng)計其中的所有訂單價格總和,并輸出結(jié)賬信息。
三、采坑心得。
1.非法輸入:
第一次作業(yè)7-9二進制數(shù)值提取:

import java.util.*; import java.lang.*; public class Main{ public static void main(String[] args){ Scanner input = new Scanner(System.in); String str=input.nextLine(); int Len=str.length(); int Flag=0; for(int t=0;t<Len;t++) { if(str.charAt(t)=='-'&&str.charAt(t+1)=='1'){ Flag=1; break; } if(str.charAt(t)=='0'||str.charAt(t)=='1'){ System.out.print(str.charAt(t)); } } if(Flag==0){ System.out.println("Wrong Format"); } } }
這段代碼存在問題是:對于長度為1的字符串輸入時,訪問了后面一個字符。
當輸入長度僅為1的字符串時,在循環(huán)中判斷if(str.charAt(t)=='-'&&str.charAt(t+1)=='1')會訪問到字符串外面的內(nèi)存空間,會產(chǎn)生StringIndexOutOfBoundsException異常。可以添加if(Len==1) return;來避免這個問題。
2.運行超時:
第二次作業(yè)7-4小明走格子:

import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int m = scanner.nextInt(); while (m-- > 0) { int n = scanner.nextInt(); int[] dp = new int[n + 1]; dp[0] = 1; dp[1] = 1; if (n >= 2) { dp[2] = 2; } if (n >= 3) { dp[3] = 4; } for (int i = 4; i <= n; i++) { dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3] + dp[i - 4]; } System.out.println(dp[n]); } } }
在網(wǎng)上查閱的資料建議可以通過字符流輸入(BufferedReader),來提升輸入速度,從而減少運行時間;
還有的建議是使用滾動數(shù)組。因為dp[i]只與dp[i-1]、dp[i-2]、dp[i-3]、dp[i-4]有關(guān),所以可以將數(shù)組中的元素不斷往后移,并使用一個指針表示當前計算到的位置。這樣可以避免不必要的空間浪費,從而降低時間復雜度。
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int m = scanner.nextInt(); while (m-- > 0) { int n = scanner.nextInt(); int[] dp = new int[5]; dp[0] = 1; dp[1] = 1; if (n >= 2) { dp[2] = 2; } if (n >= 3) { dp[3] = 4; } int cur = 4; while(cur <= n){ int next = dp[3] + dp[2] + dp[1] + dp[0]; dp[0] = dp[1]; dp[1] = dp[2]; dp[2] = dp[3]; dp[3] = next; cur++; } System.out.println(dp[3]); } } }
使用滾動數(shù)組后,只需要記錄數(shù)組中最后四個元素,并隨著計算不斷往后更新,即可得到dp[n]的值。因此,在計算dp[i]時,只需要進行一次加法運算,而不需要再次訪問前面的數(shù)組元素,從而降低了時間復雜度,避免了超時的問題。
四、主要困難以及改進建議。
主要困難:
1.菜單計價程序需要維護菜品的名稱、價格、份數(shù)、總價等信息,需要建立相應(yīng)的數(shù)據(jù)模型來存儲和管理這些信息。如果數(shù)據(jù)模型設(shè)計不合理,會影響程序的可維護性、擴展性和性能。
2.在計算總價時,可能會出現(xiàn)精度丟失或者舍入誤差等問題,導致計算結(jié)果與實際結(jié)果存在差異。為了避免這個問題,程序需要使用適當?shù)臄?shù)據(jù)類型和算法,并進行精度控制和錯誤處理。
3.如果菜單計價程序需要支持多用戶并發(fā)操作,需要考慮多線程并發(fā)訪問帶來的數(shù)據(jù)一致性和安全性問題,并使用適當?shù)耐綑C制進行控制。
4.菜單計價程序可能涉及到多個相似的功能模塊,需要考慮代碼復用和重構(gòu)的問題,以提高代碼的重用性、可讀性和可維護性。這需要合理的設(shè)計架構(gòu)和代碼組織結(jié)構(gòu),并使用適當?shù)脑O(shè)計模式和最佳實踐。
五、總結(jié)。
一、對代碼:
對于Java代碼,我自身是帶有敬意的,因為C語言考試的不及格,多少對面向?qū)ο蟪绦蛟O(shè)計是抱有巨大的憂患意識的,所以在做作業(yè)的時候不敢怠慢。聽老師的話先在IDEA(老師說也可以在eclipse)里先寫好再復制粘貼到PTA里,我也聽說了一些同學直接在PTA里寫,(邏輯,運行等)錯誤百出,浪費了很多時間。雖然真的學得特別吃力,但我會認真聽老師講課,去看別人寫的代碼,看別人下很大功夫才想出來的設(shè)計和算法。
二、對自己:
只能說盡力去學吧,Java本身就是一個十分龐大的東西,不能全指望老師上課講的那些語法,還要去找資源,自己去B站找視頻看。也是聽取了厲害大佬的建議:時刻提醒自己這門專業(yè)本身就不是以學習語法為重點。處理問題時一頭扎進問題中,忽略其他細節(jié),在錯誤的方向上瘋狂進發(fā),然后寫出來一堆沒意義的代碼,為了避免這種情況發(fā)生,老師講到的東西一定要注意,老師上課講的某些點很不經(jīng)意,但都是他這么多年寫代碼總結(jié)出來的經(jīng)驗,認真學吧,總有些收獲!!!
三、對教師:
我的面向?qū)ο蟪绦蛟O(shè)計老師是羅老師,對我們很認真負責,上課也是一本正經(jīng)地上,我只能說在他的課上有種回到高中的感覺……
四、對這門課:
個人認為這種形式還不錯,課上老師輸出大波干貨,課下自己自行摸索,也有同學老師之間的交流協(xié)作過程,雖然這樣挺辛苦,但吃得苦中苦方為人上人嘛
還有就是這門課的考查方式,不是像上學期C語言那樣手寫代碼,而是真正地在筆記本上敲代碼,考察編程能力,真的是泰褲辣!
浙公網(wǎng)安備 33010602011771號