




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第11章結(jié)構(gòu)體與共用體前面已學(xué)習(xí)了變量和數(shù)組這些簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu),它們的特點(diǎn)是必須使用規(guī)定的數(shù)據(jù)類型。例如數(shù)組被定義為整型后,它的所有存儲(chǔ)單元都是由整型構(gòu)成。現(xiàn)實(shí)生活中某一類事物的共同屬性可能是由不同數(shù)據(jù)類型組成的集合,或者某一屬性在不同的情況下表現(xiàn)為不同的數(shù)據(jù)類型。本章將講解結(jié)構(gòu)體與共用體,用來(lái)設(shè)計(jì)復(fù)合數(shù)據(jù)結(jié)構(gòu)。11.1結(jié)構(gòu)體類型變量的定義和引用結(jié)構(gòu)體是一種復(fù)合數(shù)據(jù)類型,它由不同數(shù)據(jù)類型的存儲(chǔ)單元組合。例如,學(xué)生的成績(jī)表上有姓名、專業(yè)、學(xué)號(hào)和每門功課的成績(jī),姓名和專業(yè)可以看作是字符串型數(shù)據(jù),學(xué)號(hào)是無(wú)符號(hào)長(zhǎng)整型數(shù)據(jù),每門功課的成績(jī)是單精度浮點(diǎn)型數(shù)據(jù),由這些數(shù)據(jù)類型復(fù)合組成的學(xué)生成績(jī)單數(shù)據(jù)類型,就是一種結(jié)構(gòu)體類型。11.1.1結(jié)構(gòu)體類型變量的定義在定義結(jié)構(gòu)體類型變量之前,首先需要設(shè)計(jì)結(jié)構(gòu)體,定義結(jié)構(gòu)體的名稱和成員的數(shù)據(jù)類型,然后使用結(jié)構(gòu)體說(shuō)明變量,這時(shí)結(jié)構(gòu)體就成為了一種新的數(shù)據(jù)結(jié)構(gòu)。定義結(jié)構(gòu)體使用修飾符struct,它一般形式為:struct結(jié)構(gòu)體名{成員項(xiàng)列表};結(jié)構(gòu)體名是該結(jié)構(gòu)體獨(dú)一無(wú)二的名稱,命名規(guī)則與變量命名相同。成員項(xiàng)列表是結(jié)構(gòu)體中數(shù)據(jù)成員的數(shù)據(jù)類型和名稱,數(shù)據(jù)成員可以是變量、數(shù)組或者其它結(jié)構(gòu)體等復(fù)合數(shù)據(jù)結(jié)構(gòu)。成員項(xiàng)列表的一般形式為:數(shù)據(jù)類型成員名1;數(shù)據(jù)類型成員名2;數(shù)據(jù)類型成員名3;11.1.1結(jié)構(gòu)體類型變量的定義學(xué)生成績(jī)單的數(shù)據(jù)結(jié)構(gòu)如圖所示。11.1.1結(jié)構(gòu)體類型變量的定義該結(jié)構(gòu)有4個(gè)成員,name[]和dept[]是字符型數(shù)組,用于保存學(xué)生姓名與專業(yè);no是長(zhǎng)整型變量,用于保存學(xué)生的學(xué)號(hào),score[]是單精度浮點(diǎn)型數(shù)組,用于保存學(xué)生的成績(jī)。下例將定義學(xué)生成績(jī)單的結(jié)構(gòu)體:struct
student
//結(jié)構(gòu)體名{
charname[50];
//姓名
chardept[50];
//專業(yè)
longno;
//學(xué)號(hào)
floatscore[4];
//成績(jī)};
//結(jié)構(gòu)體定義結(jié)束一定要加上分號(hào)結(jié)構(gòu)體定義后,并沒(méi)有在內(nèi)存中為該結(jié)構(gòu)體劃分存儲(chǔ)空間,它只是作為一種數(shù)據(jù)結(jié)構(gòu)存在。只有在使用結(jié)構(gòu)體類型聲明變量后,系統(tǒng)才用該結(jié)構(gòu)體分配內(nèi)存空間給變量。使用結(jié)構(gòu)體聲明變量的一般形式是:struct結(jié)構(gòu)體名結(jié)構(gòu)體變量名該語(yǔ)句只能在結(jié)構(gòu)體定義后出現(xiàn)。如下例所示:struct
studentstu1,stu2;
//聲明結(jié)構(gòu)體變量stu1和stu211.1.1結(jié)構(gòu)體類型變量的定義結(jié)構(gòu)體變量的聲明還有其它形式,例如直接在定義結(jié)構(gòu)體的同時(shí)聲明變量,或者省略結(jié)構(gòu)體名直接定義結(jié)構(gòu)體類型的變量。如下例所示:struct
student
//結(jié)構(gòu)體名{
//成員項(xiàng)列表}
stu1,stu2;
//定義結(jié)構(gòu)體的同時(shí)聲明變量struct{
//成員項(xiàng)列表}
strc1,strc2;
//省略結(jié)構(gòu)體名直接定義結(jié)構(gòu)體類型的變量這兩種用法使結(jié)構(gòu)體喪失了通用性,特別是省略結(jié)構(gòu)體名的做法,這樣結(jié)構(gòu)體就不能在源代碼其它部分聲明更多的結(jié)構(gòu)體變量。在編寫大型程序的源代碼時(shí),結(jié)構(gòu)體定義部分通常放在頭文件中,使用時(shí)包含該頭文件即可,這樣一個(gè)結(jié)構(gòu)體不需要在程序的不同文件中反復(fù)定義。11.1.2結(jié)構(gòu)體類型變量的引用引用結(jié)構(gòu)體變量的數(shù)據(jù)需要同時(shí)給出結(jié)構(gòu)體變量名和數(shù)據(jù)成員名,引用結(jié)構(gòu)體變量的一般形式是:結(jié)構(gòu)體變量名.數(shù)據(jù)成員名它們之間用“.”操作符分隔。如下列源代碼所示:stu1.no
=20090001;
//使用“.”操作符引用結(jié)構(gòu)體成員這兩種符號(hào)的優(yōu)先級(jí)高于算術(shù)運(yùn)算符和賦值符號(hào),所以結(jié)構(gòu)體變量的成員與普通的變量或數(shù)組使用方法完全相同。11.1.3結(jié)構(gòu)體類型變量的初始化結(jié)構(gòu)體匯集了不同的數(shù)據(jù)類型,為結(jié)構(gòu)體類型變量初始化就略顯復(fù)雜,需要考慮初始化數(shù)據(jù)與結(jié)構(gòu)體成員項(xiàng)數(shù)據(jù)類型的匹配。如下例所示:struct
studentstu1={"Tom","Math",20090001,87.5,70.5,93,91};//聲明結(jié)構(gòu)體變量并初始化該語(yǔ)句為結(jié)構(gòu)體變量stu1的成員賦值,各成員的值分別為:
="Tom"
//引用name成員并賦值stu1.dept
="Math"
//引用dept成員并賦值stu1.no
=20090001
//引用no成員并賦值stu1.score[0]
=87.5
//引用score成員,并為該數(shù)組的第1個(gè)元素賦值stu1.score[1]
=70.5stu1.score[2]
=93stu1.score[3]
=9111.1.3結(jié)構(gòu)體類型變量的初始化這種初始化方法的原理是,結(jié)構(gòu)體的成員在內(nèi)存的連續(xù)空間中順序存儲(chǔ),從結(jié)構(gòu)體的首地址開(kāi)始依次將相匹配的數(shù)據(jù)類型保存在對(duì)應(yīng)的內(nèi)存單元中。如果結(jié)構(gòu)體中以另一個(gè)結(jié)構(gòu)體作為成員項(xiàng),如下例所示:structstrc1
//定義結(jié)構(gòu)體strc1{
inta;
//定義整型數(shù)據(jù)成員
longb;
//定義長(zhǎng)整型數(shù)據(jù)成員};struct
strc2
//定義結(jié)構(gòu)體strc2{
floata;
//定義單精度浮點(diǎn)型數(shù)據(jù)成員
structstrc1b;
//將結(jié)構(gòu)體strc1作為strc2的成員項(xiàng)};struct
strc2x;
//定義結(jié)構(gòu)體變量x11.1.3結(jié)構(gòu)體類型變量的初始化那么結(jié)構(gòu)體變量x中各成員的分配仍然是在連續(xù)空間中,結(jié)構(gòu)體變量x的成員項(xiàng)b在內(nèi)存空間中的總長(zhǎng)度為結(jié)構(gòu)體strc1定義的長(zhǎng)度,分布形式如strc1定義的順序,如圖所示。11.2結(jié)構(gòu)體數(shù)組的定義和引用當(dāng)需要使用大量相同的結(jié)構(gòu)體變量時(shí),可使用結(jié)構(gòu)體定義數(shù)組,該數(shù)組包含與結(jié)構(gòu)體相同的數(shù)據(jù)結(jié)構(gòu)所組成的連續(xù)存儲(chǔ)空間。如下例所示:struct
studentstu_a[50];
//聲明長(zhǎng)度為50的結(jié)構(gòu)體數(shù)組stu_a引用結(jié)構(gòu)體數(shù)組中元素的一般形式為:結(jié)構(gòu)體數(shù)組名[n].成員名[]符號(hào)的優(yōu)先級(jí)與.符號(hào)相同,適用于自左向右結(jié)合性,所以運(yùn)算時(shí)首先獲得的是結(jié)構(gòu)體數(shù)組的元素,然后再獲得該元素的成員。11.2結(jié)構(gòu)體數(shù)組的定義和引用如果該成員是數(shù)組,引用該成員數(shù)組元素的一般形式為:結(jié)構(gòu)體數(shù)組名[n].成員名[n]。同理,如果該成員是結(jié)構(gòu)體變量,引用形式為:結(jié)構(gòu)體數(shù)組名[n].成員.子成員。依次類推,任何復(fù)雜的成員都可以被訪問(wèn)。如下例所示:
structstudentstu_a[2]=
//初始化結(jié)構(gòu)體數(shù)組
{"Tom","Math",20090001,87.5,70.5,93,91,
"Jerry","Math",20090002,90,78.5,83.5,66};inti;for(i=0;i<2;i++){
printf("%8s%8s%ld%5.2f%5.2f%5.2f%5.2f\n",
stu_a[i].name,
//引用結(jié)構(gòu)體數(shù)組元素的成員
stu_a[i].dept,
stu_a[i].no,
stu_a[i].score[0],
//成員是數(shù)組,引用其中元素
stu_a[i].score[1],
stu_a[i].score[2],
stu_a[i].score[3]);
}程序中聲明了結(jié)構(gòu)體數(shù)組stu_a[],并在聲明時(shí)用數(shù)據(jù)為其初始化。然后用printf()函數(shù)將結(jié)構(gòu)體數(shù)組中的數(shù)據(jù)輸出。11.3結(jié)構(gòu)體指針的定義和引用C語(yǔ)言中指針的操作非常靈活,它也能指向結(jié)構(gòu)體變量對(duì)結(jié)構(gòu)體變量進(jìn)行操作。在學(xué)習(xí)結(jié)構(gòu)體指針之前,需要再次加深對(duì)指針的認(rèn)識(shí)。聲明指針變量時(shí)所使用的數(shù)據(jù)類型修飾符實(shí)際上的作用是定義指針訪問(wèn)內(nèi)存的范圍,如果指針定義為整型,那么該指針訪問(wèn)內(nèi)存的范圍就是整型變量在內(nèi)存中所占用的空間大小。雖然每次嘗試將指針變量所儲(chǔ)存的內(nèi)存地址輸出會(huì)發(fā)現(xiàn),任何類型的內(nèi)存地址長(zhǎng)度都是一樣,但不同類型間不能相互復(fù)制,只有空值型除外。因此在使用指針操作結(jié)構(gòu)體時(shí),一定要確定指針?biāo)x的數(shù)據(jù)類型與結(jié)構(gòu)體的數(shù)據(jù)類型相同。11.3.1指向結(jié)構(gòu)體類型變量的使用定義結(jié)構(gòu)體變量的一般形式是:結(jié)構(gòu)體名*結(jié)構(gòu)體變量名結(jié)構(gòu)體名作為指針變量的類型修飾符。引用結(jié)構(gòu)體指針?biāo)赶虻慕Y(jié)構(gòu)體變量成員需要使用“->”操作符,該操作符由減號(hào)“–”和小于號(hào)“>”組合而成。如下列源代碼所示:typedef
structstudentstu_t;
//將結(jié)構(gòu)體student定義為數(shù)據(jù)類型
stu_t
stu1={"Tom","Math",20090001,87.5,70.5,93,91};
//定義結(jié)構(gòu)體變量并初始化
stu_t
*p;
//定義結(jié)構(gòu)體指針
p=&stu1;
//將結(jié)構(gòu)體變量地址賦給指針
p->no=20090005;
//引用指針?biāo)赶蚪Y(jié)構(gòu)體變量的成員11.3.1指向結(jié)構(gòu)體類型變量的使用代碼中使用了typedef命令,該命令用于定義新的數(shù)據(jù)類型修飾符。執(zhí)行typedef命令后,stu_t成為了student結(jié)構(gòu)體類型修飾符,在代碼中stu_t的作用等同于structstudent。指針*p被指向結(jié)構(gòu)體變量stu1,但指針*p并不是結(jié)構(gòu)體變量,所以不能使用“.”符號(hào)引用結(jié)構(gòu)體成員,只能使用“->”操作符。在設(shè)計(jì)一些需要大量交換數(shù)據(jù)的程序時(shí),需要?jiǎng)討B(tài)為數(shù)據(jù)劃分內(nèi)存。當(dāng)不再需要該數(shù)據(jù)時(shí),可以從內(nèi)存中釋放,以節(jié)省程序運(yùn)行時(shí)占用的內(nèi)存空間。下例將演示為結(jié)構(gòu)體指針動(dòng)態(tài)分配內(nèi)存的操作方法。#include<stdlib.h>
//包含內(nèi)存動(dòng)態(tài)分配相關(guān)函數(shù)typedef
structstudentstu_t;
//將結(jié)構(gòu)體student定義為數(shù)據(jù)類型
stu_t
*p=(stu_t*)malloc(sizeof(stu_t));
//為結(jié)構(gòu)體指針劃分內(nèi)存空間
p->
no=2009;
//引用該內(nèi)存空間
free(stu_t);
//使用完畢后釋放該內(nèi)存空間在為結(jié)構(gòu)體動(dòng)態(tài)分配內(nèi)存空間時(shí),使用sizeof()函數(shù)計(jì)算結(jié)構(gòu)體stu_t在內(nèi)存中所需要的空間,然后使用malloc()函數(shù)將sizeof()函數(shù)返回的數(shù)量在內(nèi)存中劃分出來(lái),malloc()函數(shù)的返回值是該內(nèi)存空間的首地址,所以用強(qiáng)制轉(zhuǎn)換表達(dá)式“(stu_t*)”將malloc()返回的地址轉(zhuǎn)換為stu_t類型的指針。11.3.2指向結(jié)構(gòu)體類型數(shù)組的指針的使用結(jié)構(gòu)體類型數(shù)組本質(zhì)上是作為數(shù)組存在,數(shù)組的元素是結(jié)構(gòu)體變量。結(jié)構(gòu)體數(shù)組的名稱即是指向該數(shù)組第一個(gè)數(shù)組元素的指針。結(jié)構(gòu)體數(shù)組元素之間不能直接相互復(fù)制數(shù)據(jù),下面將介紹通過(guò)指針直接訪問(wèn)內(nèi)存空間復(fù)制結(jié)構(gòu)體數(shù)組元素的方法。#include<stdlib.h>
//包含內(nèi)存動(dòng)態(tài)分配相關(guān)函數(shù)#include<string.h>
//包含內(nèi)存復(fù)制相關(guān)函數(shù)typedef
structstudentstu_t;
//將結(jié)構(gòu)體student定義為數(shù)據(jù)類型
stu_t
stu_a[2]={"Tom","Math",20090001,87.5,70.5,93,91};
//初始化結(jié)構(gòu)體數(shù)組第1個(gè)元素
stu_t
*p=stu_a;
//為結(jié)構(gòu)體指針劃分內(nèi)存空間
memcpy(p+1,p,sizeof(stu_t));
//將數(shù)組第1個(gè)元素復(fù)制給數(shù)組第2個(gè)元素
puts((p+1)->name);
//用指針引用數(shù)組第2個(gè)元素的數(shù)組成員程序中定義了結(jié)構(gòu)體數(shù)組stu_a,在初始化時(shí)為其第1個(gè)元素賦值。定義指針*p時(shí),用數(shù)組名stu_a為指針*p賦值,指針*p指向了數(shù)組stu_a第1個(gè)元素。memcpy()函數(shù)的作用是將內(nèi)存中從指針*p指向的地址開(kāi)始長(zhǎng)度為sizeof(stu_t)的數(shù)據(jù),復(fù)制到內(nèi)存中指針*p+1指向的地址開(kāi)始長(zhǎng)度為sizeof(stu_t)的空間里。由此可見(jiàn),對(duì)指針*p+1進(jìn)行的操作,并非簡(jiǎn)單的將內(nèi)存地址作為整型數(shù)據(jù)進(jìn)行加1運(yùn)算,1代表的是sizeof(stu_t)的長(zhǎng)度的內(nèi)存區(qū)間所跨越地址的差值。11.4共用體共用體又稱為聯(lián)合體,是由不同數(shù)據(jù)類型組成的一個(gè)整體。與結(jié)構(gòu)體不同的是,共用體每次只能使用其中一個(gè)成員。結(jié)構(gòu)體的總長(zhǎng)度是結(jié)構(gòu)體所有成員長(zhǎng)度之和,共用體的總長(zhǎng)度是其中最長(zhǎng)一個(gè)數(shù)據(jù)類型的長(zhǎng)度,共用體的所有成員共享這一存儲(chǔ)空間。在一些場(chǎng)合中,只需要使用某一類型的變量而其它類型的變量暫時(shí)不需要使用。當(dāng)使用另一類型變量時(shí),原先的變量也轉(zhuǎn)為與程序無(wú)關(guān),這種情況下可使用共用體節(jié)省同時(shí)存在多種數(shù)據(jù)類型變量所需要的額外空間。11.4.1共用體的定義定義共用體使用修飾符union,一般形式是:union共用體名{成員項(xiàng)列表};共用體名是該共用體獨(dú)一無(wú)二的名稱,命名規(guī)則與變量命名相同。成員項(xiàng)列表是共用體中數(shù)據(jù)成員的數(shù)據(jù)類型和名稱,數(shù)據(jù)成員可以是變量、數(shù)組或者其它結(jié)構(gòu)體等復(fù)合數(shù)據(jù)結(jié)構(gòu),各成員通常不使用相同的數(shù)據(jù)類型。成員項(xiàng)列表的一般形式為:數(shù)據(jù)類型成員名1;數(shù)據(jù)類型成員名2;數(shù)據(jù)類型成員名3;11.4.1共用體的定義使用共用體聲明變量的一般形式是:union共用體名共用體變量名;該語(yǔ)句只能在共用體定義后出現(xiàn)。如下例所示:union
unidate
{
//共用體名
chara;
//共用體成員
intb;
longc;
double
d;};unionunidate
x;
//共用體變量共用體成員中,長(zhǎng)度最長(zhǎng)的是雙精度浮點(diǎn)型d,共用體變量x的長(zhǎng)度為雙精度浮點(diǎn)型數(shù)據(jù)類型的長(zhǎng)度,內(nèi)存分配形式如后圖所示。11.4.1共用體的定義11.4.2共用體變量的引用共用體變量的引用方式與結(jié)構(gòu)體變量相同,一般形式為:共用體名.成員名但共用體一次只能使用一個(gè)成員,如下例所示:unionunidatex;
//聲明共用體變量x.a=65;
//為成員a賦值printf("x.a=%c\n",x.a);x.b=100;
//為成員b賦值printf("x.b=%d\n",x.b);x.c=10005000;
//為成員c賦值printf("x.c=%ld\n",x.c);x.d=0.69314718056;
//為成員d賦值printf("x.d=%f\n",x.d);printf("x.a=%c\n",x.a);
//再次輸出成員a,這時(shí)成員a已沒(méi)被使用該程序的輸出結(jié)果為:x.a=Ax.b=100x.c=10005000x.d=0.693147x.a=最后一次輸出的結(jié)果為不可預(yù)知的,因?yàn)楣灿皿wx的存儲(chǔ)空間中已經(jīng)被成員x.d使用過(guò),而輸出成員x.a前,沒(méi)有重新為成員x.a賦值,這時(shí)如果引用成員x.a的數(shù)據(jù),獲得的是成員x.d的一部分?jǐn)?shù)據(jù),所以輸出結(jié)果可能因系統(tǒng)環(huán)境的不同而有差異。11.5媒體播放器——建立媒體庫(kù)媒體播放器程序中有許多復(fù)雜的數(shù)據(jù)結(jié)構(gòu),這些數(shù)據(jù)結(jié)構(gòu)可以用來(lái)管理復(fù)雜的信息。以媒體庫(kù)為例,每個(gè)媒體項(xiàng)目包含標(biāo)題、藝術(shù)家、專輯名稱、流派、時(shí)間長(zhǎng)度、文件路徑等幾項(xiàng)基本信息。播放列表的實(shí)際應(yīng)用中,也必須有序號(hào)、標(biāo)題、文件路徑、時(shí)間長(zhǎng)度等信息。本節(jié)實(shí)例將繼續(xù)介紹媒體庫(kù)的設(shè)計(jì),首先介紹媒體庫(kù)中數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì),然后介紹媒體庫(kù)的一些基本操作實(shí)現(xiàn)方法。11.5.1設(shè)計(jì)媒體庫(kù)中的數(shù)據(jù)結(jié)構(gòu)媒體庫(kù)中主要的數(shù)據(jù)結(jié)構(gòu)用來(lái)保存媒體文件中所包含的信息,這些信息可以使用libid3tag庫(kù)讀取。libid3tag庫(kù)被mad插件使用,該插件用于在GStreamer框架中對(duì)MP3文件提供支持,是一個(gè)用途非常廣泛的函數(shù)庫(kù)。安裝該庫(kù)可以從官方站點(diǎn)“/products/mad”中下載源代碼進(jìn)行編譯,也可在終端上執(zhí)行下列指令:apt-getinstalllibid3tag0libid3tag0-dev在程序中使用該庫(kù)只須包含頭文件id3tag,編譯時(shí)在CrossGCCLinker|Libraries列表項(xiàng)Libraries(-l)中加入編譯指令id3tag,或者使用pkg-config程序加入指令“'pkg-config--cflags--libsid3tag'”。11.5.1設(shè)計(jì)媒體庫(kù)中的數(shù)據(jù)結(jié)構(gòu)1.libid3tag庫(kù)簡(jiǎn)介該函數(shù)庫(kù)本身就包含有4個(gè)主要的數(shù)據(jù)結(jié)構(gòu),id3_file用于保存文件信息,id3_file_open()函數(shù)用于打開(kāi)指令路徑的媒體文件,并創(chuàng)建id3_file結(jié)構(gòu)體。id3_tag用于保存文件中的媒體信息,可使用id3_file_tag()函數(shù)通過(guò)一個(gè)id3_file結(jié)構(gòu)體創(chuàng)建。id3_frame是使用的重點(diǎn),用于保存一個(gè)信息項(xiàng)目的信息,由id3_tag_findframe()函數(shù)訪問(wèn)id3_tag結(jié)構(gòu)創(chuàng)建。其中包含有id3_field共用體,保存項(xiàng)目的具體數(shù)值。訪問(wèn)完媒體文件后,需要使用id3_file_close()函數(shù)釋放這些數(shù)據(jù)類型所使用的內(nèi)存資源。它們的一般形式為:structid3_file*id3_file_open(charconst*,enumid3_file_mode);structid3_tag*id3_file_tag(structid3_fileconst*);structid3_frame*id3_tag_findframe(structid3_tagconst*,charconst*,unsignedint);intid3_file_close(structid3_file*);id3_file_open()函數(shù)的第1個(gè)參數(shù)是包含完整路徑的文件名,第2個(gè)參數(shù)是文件打開(kāi)方式。例如使用ID3_FILE_MODE_READONLY參數(shù)表示以只讀方式打開(kāi),ID3_FILE_MODE_READWRITE參數(shù)表示以讀寫方式打開(kāi)。id3_tag_findframe()函數(shù)的第2個(gè)參數(shù)用于指定要訪問(wèn)的項(xiàng)目名稱,這些名稱在一個(gè)關(guān)于媒體信息的ID3標(biāo)準(zhǔn)文檔中定義,見(jiàn)。常用信息如后表所示。11.5.1設(shè)計(jì)媒體庫(kù)中的數(shù)據(jù)結(jié)構(gòu)常量名稱縮
寫描
述ID3_FRAME_TITLETIT2媒體的標(biāo)題ID3_FRAME_ARTISTTPE1藝術(shù)家名稱ID3_FRAME_ALBUMTALB專輯名稱ID3_FRAME_YEARTDRC發(fā)行年份ID3_FRAME_TRACKTRCK在CD光盤中的軌道位置ID3_FRAME_GENRETCON流派ID3_FRAME_COMMENTCOMM注釋(無(wú))TDRC記錄長(zhǎng)度(并不一定能反映真實(shí)長(zhǎng)度)11.5.1設(shè)計(jì)媒體庫(kù)中的數(shù)據(jù)結(jié)構(gòu)第3個(gè)參數(shù)用于指定索引號(hào),有些項(xiàng)目信息被分為多個(gè)段,第一段的編號(hào)為0。創(chuàng)建了id3_frame結(jié)構(gòu)體后,就可以訪問(wèn)其中的媒體信息,該結(jié)構(gòu)體內(nèi)包含多個(gè)成員,定義形式如下:structid3_frame{
charid[];
//項(xiàng)目的編號(hào)(媒體標(biāo)題為“TIT2”)
charconst*description;
//結(jié)構(gòu)體的英文描述字符串(媒體標(biāo)題為“Title”)
unsignedintnfields;
//所包含項(xiàng)目分段數(shù)
unionid3_field*fields;
//所包含項(xiàng)目的數(shù)據(jù)陣列};id3_field共用體作為其成員,保存著實(shí)際的項(xiàng)目信息。不同項(xiàng)目的數(shù)據(jù)類型可能有區(qū)別,媒體的標(biāo)題通是字符串,發(fā)行年份是數(shù)字,使用共用體的作用是為讀取這些數(shù)據(jù)提供正確的接口。(11_5_1_1.c)在共用體中又定義枚舉類型成員和一系列結(jié)構(gòu)體,從內(nèi)存分配上來(lái)說(shuō),所有成員都是共享同一個(gè)內(nèi)存區(qū)域,所以只有選擇對(duì)應(yīng)的類型才能獲得相應(yīng)的信息。11.5.1設(shè)計(jì)媒體庫(kù)中的數(shù)據(jù)結(jié)構(gòu)2.設(shè)計(jì)媒體庫(kù)的數(shù)據(jù)結(jié)構(gòu)單個(gè)媒體庫(kù)項(xiàng)目的數(shù)據(jù)結(jié)構(gòu)可以用一個(gè)結(jié)構(gòu)體表示,播放列表也是同樣。實(shí)際使用中再由這些結(jié)構(gòu)體組成數(shù)組進(jìn)行操作,這樣就很容易的控制其長(zhǎng)短。這些數(shù)據(jù)結(jié)構(gòu)被定義在頭文件medialib.h中。(11_5_1_2.c)3.讀取媒體文件信息到媒體庫(kù)項(xiàng)目中讀取媒體文件信息的流程為,首先通過(guò)文件創(chuàng)建id3_file結(jié)構(gòu)體,然后使用id3_file結(jié)構(gòu)體創(chuàng)建id3_tag結(jié)構(gòu)體,最后使用id3_tag創(chuàng)建出多個(gè)項(xiàng)目的id3_frame結(jié)構(gòu)體。復(fù)制數(shù)據(jù)到媒體庫(kù)項(xiàng)目中有兩種方式,在復(fù)制字符串信息時(shí),可直接訪問(wèn)id3_field共用體的內(nèi)存空間。如果是其它類型,必須用接口函數(shù)提取出對(duì)應(yīng)的數(shù)值,例如id3_field_getint()函數(shù)用于提取數(shù)字信息。(11_5_1_3.c)代碼中將結(jié)構(gòu)體struct_medialib的指針作為形式參數(shù),所以運(yùn)行時(shí)必須使用“->”操作符訪問(wèn)其成員。改變?cè)摻Y(jié)構(gòu)體內(nèi)的數(shù)值后,實(shí)際參數(shù)也將隨之改變。讀取id3_frame的成員id3_field共用體時(shí),因?yàn)槭侵苯油ㄟ^(guò)指針訪問(wèn),所以需要將其強(qiáng)制轉(zhuǎn)換為字符型指針,例如“(char*)frame_title->fields”。這段代碼需要保存到文件medialib.c中,同時(shí)還需要在頭文件medialib.h中加入函數(shù)原型。如下所示:intread_tag_from_file(constchar*file,struct_medialib*media);11.5.2媒體庫(kù)的基本操作媒體庫(kù)的基本操作在第9章實(shí)例部分已進(jìn)行過(guò)定義,因?yàn)橛行﹥?nèi)容涉及到數(shù)據(jù)庫(kù)和程序界面,所以本小節(jié)暫時(shí)不考慮。本節(jié)介紹添加文件到媒體庫(kù)、在媒體庫(kù)中查找文件、從媒體庫(kù)刪除選定文件、從媒體庫(kù)刪除所有文件。由于所有操作指令是由核心控制模塊所發(fā)出的,所以媒體庫(kù)數(shù)據(jù)的入口在該模塊中創(chuàng)建。在第8章為播放列表建立的數(shù)據(jù)結(jié)構(gòu)中使用數(shù)組存放項(xiàng)目信息。由于數(shù)組的長(zhǎng)度在創(chuàng)建時(shí)已確定,實(shí)際應(yīng)用中有兩個(gè)顯要缺陷,其一是數(shù)組長(zhǎng)度太短時(shí)無(wú)法裝入更多的項(xiàng)目,其二是數(shù)組長(zhǎng)度太長(zhǎng)時(shí)浪費(fèi)了大量的內(nèi)存空間。而數(shù)組長(zhǎng)度究竟應(yīng)該是多長(zhǎng)很難確定,所以如果用一種長(zhǎng)度可變的數(shù)據(jù)結(jié)構(gòu)來(lái)存放媒體信息更為合適。單向鏈表就是一種可變長(zhǎng)度的數(shù)據(jù)結(jié)構(gòu),它的每一項(xiàng)稱之為一個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)是一個(gè)單獨(dú)的結(jié)構(gòu)體。節(jié)點(diǎn)的最后一個(gè)成員是與節(jié)點(diǎn)的結(jié)構(gòu)體指針,它能夠指向另一個(gè)節(jié)點(diǎn),由此形成了一個(gè)鏈狀結(jié)構(gòu),如圖所示。11.5.2媒體庫(kù)的基本操作在該鏈表中有3個(gè)節(jié)點(diǎn),這些節(jié)點(diǎn)并非處在連續(xù)的內(nèi)存空間中。*np指針是鏈表的入口,它指向了node1節(jié)點(diǎn)的首地址。node1節(jié)點(diǎn)末尾的指針指向node2節(jié)點(diǎn)結(jié)構(gòu)體首地址,node2節(jié)點(diǎn)的指針指向node3節(jié)點(diǎn)的首地址。node3節(jié)點(diǎn)是鏈表的末尾,它的指針指向NULL。節(jié)點(diǎn)使用動(dòng)態(tài)內(nèi)存分配方式創(chuàng)建,當(dāng)鏈表為空時(shí),鏈表入口指向NULL的位置。創(chuàng)建第一個(gè)節(jié)點(diǎn)后,將節(jié)點(diǎn)的首地址傳送給鏈表入口,創(chuàng)建第二個(gè)節(jié)點(diǎn)時(shí),將內(nèi)存地址傳送給上一個(gè)節(jié)點(diǎn)內(nèi)的指針。節(jié)點(diǎn)本身沒(méi)有名稱,訪問(wèn)節(jié)點(diǎn)只能使用遍歷方法。通常用一個(gè)整型變量記錄節(jié)點(diǎn)的總長(zhǎng)度,再用另一個(gè)整型變量記錄遍歷的位置。如果要?jiǎng)h除一個(gè)節(jié)點(diǎn),首先遍歷到該節(jié)點(diǎn)之前的節(jié)點(diǎn),將指針指向被刪除節(jié)點(diǎn)之后的節(jié)點(diǎn)的首地址。如果刪除的是鏈表首端的節(jié)點(diǎn),將鏈表入口指針指向被刪除節(jié)點(diǎn)之后的節(jié)點(diǎn)的首地址。如果刪除的是鏈表末尾的節(jié)點(diǎn),則將上一個(gè)節(jié)點(diǎn)的指針置為NULL。最后釋放被刪除節(jié)點(diǎn)的內(nèi)存空間。插入一個(gè)節(jié)點(diǎn)的原理與刪除節(jié)點(diǎn)原理相似,先為插入的節(jié)點(diǎn)分配內(nèi)存空間,將插入位置后的節(jié)點(diǎn)的首地址傳遞到插入節(jié)點(diǎn)的指針中,然后將插入節(jié)點(diǎn)的首地址傳遞到插入位置前的一個(gè)節(jié)點(diǎn)的指針中。11.5.2媒體庫(kù)的基本操作了解鏈表操作的原理后,即可為媒體庫(kù)創(chuàng)建鏈表,先要定義節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)node_t,然后定義鏈表的數(shù)據(jù)結(jié)構(gòu)link_t。這些定義放在medialib.h中,如下列源代碼所示:typedefstruct_node_tnode_t;
//將結(jié)構(gòu)體定義為新類型struct_node_t{
//節(jié)點(diǎn)的結(jié)構(gòu)體
Medialibitem;
//存放媒體信息的結(jié)構(gòu)體成員
node_t*p;
//指向另一個(gè)節(jié)點(diǎn)的指針};typedefstruct_link_tlink_t;struct_link_t{
//鏈表的結(jié)構(gòu)體
node_t*np;
//指向鏈表中第一個(gè)節(jié)點(diǎn)首地址的指針
intlength;
//用于記錄鏈表的長(zhǎng)度};媒體庫(kù)的控制指令由核心控制模塊發(fā)出,所以應(yīng)該將鏈表初始化的代碼放在核心控制模塊中。使用時(shí)核心控制模塊將鏈表的結(jié)構(gòu)體首地址作為參數(shù)傳遞到調(diào)用者。在main_core.c中加入媒體庫(kù)模塊的頭文件medialib.h,然后在main_core()函數(shù)中加入初始化鏈表的語(yǔ)句,如下列源代碼所示:#include"medialib.h"void*main_core(intcmd,void*data){
link_tmlink={NULL,0};
//初始化媒體庫(kù)鏈表}在頭文件medialib.h中已經(jīng)將媒體庫(kù)鏈表結(jié)構(gòu)定義為一個(gè)新類型link_t,所以可以直接用link_t類型創(chuàng)建媒體庫(kù)。媒體庫(kù)結(jié)構(gòu)創(chuàng)建后,即可實(shí)現(xiàn)一些對(duì)媒體庫(kù)的基本操作。下面依次介紹這些操作的實(shí)現(xiàn)方法,代碼保存到medialib.c文件中。11.5.3添加文件到媒體庫(kù)添加文件到媒體庫(kù)操作的作用是將媒體文件信息作為一個(gè)鏈表項(xiàng)放在鏈表的末端。實(shí)現(xiàn)該操作需要設(shè)計(jì)兩個(gè)函數(shù),第一個(gè)函數(shù)是遍歷到媒體庫(kù)鏈表末端,第二個(gè)函數(shù)是調(diào)用11.5.2小節(jié)中設(shè)計(jì)用于讀取媒體文件信息的read_tag_from_file()函數(shù),然
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 印刷企業(yè)市場(chǎng)調(diào)研方法考核試卷
- 家庭裝飾畫(huà)框批發(fā)考核試卷
- 園藝陶瓷的公共空間裝飾效果考核試卷
- 印刷設(shè)備生產(chǎn)過(guò)程的智能化技術(shù)應(yīng)用案例考核試卷
- 圖書(shū)出租業(yè)務(wù)的服務(wù)標(biāo)準(zhǔn)化培訓(xùn)考核試卷
- 影視錄放設(shè)備的智能鏡頭切換考核試卷
- 暖氣施工合同范本
- 簽訂重大銷售合同范本
- 口腔消毒培訓(xùn)課件
- 電商行業(yè)產(chǎn)品描述免責(zé)協(xié)議承諾書(shū)
- 八年級(jí)英語(yǔ)初中英語(yǔ)閱讀理解閱讀專項(xiàng)練習(xí)試卷附答案
- 固定資產(chǎn)清查盤點(diǎn)明細(xì)表
- 人教版八年級(jí)數(shù)學(xué)下冊(cè)課件【全冊(cè)】
- 物聯(lián)網(wǎng)管理平臺(tái)的設(shè)計(jì)與實(shí)現(xiàn)
- 1例妊娠糖尿病的個(gè)案護(hù)理
- 光伏發(fā)電職業(yè)病危害預(yù)評(píng)價(jià)方案方案
- 財(cái)務(wù)報(bào)表涉稅分析
- 立式單軸木工銑床安全操作規(guī)程
- 重癥患者識(shí)別課件
- 《計(jì)算機(jī)組成原理》全冊(cè)詳解優(yōu)秀課件
- 高中物理新課標(biāo)人教必修252平拋運(yùn)動(dòng)(帶動(dòng)畫(huà)和投彈游戲)課件
評(píng)論
0/150
提交評(píng)論