1042 C++ 程式作業四:
        資料匣與檔案系統設計

說明

這個作業希望大家模擬設計一個簡單的資料匣與檔案管理程式, 假設操作者在一個資料匣中可以存放多個資料檔案(每一個檔案有檔案名稱和檔案內容), 可以對這些儲存下來的資料做一些基本的處理。基本的功能類似檔案系統介面的操作與管理, 可以新增檔案, 可以新增資料匣, 可以搜尋檔案名稱, 可以搜尋檔案內容, 可以刪除檔案與資料匣

範例執行程式 FileDirectory.exe, 資料檔案 prog4a.in, 下載後可以直接透過鍵盤交談式執行,也可以在 cmd.exe 命令視窗中輸入

直接執行資料檔案 prog4a.in 中的命令, 程式結束後會將所建立的資料匣及檔案架構存檔, 下次執行會直接由內定的檔案中讀入

作業目標:

  1. 練習以 C++ 語法實作指定的類別架構 (包括繼承與組合)

  2. 練習物件間的分工合作 (封裝與委託)

  3. 練習序列化 (Serialization) 讀取檔案與寫入檔案

  4. 練習 iostream 中基本的鍵盤輸入與螢幕輸出

  5. 練習使用 string 與 vector 等等基本的標準函式庫裡的樣板類別

  6. 練習覆蓋 (overriding) 基礎類別中的虛擬函式

  7. 練習使用多型指標

  8. 練習使用異質容器

  9. 實習 Quiz#3 中直覺的類別架構比較

程式要求

  1. 程式功能要求如下:

    1. 可以在階層式的資料匣中移動 (使用者在操作時有一個目前資料匣的狀態)

    2. 新增檔案: 輸入資料檔案的名稱和資料檔案的內容(假設只有一列文字資料), 在一個資料匣中不可以有兩個相同檔案名稱的檔案/資料匣

    3. 新增資料匣: 輸入資料匣的名稱, 在一個資料匣中不可以有兩個相同名稱的子資料匣/檔案

    4. 刪除指定名稱的檔案

    5. 刪除指定名稱的資料匣以及所有下層的檔案和子資料匣

    6. 允許使用者查詢目前資料匣中有哪些檔案與子資料匣

    7. 允許使用者查詢目前資料匣及子資料匣中有哪些檔案與子資料匣

    8. 允許使用者查詢某一個指定檔案的內容

    9. 允許使用者以檔案名稱搜尋第一個具有指定名稱的檔案或資料匣

    10. 允許使用者以檔案內容的關鍵字串搜尋第一個包括此字串的檔案

    11. 計算檔案大小或是資料匣內所有檔案的大小總和

    12. 程式結束時自動將所有物件的狀態儲存在檔案裡

    13. 程式開始時自動由檔案中讀入上一次執行時各個物件的狀態: 請運用建構元函式實作

  2. 程式實作時請注意下列事項:

    1. 請運用 memory_leak.h, memory_leak.cpp 檢查記憶體的錯誤

    2. 下圖這個類別架構是一個非常常用的設計樣式 (pattern), 共有四個類別 Client, Component, Leaf 和 Composite, 我們稱為 Composite Pattern
    3. 這個樣式主要用來實作樹狀架構的資料, 其中 Composite 是樹狀架構內部的節點, 是一個容器, 每一個 Composite 物件中可以包含多個 Leaf 或是 Composite 物件, 我們稍微修改一下用來表示 File-Folder 的樹狀架構如下



    4. 其中每一個 File 類別的物件是樹狀架構中的葉節點 (leaf node), 每一個 Folder 類別的物件是樹狀架構中的內部節點 (internal node), 這兩種物件都有一個共同的特性就是它們都是上層節點的子節點, 因此我們把這種共同的架構歸納出來成為它們的父類別 Entry 類別。 Folder 類別的物件裡面需要記住其下層物件 (可以是 File 物件 或是 Folder 物件), 因此我們看到 Folder 類別可以和多個 Entry 類別的物件有關係, 圖中 Folder 類別旁邊中空的菱形是 UML 語法中代表 聚合 (Aggregation) 的意思, 表示一個 Folder 裡可以容納多個 Entry 物件, 同時所包含 Entry 物件的生命週期和 Folder 沒有關係 (刪除 Folder 物件時, 不見得一定要刪除所有下層的物件, 例如可以將所容納的物件移到其他資料匣下, 這個搬移的功能在這次作業裡沒有要求你完成)。

    5. 在上面的架構裡, Folder 類別中的 entries 物件成員 是一個異質的陣列, 請注意很多搜尋與列印的動作中, 都會運用到 Entry * 型態的多型指標, 將 File 和 Folder 類別的物件一視同仁, 以簡化處理的機制, 這是 Composite 設計樣式和實習 Quiz#3 中直覺的類別架構最大的差別。

    6. 上圖中 File::add() 事實上應該什麼都不做, 只回傳 false, File::remove(Entry *) 也是這樣
      File::getSize() 回傳檔案的大小 (byte 數), Folder::getSize() 回傳所有下層檔案大小的總和
      File::printList(prefix:string, recursive:bool) 轉而呼叫 Entry::printName(prefix)
      Folder::printList(prefix:string, recursive:bool) 除了呼叫 Entry::printName(prefix) 列印本身資料匣名稱之外, 如果 recursive 為 true 的話, 還會要求子資料匣內所有的 Entry 物件列印
      prefix 字串最主要是用來調整列印時左邊應該保留的空格
      Folder::remove(Entry *=0) 這個介面 overload 兩個不同的用法, 如果呼叫 folderObject.remove(&fileObject) 則在該 folderObject 中刪除指定的 fileObject, 如果呼叫 folderObject.remove() 沒有給參數時, 就把 folderObject 裡所有的物件(檔案或是資料匣)通通刪除
      另外建立樹狀架構時也可以考慮在上下層 folder 之間建立雙向的連結, 如此在遊走於各個資料匣時會比較方便

    7. 你可以參考在這幾個類別圖中我所列的界面函式來實作, 不過只實作這幾個界面函式可能也沒辦法完成程式的所有功能, 並不強迫你使用這樣子的界面, 如果你有其他的想法, 你覺得變更以後可以有比較好的設計, 一定要在心得裡面討論。

  3. 說明文件之要求:

    1. 基本的心得, 程式架構說明 (UML 類別圖)

    2. 請特別分析一下你的程式裡是否有不斷重複的程式架構, 有沒有什麼辦法簡化

進一步增加程式的功能

原則上你想要增加什麼功能都是可以的, 記得在心得中寫出來, 這樣助教才會注意到, 可以多得到一些分數, 例如移動檔案, 移動子資料匣, 複製檔案與資料匣, 檔案名稱排序等等。

做完上面的要求以後, 你一定要找時間繼續看下一層的要求 - Visitor 設計樣式, 可以看到運用繼承時進階的物件導向設計方法

程式繳交說明:

  1. 請於時限內 (105/06/08 星期四 21:00) 上傳程式檔案 (逾時無法上傳), 上傳網頁
  2. 請運用 StarUML 繪製 類別圖 將影像匯入 word 報告檔中, 並且繳交 .uml 檔案
  3. 程式設計心得與討論 (當然如果你沒有討論任何程式碼, 沒有什麼有建設性的心得, 就算你有一個可以執行的程式, 你這一部份的分數可能還是很低 )
唸資訊工程系最大的優點其實就是你能夠由系統實作的角度來看任何問題,如果你放棄掌握軟體這個工具,那你在畢業的時候就會發現你在理論上比不上數學/應數系/統計系的訓練,在人機介面、智慧型系統、通訊系統、數位硬體等等工程應用上比不上電機系的訓練,在經濟、會計、管理比不上資管/企管系的訓練,你會變成很容易被人取代的...請加油

程式 Demo 說明:

  1. demo 的同學,程式必須能夠現場編譯沒有錯誤
  2. 請說明你的測試方法與測試資料,並操作測試, 請將你要測試的資料先打好,例如 prog4a.in, 利用 DOS 的重新導向來測試,例如 FileDirectory < prog4a.in > result.log
  3. 執行助教指定的測試資料
  4. 請回答你的程式在設計上的相關問題

C++ 物件導向程式設計課程 首頁

製作日期: 05/18/2016 by 丁培毅 (Pei-yih Ting)
E-mail: pyting@mail.ntou.edu.tw TEL: 02 24622192x6615
海洋大學 電機資訊學院 資訊工程學系 Lagoon