詳解C++中的指針結(jié)構(gòu)體數(shù)組以及指向結(jié)構(gòu)體變量的指針
C++結(jié)構(gòu)體數(shù)組
一個結(jié)構(gòu)體變量中可以存放一組數(shù)據(jù)(如一個學(xué)生的學(xué)號、姓名、成績等數(shù)據(jù))。如果有10個學(xué)生的數(shù)據(jù)需要參加運算,顯然應(yīng)該用數(shù)組,這就是結(jié)構(gòu)體數(shù)組。結(jié)構(gòu)體數(shù)組與以前介紹過的數(shù)值型數(shù)組的不同之處在于:每個數(shù)組元素都是一個結(jié)構(gòu)體類型的數(shù)據(jù),它們都分別包括各個成員項。
定義結(jié)構(gòu)體數(shù)組和定義結(jié)構(gòu)體變量的方法相仿,定義結(jié)構(gòu)體數(shù)組時只需聲明其為數(shù)組即可。如:
struct Student //聲明結(jié)構(gòu)體類型Student { int num; char name[20]; char sex; int age; float score; char addr[30]; }; Student stu[3]; //定義Student類型的數(shù)組stu
也可以直接定義一個結(jié)構(gòu)體數(shù)組,如:
struct Student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu[3];
或
struct { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu[3];
結(jié)構(gòu)體數(shù)組的初始化與其他類型的數(shù)組一樣,對結(jié)構(gòu)體數(shù)組可以初始化。如:
struct Student { int num; char name[20]; char sex; int age; float score; char addr[30]; }stu[3]={ {10101,″Li Lin″, ′M′, 18,87.5, ″103 Beijing Road″}, {10102,″Zhang Fun″,′M′,19,99, ″130 Shanghai Road″}, {10104,″Wang Min″,′F′, 20,78.5, ″1010 Zhongshan Road″} };
定義數(shù)組stu時,也可以不指定元素個數(shù),即寫成以下形式:
stu[ ]={{…},{…},{…}};
編譯時,系統(tǒng)會根據(jù)給出初值的結(jié)構(gòu)體常量的個數(shù)來確定數(shù)組元素的個數(shù)。一個結(jié)構(gòu)體常量應(yīng)包括結(jié)構(gòu)體中全部成員的值。
當(dāng)然,數(shù)組的初始化也可以用以下形式:
Student stu[ ]={{…},{…},{…}}; //已事先聲明了結(jié)構(gòu)體類型Student
由上可以看到,結(jié)構(gòu)體數(shù)組初始化的一般形式是在所定義的數(shù)組名的后面加上 ={初值表列};
結(jié)構(gòu)體數(shù)組應(yīng)用舉例
下面舉一個簡單的例子來說明結(jié)構(gòu)體數(shù)組的定義和引用。
【例】對候選人得票的統(tǒng)計程序。設(shè)有3個候選人,最終只能有1人當(dāng)選為領(lǐng)導(dǎo)。今有10個人參加投票,從鍵盤先后輸入這10個人所投的候選人的名字,要求最后輸出這3個候選人的得票結(jié)果。
可以定義一個候選人結(jié)構(gòu)體數(shù)組,包括3個元素,在每個元素中存放有關(guān)的數(shù)據(jù)。程序如下:
#include <iostream> using namespace std; struct Person //聲明結(jié)構(gòu)體類型Person { char name[20]; int count; }; int main( ) { //定義Person類型的數(shù)組,內(nèi)容為3個候選人的姓名和當(dāng)前的得票數(shù) Person leader[3]={"Li",0,"Zhang",0,"Fun",0}; int i,j; char leader_name[20]; //leader_name為投票人所選的人的姓名 for(i=0;i<10;i++) { cin>>leader_name; //先后輸入10張票上所寫的姓名 for(j=0;j<3;j++) //將票上姓名與3個候選人的姓名比較 //如果與某一候選人的姓名相同,就給他加一票 if(strcmp(leader_name,leader[j].name)==0) leader[j].count++; } cout<<endl; for(i=0;i<3;i++) //輸出3個候選人的姓名與最后得票數(shù) { cout<<leader[i].name<<":"<<leader[i].count<<endl; } return 0; }
運行情況如下:
Zhang↙ (每次輸入一個候選人的姓名) Li↙ Fun↙ Li↙ Zhang↙ Li↙ Zhang↙ Li↙ Fun↙ Wang↙ Li:4 (輸出3個候選人的姓名與最后得票數(shù)) Zhang:3 Fun:2
程序定義一個全局的結(jié)構(gòu)體數(shù)組leader,它有3個元素,每一元素包含兩個成員,即name(姓名)和count(得票數(shù))。在定義數(shù)組時使之初始化,使3位候選人的票數(shù)都先置零。
在這個例子中,也可以不用字符數(shù)組而用string方法的字符串變量來存放姓名數(shù)據(jù),程序可修改如下:
#include <iostream> #include <string> using namespace std; struct Person { string name;//成員name為字符串變量 int count; }; int main( ) { Person leader[3]={"Li",0,"Zhang",0,"Fun",0}; int i,j; string leader_name;// leader_name為字符串變量 for(i=0;i<10;i++) { cin>>leader_name; for(j=0;j<3;j++) if(leader_name==leader[j].name) leader[j].count++//用“==”進行比較 } cout<<endl; for(i=0;i<3;i++) { cout<<leader[i].name<<":"<<leader[i].count<<endl; } return 0; }
運行情況與前相同。顯然后一個程序節(jié)省內(nèi)存空間,使用更方便,易讀性更好。但是 有些C++系統(tǒng)不能對包含string成員的結(jié)構(gòu)體變量初始化,需要作一些修改才能運行, 讀者可上機試一下。
C++指向結(jié)構(gòu)體變量的指針
一個結(jié)構(gòu)體變量的指針就是該變量所占據(jù)的內(nèi)存段的起始地址??梢栽O(shè)一個指針變量,用來指向一個結(jié)構(gòu)體變量,此時該指針變量的值是結(jié)構(gòu)體變量的起始地址。指針變量也可以用來指向結(jié)構(gòu)體數(shù)組中的元素。
通過指向結(jié)構(gòu)體變量的指針引用結(jié)構(gòu)體變量中的成員
下面通過一個簡單例子來說明指向結(jié)構(gòu)體變量的指針變量的應(yīng)用。
【例】指向結(jié)構(gòu)體變量的指針的應(yīng)用。
#include <iostream> #include <string> using namespace std; int main( ) { struct Student//聲明結(jié)構(gòu)體類型student { int num; string name; char sex; float score; }; Student stu;//定義Student類型的變量stu Student *p=&stu;//定義p為指向Student類型數(shù)據(jù)的指針變量并指向stu stu.num=10301;//對stu中的成員賦值 stu.name="Wang Fun";//對string變量可以直接賦值 stu.sex='f'; stu.score=89.5; cout<<stu. num<<" "<<stu.name<<" "<<stu.sex<<" "<< stu.score<<endl; cout<<p -> num<<" "<<(*p).name<<" "<<(*p).sex<<" "<<(*p).score<<endl; return 0; }
程序運行結(jié)果如下:
10301 Wang Fun f 89.5 (通過結(jié)構(gòu)體變量名引用成員)
10301 Wang Fun f 89.5 (通過指針引用結(jié)構(gòu)體變量中的成員)
兩個cout語句輸出的結(jié)果是相同的。
為了使用方便和使之直觀,C++提供了指向結(jié)構(gòu)體變量的運算符->,例如p->num表示指針p當(dāng)前指向的結(jié)構(gòu)體變量中的成員num。
p->num 和(*p).num等價。
同樣
p->name等價于(*p).name。
也就是說,以下3種形式等價:
結(jié)構(gòu)體變量.成員名。如stu.num。
(*p).成員名。如(*p).num。
p->成員名。如p->num。
“->”稱為指向運算符。
請分析以下幾種運算:
- p->n 得到p指向的結(jié)構(gòu)體變量中的成員n的值。
- p->n++ 得到p指向的結(jié)構(gòu)體變量中的成員n的值,用完該值后使它加1。
- ++p->n 得到p指向的結(jié)構(gòu)體變量中的成員n的值,并使之加1,然后再使用它。
用結(jié)構(gòu)體變量和指向結(jié)構(gòu)體變量的指針構(gòu)成鏈表
鏈表是一種常見的重要的數(shù)據(jù)結(jié)構(gòu)。下圖表示最簡單的一種鏈表(單向鏈表)的結(jié)構(gòu)。
鏈表有一個“頭指針”變量,圖中以head表示,它存放一個地址。該地址指向一個元素。鏈表中的每一個元素稱為“結(jié)點”,每個結(jié)點都應(yīng)包括兩個部分:
一是用戶需要用的實際數(shù)據(jù),
二是下一個結(jié)點的地址。
可以看到鏈表中各元素在內(nèi)存中的存儲單元可以是不連續(xù)的。要找某一元素,可以先找到上一個元素,根據(jù)它提供的下一元素地址找到下一個元素。
可以看到,這種鏈表的數(shù)據(jù)結(jié)構(gòu),必須利用結(jié)構(gòu)體變量和指針才能實現(xiàn)。
可以聲明一個結(jié)構(gòu)體類型,包含兩種成員,一種是用戶需要用的實際數(shù)據(jù),另一種是用來存放下一結(jié)點地址的指針變量。
例如,可以設(shè)計這樣一個結(jié)構(gòu)體類型:
struct Student { int num; float score; Student *next; //next指向Student結(jié)構(gòu)體變量 };
其中成員num和score是用戶需要用到的數(shù)據(jù),相當(dāng)于圖7.8結(jié)點中的A, B, C, D。next是指針類型的成員,它指向Student類型數(shù)據(jù)(就是next所在的結(jié)構(gòu)體類型)。用這種方法就可以建立鏈表。見圖。
圖中每一個結(jié)點都屬于Student類型,在它的成員next中存放下一個結(jié)點的地址,程序設(shè)計者不必知道各結(jié)點的具體地址,只要保證能將下一個結(jié)點的地址放到前一結(jié)點的成員next中即可。
下面通過一個例子來說明如何建立和輸出一個簡單鏈表。
【例】建立一個如圖所示的簡單鏈表,它由3個學(xué)生數(shù)據(jù)的結(jié)點組成。輸出各結(jié)點中的數(shù)據(jù)。
#define NULL 0 #include <iostream> using namespace std; struct Student { long num; float score; struct Student *next; }; int main( ) { Student a,b,c,*head,*p; a. num=31001; a.score=89.5; //對結(jié)點a的num和score成員賦值 b. num=31003; b.score=90; //對結(jié)點b的num和score成員賦值 c. num=31007; c.score=85; //對結(jié)點c的num和score成員賦值 head=&a; //將結(jié)點a的起始地址賦給頭指針head a.next=&b; //將結(jié)點b的起始地址賦給a結(jié)點的next成員 b.next=&c; //將結(jié)點c的起始地址賦給b結(jié)點的next成員 c.next=NULL; //結(jié)點的next成員不存放其他結(jié)點地址 p=head; //使p指針指向a結(jié)點 do { cout<<p->num<<" "<<p->score<<endl; //輸出p指向的結(jié)點的數(shù)據(jù) p=p->next; //使p指向下一個結(jié)點 } while (p!=NULL); //輸出完c結(jié)點后p的值為NULL return 0; }
本例是比較簡單的,所有結(jié)點(結(jié)構(gòu)體變量)都是在程序中定義的,不是臨時開辟的,也不能用完后釋放,這種鏈表稱為靜態(tài)鏈表。對各結(jié)點既可以通過上一個結(jié)點的next指針去訪問,也可以直接通過結(jié)構(gòu)體變量名a, b, c去訪問。
動態(tài)鏈表則是指各結(jié)點是可以隨時插入和刪除的,這些結(jié)點并沒有變量名,只能先找到上一個結(jié)點,才能根據(jù)它提供的下一結(jié)點的地址找到下一個結(jié)點。只有提供第一個結(jié)點的地址,即頭指針head,才能訪問整個鏈表。如同一條鐵鏈一樣,一環(huán)扣一環(huán),中間是不能斷開的。
建立動態(tài)鏈表,要用到后面介紹的動態(tài)分配內(nèi)存的運算符new和動態(tài)撤銷內(nèi)存的運算符delete。
欄 目:C語言
下一篇:C++中結(jié)構(gòu)體的類型定義和初始化以及變量引用
本文標(biāo)題:詳解C++中的指針結(jié)構(gòu)體數(shù)組以及指向結(jié)構(gòu)體變量的指針
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/2725.html
您可能感興趣的文章
- 04-02c語言沒有round函數(shù) round c語言
- 01-10求子數(shù)組最大和的解決方法詳解
- 01-10深入二叉樹兩個結(jié)點的最低共同父結(jié)點的詳解
- 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計- 解析最少換車次數(shù)的問題詳解
- 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計-用棧實現(xiàn)表達式求值的方法詳解
- 01-10HDOJ 1443 約瑟夫環(huán)的最新應(yīng)用分析詳解
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實現(xiàn)全排列算法的方法詳解
- 01-10如何查看進程實際的內(nèi)存占用情況詳解
- 01-10深入Main函數(shù)中的參數(shù)argc,argv的使用詳解


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機閱讀
- 01-10C#中split用法實例總結(jié)
- 04-02jquery與jsp,用jquery
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-11ajax實現(xiàn)頁面的局部加載
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-10delphi制作wav文件的方法