大量編輯介紹我最初批評了問題描述爲混亂。我的問題源於問題中使用「文件」的概念。這個問題意味着光盤,程序和曲目都存儲在一個'文件'中。我認爲提問者正在構建他自己的文件系統,這會讓這個「一個文件中的所有東西」變得很奇怪,但是我現在已經認定他可能沒有這樣做,在這種情況下,它並不奇怪。所以,我會繼續前進,根據他使用現有(可能是標準)文件系統的假設提供一個真正的答案,並且他的整個數據結構都存儲在該文件系統中的一個文件中。如果我錯誤地認爲我會糾正的。
我會首先爲這種情況提供一個一般建議;首先從API用戶的角度來看待事物。然後設計您的API,以便他編寫的代碼輕鬆流動,無需處理您的域中正確的詳細信息。
處理API設計的一種方法是首先編寫一些用戶代碼並定義API,以便該代碼易於編寫。作爲獎勵,在您實際實現API之後,您將擁有一些測試代碼來試用。
轉向更具體的建議;
這是系統中三種數據類型的目錄。如果你喜歡,我們可以把它們當作抽象數據類型或'對象'來對待,並且定義一個typdef'ed結構體(DISC,PROGRAM,TRACK)來表示每一個。
disc = a collection of programs stored in a file
+-----------+
|file |
+-----------+
|program |
+-----------+
|program |
+-----------+
|... |
+-----------+
|program |
+-----------+
program = a collection of tracks
+-----------+
|ptr->disc |
+-----------+
|name |
+-----------+
|file offset|
+-----------+
|track |
+-----------+
|track |
+-----------+
|... |
+-----------+
|track |
+-----------+
track = a collection of audio samples
+------------------+
|ptr->program |
+------------------+
|name |
+------------------+
|file offset+length|
+------------------+
|file offset+length|
+------------------+
|... |
+------------------+
|file offset+length|
+------------------+
我建議你不讓你的用戶挑選出從結構數據。你不能真正隱藏C語言中的結構的內部元素(沒有通過強制轉換等方式),但是你可以提供一系列函數讓你的用戶在不訪問抽象類型的內容的情況下做他們需要做的事情他們自己。例如,我們的功能家族可能看起來像這樣;
// DISC functions
DISC *dopen( const char *disc_name);
void dstats(int *ptr_nbr_programs, FILE **ptr_file);
void dclose(DISC *disc);
// PROGRAM functions
PROGRAM *popen_name(DISC *disc, const char *program_name);
PROGRAM *popen_idx (DISC *disc, int program_idx);
void pstats(int *ptr_nbr_tracks);
void pclose(PROGRAM *program);
// TRACK functions
TRACK *topen_name(PROGRAM *program, const char *track_name);
TRACK *topen_idx (PROGRAM *program, int track_idx);
int tread(unsigned char *buf, int nbytes_to_read);
void tseek(unsigned long offset);
void tclose(TRACK *track);
這應該都是合理的自我解釋 - 它是模仿現有的標準C FILE範例。
首先你的用戶用dopen()獲得一個ptr到DISC。假設這是有效的(如果不這樣做,它將返回NULL),他可以使用dstats()獲取任何全局DISC信息。更重要的是,他可以通過popen()函數族之一獲得DISC中PROGAM的ptr。
隨着程序的一個ptr,他可以進一步鑽取並獲得一個具有topen()系列函數的單個TRACK。
一個非常重要的問題是,您不會讓自己的用戶遍歷音頻片段自己從TRACK中獲取數據。用戶提供一個緩衝區來讀取樣本,並根據需要通過碎片進行迭代以填充緩衝區。 tseek()函數提供給他隨機訪問。
我還沒有試圖找出每個參數的詳細信息以及如何處理錯誤等,我只是提出了一個概念來提煉。
請注意,'三明治'範式貫穿始終。每種類型的介紹性「開放式」和結束式「近距離」三明治操作。
* facepalm *感謝查理 – Draemon 2009-04-20 23:59:48