大量编辑介绍我最初批评了问题描述为混乱。我的问题源于问题中使用“文件”的概念。这个问题意味着光盘,程序和曲目都存储在一个'文件'中。我认为提问者正在构建他自己的文件系统,这会让这个“一个文件中的所有东西”变得很奇怪,但是我现在已经认定他可能没有这样做,在这种情况下,它并不奇怪。所以,我会继续前进,根据他使用现有(可能是标准)文件系统的假设提供一个真正的答案,并且他的整个数据结构都存储在该文件系统中的一个文件中。如果我错误地认为我会纠正的。
我会首先为这种情况提供一个一般建议;首先从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