OO面向對象課程作業1-3總結

来源:https://www.cnblogs.com/zackerzhuang/archive/2018/04/03/8710555.html
-Advertisement-
Play Games

作業一、多項式的加減運算 1、設計要點與自我分析 我設計的類圖 老師建議類圖 我設計了兩個類來進行多項式的計算,類Polynomial進行多項式的存儲和輸入輸出,第二個類進行多項式加減運算。而加減運算的類裡面只有方法,而且都是靜態方法,沒有存儲變數,感覺這個設計還是有些問題。之後我也參考了一下別人的 ...


作業一、多項式的加減運算

1、設計要點與自我分析

我設計的類圖

複雜度分析圖

老師建議類圖

我設計了兩個類來進行多項式的計算,類Polynomial進行多項式的存儲和輸入輸出,第二個類進行多項式加減運算。而加減運算的類裡面只有方法,而且都是靜態方法,沒有存儲變數,感覺這個設計還是有些問題。之後我也參考了一下別人的代碼。

在Method Metrics中可以看到ev, iv, v這三欄,分別代指基本複雜度(Essential Complexity (ev(G))、模塊設計複雜度(Module Design Complexity (iv(G)))、Cyclomatic Complexity (v(G))圈複雜度。
ev(G)基本複雜度是用來衡量程式非結構化程度的,非結構成分降低了程式的質量,增加了代碼的維護難度,使程式難於理解。因此,基本複雜度高意味著非結構化程度高,難以模塊化和維護。實際上,消除了一個錯誤有時會引起其他的錯誤。
Iv(G)模塊設計複雜度是用來衡量模塊判定結構,即模塊和其他模塊的調用關係。軟體模塊設計複雜度高意味模塊耦合度高,這將導致模塊難於隔離、維護和復用。模塊設計複雜度是從模塊流程圖中移去那些不包含調用子模塊的判定和迴圈結構後得出的圈複雜度,因此模塊設計複雜度不能大於圈複雜度,通常是遠小於圈複雜度。
v(G)是用來衡量一個模塊判定結構的複雜程度,數量上表現為獨立路徑的條數,即合理的預防錯誤所需測試的最少路徑條數,圈複雜度大說明程式代碼可能質量低且難於測試和維護,經驗表明,程式的可能錯誤和高的圈複雜度有著很大關係。
Class metrics中兩欄分別為Ocavg(Average Operation Complexity)和WMC(Weighed method complexity)
在main函數中,我的基本複雜度較大較大,我定義了一個output的函數方法用於輸出結果,不過模塊化程度還算可以。

  • 多項式的存儲:
    我用的是一維數組來存儲多項式,下標代表的是多項式的次數,數組存儲的是多項式的繫數,這種存儲方法對於多項式加減法的操作很方便,但是浪費的空間大,因為很多繫數是0;而且存儲多項式加減式子的時候也開了大數組將所有數據裝進去,一次性進行計算,這樣也浪費了大量的空間。
    參考了大佬的代碼,學習了一下如何管理多項式的存儲和加減:

1、專門設出一個類來存多項式的每一項,包括繫數和次數,然後開一個ArrayList<Object>來存儲這個類。

2、加減法操作,將所有項加入到原來的ArrayList裡面,然後在ArrayList裡面對指數相同的項進行合併操作,再進行對指數從小到大的排序,用了sort()函數。

2、所用知識

1. 去除空白字元
s = s.replaceAll("\\s*", "");
2. 正則表達式的使用

1、使用group()捕獲組:

捕獲組是把多個字元當一個單獨單元進行處理的方法,它通過對括弧內的字元分組來創建。group(0)代表的是整個匹配的表達式,之後每遇到一個左括弧,group的索引值加一。

  • public String group( )

返回上次匹配操作(比方說find( ))的group 0(整個匹配)

  • public String group(int i)

返回上次匹配操作的某個group。如果匹配成功,但是沒能找到group,則返回null。

2、非貪婪匹配:

當“ ?”字元緊隨任何其他限定符(*、+、?、{n}、{n,}、{n,m}之後時,匹配模式是"非貪心的"。"非貪心的"模式匹配搜索到的、儘可能短的字元串,而預設的"貪心的"模式匹配搜索到的、儘可能長的字元串。

*、+限定符都是貪婪的,因為它們會儘可能多的匹配文字,只有在它們的後面加上一個?就可以實現非貪婪或最小匹配。

3、判斷兩個字元串內容是否相等

需要用str.equals()的方法判斷,而不能使用“==”號。

4、錯誤的捕捉,使用try-catch和throw

try{
                ... ...
        }catch(IOException e){
            //處理IO異常的代碼
        }catch(NumberFormatException e){
            //處理parseInt不能轉換時的異常代碼
        }catch(StringIndexOutOfBoundsException e){
            //處理數組越界的異常代碼
        }catch(Exception e) {
            //總異常(父類)
        } 

也可以自定義異常,如果不滿足某項條件則拋出異常

if(!m.find()){
    throw new PolynomialError();
}

5、結束進程
System.exit(0);

6、可以重寫toString()的方法返回多項式的值。

3、遇見BUG以及改正方法

1、正則表達式太長,在數據壓力大的時候可能會爆棧
我將整個多項式加減法的式子用正則表達式一次性匹配檢查格式是否正確,但由於表達式太長,數據壓力大而爆棧。應該逐個多項式進行匹配,逐個向後查找。

2、繫數相加的時候容易超出範圍

使用java異常處理語句進行異常的捕捉

3、輸出多項式的時候沒有判斷是否是輸出第一個大括弧,導致前面出現逗號。

加入第一次進入輸出迴圈的判斷。

4、在本題目的多項式匹配當中,可使用 **(^|\\+|-)(\\{.*?\\})**來匹配其中加減的操作項。

但是如果兩個加減項之間出現了非法字元,正則表達式會自動跳過非法字元去匹配下一項,要怎麼解決這個問題呢?我想到三種方法:

(1)將匹配成功的字元串刪除以後,用^從頭開始匹配。代碼如下:

    String pattern = "^(^|\\+|-)(\\{.*?\\})";
    Pattern r = Pattern.compile(pattern);       
    Matcher m = r.matcher(line); 
    while (m.find()) { 
        System.out.println("Found value: " + m.group()); 
        line = line.replace(m.group(),"");
        m = r.matcher(line); 
    }

(2)每次記錄匹配字元串的長度,然後依次累加,如果發現累加得到的字元串長度和讀到的m.start(0)索引值不一致,則中間有非法字元。
(3)用region(start,end)重設m的範圍。

4、Eclipse的使用總結

1. 導入工程
  • 設置工作空間(Workspace)有明顯的層次結構。 項目在最頂級,項目裡頭可以有文件和文件夾。插件可以通過資源插件提供的API來管理工作空間的資源。

  • 首先打開eclipse軟體,找到左上角File然後點擊,然後我們選擇Import,點擊Import

  • 點擊Import後,會彈出Import視窗,然後找到General,點擊General左邊小三角,然後選擇Existing Projects into Workspace

  • 有時候點導入文件會出現提示

Project is not a Java project.

有幾種情況:

  • package名字不相符:右鍵項目->Build Path來更改source folder的設置

  • eclipse 工程沒有build path,則在項目.project文件中添加

    <buildSpec>
    <buildCommand>
    <name>org.eclipse.jdt.core.javabuilder</name>
    <arguments>
    </arguments>
    </buildCommand>
    </buildSpec>
    <natures>
    <nature>org.eclipse.jdt.core.javanature</nature>
    </natures>
  • JDK版本不對: 項目右鍵 -->properties-->Java Build Path-->Libraries 然後將JDK換成你當前的JDK版本
2、修改字元集

預設情況下 Eclipse 字元集為 GBK,但現在很多項目採用的是 UTF-8,這是我們就需要設置我們的 Eclipse 開發環境字元集為 UTF-8, 設置步驟如下:

在菜單欄選擇Window -> Preferences -> General -> Workspace -> Text file encoding ,在 Text file encoding 中點擊 Other,選擇 UTF-8。

3、調試快捷鍵

F11――進入DEBUG視圖

F5——進入:移動到下一個步驟,如果當前行有一個方法調用,該控制項將會跳轉到被調用方法的第一行執行。

F6——跳出:移動到下一行。如果在當前行有方法調用,那麼會直接移動到下一行執行。不會進入被調用方法體裡面。

F7——返回:從當前方法中跳出,繼續往下執行。

F8——移動到下一個斷點處執行。

作業二、電梯的簡單調度

1、設計要點與自我分析

邏輯結構圖:

類圖:

設計建議類圖:

複雜度分析圖:

本次作業的設計要點是多個類進行協同,同時使用隊列進行調度。我將請求加入到請求隊列當中,由調度器從請求隊列中讀取請求對電梯類進行調度和操作,樓層類我沒有實際用上,這也是設計上的不均衡。其他幾個類職責比較分明,調度邏輯清晰。
可以看到我的RequestQueue類的複雜度較高,因為我在裡面大量用if語句來判斷出現的不同格式錯誤來輸出錯誤提示,導致複雜度升高。

2、所用知識

LinkedList的使用,由於本電梯使用的是隊列的結構,使用瞭如下幾種方法:

(1)q.offer(e) 在鏈表尾部插入元素

(2)q.peek() 獲取第一個元素

(3)q.remove(e) 刪除一個元素

(4)q.poll(e) 查詢並移除第一個元素

(5)遍歷鏈表:

//for迴圈遍歷
for(int i = 0; i < linkedList.size(); i++){
    linkedList.get(i);
}
//Foreach遍歷
for(Integer i : linkedList);
//迭代器遍歷
Iterator<Integer> iterator = linkedList.iterator();
while(iterator.hasNext()){
    iterator.next();
}

但是迭代器遍歷和foreach遍歷的時候因為是動態刪除鏈表會發生線程錯誤,所以我用了for迴圈遍歷。

3、遇見BUG以及改正方法

我使用了LinkedList()來存儲請求,每次執行一次請求會遍歷鏈表看看有沒有同質請求,有的話進行刪除。但是刪除以後鏈表的總長度會改變,所以刪除以後要將索引值減一。在debug的過程中找出了這個錯誤,後來在公測的時候順利通過了。

我測試的同學沒有用正則表達式,全部用if-else判斷,程式容錯能力過差,導致公測全部沒有過。

作業三、具有捎帶功能的電梯調度

1、設計要點與自我分析

  • 提高資源利用率是調度演算法設計的核心目標
  • “順路捎帶”:在去響應一個請求的路途中可以把資源共用給順路可完成的請求

類圖:

複雜度分析:

老師推薦設計:

在第二次作業的基礎上,我用Scheduler類繼承了Dispatcher類,創建了電梯移動的介面。
我順路捎帶的思路是找到主請求,然後遍歷隊列後面可以被捎帶的請求,找到離主請求最近的請求執行,若超出主請求的執行時間,便執行主請求,然後選擇捎帶的第一條消息作為主請求。但是這個設計思路遇到了很多問題,後來參考了別人的思路。可以將每次所能找到捎帶方向上的最高樓層作為目標樓層,然後停靠中間的樓層,這樣的思路簡潔清晰,也省去了很多判斷的步驟。
可以看到我的Scheduler類複雜度十分高,因為我思路的問題,導致在這個類裡面有很多判斷條件的語句,整個程式十分冗雜。

2、所用知識

(1)類的繼承
使用繼承機制,增加一個子類來重寫第二次作業中的schedule方法,需要註意子類不能繼承父類的構造器,但是父類的構造器帶有參數的,則必須在子類的構造器中顯式地通過super關鍵字調用父類的構造器並配以適當的參數列表。 如果父類有無參構造器,則在子類的構造器中用super調用父類構造器不是必須的,如果沒有使用super關鍵字,系統會自動調用父類的無參構造器。
(2)使用interface來歸納電梯的運動方法。
(3)重寫toString()方法來獲得電梯運行狀態和時刻的觀察。

3、遇見BUG以及改正方法

在這次的作業中,由於我每次都是找到可捎帶請求的最小請求,但是在主請求更換的時候,我將主請求設為了可捎帶的最小請求,而可捎帶的最小請求在前一條捎帶請求的後面發出,這就造成了後發出的指令先執行了。參考了其他同學的捎帶思路,即找到當前方向上可捎帶的最高樓層進行停靠,可以簡化此問題。
其次就是輸出錯誤格式的問題,INVALID的輸出的是原請求,而我將請求的括弧換掉了,導致很多bug。

測試策略

一開始我是根據錯誤分支樹來構造測試用例,後來的作業中,我根據別人的代碼結構來構造測試用例,發現代碼中的邏輯錯誤和bug。

心得體會

作為剛接觸面向對象的小白,第一次作業佈置下來,就開始兩天速成Java,正則表達式,很多資料看得一臉懵逼,期間總是去打擾大佬,問一些十分基礎的問題。但在後面兩次作業中,對整個編寫流程開始熟練起來,也開始理解面向對象的編程思想。每次作業做完以後,也會參考一下別人的代碼,和自己的做一下對比,看看那些地方能更加簡潔的表達,更高效的處理,同時也感謝能將代碼分享給我的同學~
還有就是一定要仔細閱讀指導書,我就是因為指導書沒有好好看,導致程式出了很多bug,第一次作業由於輸出提示沒有#提示,掛滿了錯誤分支樹,可以說還是很絕望的。第三次的指導書和第二次的差不多,我又很粗淺地看了,差點漏掉了重要信息,第一條指令有限制。後來是在看討論區的討論才發現了這個問題。
前期的邏輯結構設計一定要清晰,否則無腦開始寫代碼真的會遇到特別多問題。
轉系之後感覺自己真的特別菜,改bug經常改到絕望,但還是真心感謝一些能夠和我交流的小伙伴。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • pylint是VScode中python自帶的插件,可以幫助代碼規範,美觀。 但是有些報錯是你不想看到的,你可以選擇性的忽略。 例如,在re.compile()中,可以添加參數 使`.` 匹配任意字元。而pylint會一直報錯不存在這種方法,導致無法運行。在Pycharm中則不會出現這種問題。 想要 ...
  • 上一節課給大家講了Python的數值和字元串 在編寫程式的過程中,經常會遇到使用很多數據量的情況,處理每一個數據量都要有一個相對應的變數,如果每一個變數都要單獨進行定義則很繁瑣,使用列表就可以解決這種問題 Python的數值類型List,也就是列表 Python的列表比較類似與其他語言的數組概念,但 ...
  • 枚舉 蘋果官方文檔 "枚舉" 蘋果官方文檔中文翻譯 "枚舉" 枚舉語法 使用Switch語句來匹配枚舉值 如果不能為所有枚舉成員都提供一個 case,那你也可以提供一個==default==情況來包含那些不能被明確寫出的成員: 關聯值 如果對於一個枚舉成員的所有的相關值都被提取為常量,或如果都被提取 ...
  • Python Copy: 在Python語言中,分為淺拷貝和深拷貝兩種形式,也就是官方文檔中的Shadow copy和Deep copy。在對簡單的對象(object)進行複製時,兩者沒有區別,如下麵的代碼所示: 從簡單對象的淺copy和深copy可以看出,對原列表中的元素進行修改,copy的對象里 ...
  • Description L公司有N個工廠,由高到底分佈在一座山上。如圖所示,工廠1在山頂,工廠N在山腳。由於這座山處於高原內陸地區(乾燥少雨),L公司一般把產品直接堆放在露天,以節省費用。突然有一天,L公司的總裁L先生接到氣象部門的電話,被告知三天之後將有一場暴雨,於是L先生決定緊急在某些工廠建立一 ...
  • 一、Python語言的特性: 1.與C語言不通,Python語言是一門解釋性語言。程式在執行過程中,執行一步、編譯一步。 2.Python是一個動態類型語言,不需要定義變數的數據類型。 3.Python是一門強類型語言。(如果定義了一個變數,如果不人為的強制類型轉換,它永遠都是開始的那種數據類型) ...
  • 在Mybatis深入學習的一周中,總感覺跟著師傅的視屏講解什麼都能懂,但實際自己操作的時候才發現自己一臉懵逼,不知道從何入手。但還好自己做了點筆記。在此記錄一下自己淺度學習Mybatis遇到幾個小問題。 1.個人感覺學習Mybatis過程中最好使用log4j 日誌文件,這樣在你自己測試代碼的時候,能 ...
  • Android類載入機制 Dalvik虛擬機如同其他Java虛擬機一樣,在運行程式時首先需要將對應的類載入到記憶體中。而在Java標準的虛擬機中,類載入可以從class文件中讀取,也可以是其他形式的二進位流。因此,我們常常利用這一點,在程式運行時手動載入Class,從而達到代碼動態載入執行的目的。只不 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...