詳解C++中的指針結(jié)構(gòu)體數(shù)組以及指向結(jié)構(gòu)體變量的指針
C++結(jié)構(gòu)體數(shù)組
一個(gè)結(jié)構(gòu)體變量中可以存放一組數(shù)據(jù)(如一個(gè)學(xué)生的學(xué)號(hào)、姓名、成績(jī)等數(shù)據(jù))。如果有10個(gè)學(xué)生的數(shù)據(jù)需要參加運(yùn)算,顯然應(yīng)該用數(shù)組,這就是結(jié)構(gòu)體數(shù)組。結(jié)構(gòu)體數(shù)組與以前介紹過(guò)的數(shù)值型數(shù)組的不同之處在于:每個(gè)數(shù)組元素都是一個(gè)結(jié)構(gòu)體類型的數(shù)據(jù),它們都分別包括各個(gè)成員項(xiàng)。
定義結(jié)構(gòu)體數(shù)組和定義結(jié)構(gòu)體變量的方法相仿,定義結(jié)構(gòu)體數(shù)組時(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
也可以直接定義一個(gè)結(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ù)組一樣,對(duì)結(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í),也可以不指定元素個(gè)數(shù),即寫成以下形式:
stu[ ]={{…},{…},{…}};
編譯時(shí),系統(tǒng)會(huì)根據(jù)給出初值的結(jié)構(gòu)體常量的個(gè)數(shù)來(lái)確定數(shù)組元素的個(gè)數(shù)。一個(gè)結(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)用舉例
下面舉一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明結(jié)構(gòu)體數(shù)組的定義和引用。
【例】對(duì)候選人得票的統(tǒng)計(jì)程序。設(shè)有3個(gè)候選人,最終只能有1人當(dāng)選為領(lǐng)導(dǎo)。今有10個(gè)人參加投票,從鍵盤先后輸入這10個(gè)人所投的候選人的名字,要求最后輸出這3個(gè)候選人的得票結(jié)果。
可以定義一個(gè)候選人結(jié)構(gòu)體數(shù)組,包括3個(gè)元素,在每個(gè)元素中存放有關(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個(gè)候選人的姓名和當(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個(gè)候選人的姓名比較
//如果與某一候選人的姓名相同,就給他加一票
if(strcmp(leader_name,leader[j].name)==0) leader[j].count++;
}
cout<<endl;
for(i=0;i<3;i++) //輸出3個(gè)候選人的姓名與最后得票數(shù)
{
cout<<leader[i].name<<":"<<leader[i].count<<endl;
}
return 0;
}
運(yùn)行情況如下:
Zhang↙ (每次輸入一個(gè)候選人的姓名) Li↙ Fun↙ Li↙ Zhang↙ Li↙ Zhang↙ Li↙ Fun↙ Wang↙ Li:4 (輸出3個(gè)候選人的姓名與最后得票數(shù)) Zhang:3 Fun:2
程序定義一個(gè)全局的結(jié)構(gòu)體數(shù)組leader,它有3個(gè)元素,每一元素包含兩個(gè)成員,即name(姓名)和count(得票數(shù))。在定義數(shù)組時(shí)使之初始化,使3位候選人的票數(shù)都先置零。
在這個(gè)例子中,也可以不用字符數(shù)組而用string方法的字符串變量來(lái)存放姓名數(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++//用“==”進(jìn)行比較
}
cout<<endl;
for(i=0;i<3;i++)
{
cout<<leader[i].name<<":"<<leader[i].count<<endl;
}
return 0;
}
運(yùn)行情況與前相同。顯然后一個(gè)程序節(jié)省內(nèi)存空間,使用更方便,易讀性更好。但是 有些C++系統(tǒng)不能對(duì)包含string成員的結(jié)構(gòu)體變量初始化,需要作一些修改才能運(yùn)行, 讀者可上機(jī)試一下。
C++指向結(jié)構(gòu)體變量的指針
一個(gè)結(jié)構(gòu)體變量的指針就是該變量所占據(jù)的內(nèi)存段的起始地址??梢栽O(shè)一個(gè)指針變量,用來(lái)指向一個(gè)結(jié)構(gòu)體變量,此時(shí)該指針變量的值是結(jié)構(gòu)體變量的起始地址。指針變量也可以用來(lái)指向結(jié)構(gòu)體數(shù)組中的元素。
通過(guò)指向結(jié)構(gòu)體變量的指針引用結(jié)構(gòu)體變量中的成員
下面通過(guò)一個(gè)簡(jiǎn)單例子來(lái)說(shuō)明指向結(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;//對(duì)stu中的成員賦值
stu.name="Wang Fun";//對(duì)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;
}
程序運(yùn)行結(jié)果如下:
10301 Wang Fun f 89.5 (通過(guò)結(jié)構(gòu)體變量名引用成員)
10301 Wang Fun f 89.5 (通過(guò)指針引用結(jié)構(gòu)體變量中的成員)
兩個(gè)cout語(yǔ)句輸出的結(jié)果是相同的。
為了使用方便和使之直觀,C++提供了指向結(jié)構(gòu)體變量的運(yùn)算符->,例如p->num表示指針p當(dāng)前指向的結(jié)構(gòu)體變量中的成員num。
p->num 和(*p).num等價(jià)。
同樣
p->name等價(jià)于(*p).name。
也就是說(shuō),以下3種形式等價(jià):
結(jié)構(gòu)體變量.成員名。如stu.num。
(*p).成員名。如(*p).num。
p->成員名。如p->num。
“->”稱為指向運(yùn)算符。
請(qǐng)分析以下幾種運(yùn)算:
- 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)成鏈表
鏈表是一種常見(jiàn)的重要的數(shù)據(jù)結(jié)構(gòu)。下圖表示最簡(jiǎn)單的一種鏈表(單向鏈表)的結(jié)構(gòu)。

鏈表有一個(gè)“頭指針”變量,圖中以head表示,它存放一個(gè)地址。該地址指向一個(gè)元素。鏈表中的每一個(gè)元素稱為“結(jié)點(diǎn)”,每個(gè)結(jié)點(diǎn)都應(yīng)包括兩個(gè)部分:
一是用戶需要用的實(shí)際數(shù)據(jù),
二是下一個(gè)結(jié)點(diǎn)的地址。
可以看到鏈表中各元素在內(nèi)存中的存儲(chǔ)單元可以是不連續(xù)的。要找某一元素,可以先找到上一個(gè)元素,根據(jù)它提供的下一元素地址找到下一個(gè)元素。
可以看到,這種鏈表的數(shù)據(jù)結(jié)構(gòu),必須利用結(jié)構(gòu)體變量和指針才能實(shí)現(xiàn)。
可以聲明一個(gè)結(jié)構(gòu)體類型,包含兩種成員,一種是用戶需要用的實(shí)際數(shù)據(jù),另一種是用來(lái)存放下一結(jié)點(diǎn)地址的指針變量。
例如,可以設(shè)計(jì)這樣一個(gè)結(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é)點(diǎn)中的A, B, C, D。next是指針類型的成員,它指向Student類型數(shù)據(jù)(就是next所在的結(jié)構(gòu)體類型)。用這種方法就可以建立鏈表。見(jiàn)圖。

圖中每一個(gè)結(jié)點(diǎn)都屬于Student類型,在它的成員next中存放下一個(gè)結(jié)點(diǎn)的地址,程序設(shè)計(jì)者不必知道各結(jié)點(diǎn)的具體地址,只要保證能將下一個(gè)結(jié)點(diǎn)的地址放到前一結(jié)點(diǎn)的成員next中即可。
下面通過(guò)一個(gè)例子來(lái)說(shuō)明如何建立和輸出一個(gè)簡(jiǎn)單鏈表。
【例】建立一個(gè)如圖所示的簡(jiǎn)單鏈表,它由3個(gè)學(xué)生數(shù)據(jù)的結(jié)點(diǎn)組成。輸出各結(jié)點(diǎn)中的數(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; //對(duì)結(jié)點(diǎn)a的num和score成員賦值
b. num=31003;
b.score=90; //對(duì)結(jié)點(diǎn)b的num和score成員賦值
c. num=31007;
c.score=85; //對(duì)結(jié)點(diǎn)c的num和score成員賦值
head=&a; //將結(jié)點(diǎn)a的起始地址賦給頭指針head
a.next=&b; //將結(jié)點(diǎn)b的起始地址賦給a結(jié)點(diǎn)的next成員
b.next=&c; //將結(jié)點(diǎn)c的起始地址賦給b結(jié)點(diǎn)的next成員
c.next=NULL; //結(jié)點(diǎn)的next成員不存放其他結(jié)點(diǎn)地址
p=head; //使p指針指向a結(jié)點(diǎn)
do
{
cout<<p->num<<" "<<p->score<<endl; //輸出p指向的結(jié)點(diǎn)的數(shù)據(jù)
p=p->next; //使p指向下一個(gè)結(jié)點(diǎn)
} while (p!=NULL); //輸出完c結(jié)點(diǎn)后p的值為NULL
return 0;
}
本例是比較簡(jiǎn)單的,所有結(jié)點(diǎn)(結(jié)構(gòu)體變量)都是在程序中定義的,不是臨時(shí)開(kāi)辟的,也不能用完后釋放,這種鏈表稱為靜態(tài)鏈表。對(duì)各結(jié)點(diǎn)既可以通過(guò)上一個(gè)結(jié)點(diǎn)的next指針去訪問(wèn),也可以直接通過(guò)結(jié)構(gòu)體變量名a, b, c去訪問(wèn)。
動(dòng)態(tài)鏈表則是指各結(jié)點(diǎn)是可以隨時(shí)插入和刪除的,這些結(jié)點(diǎn)并沒(méi)有變量名,只能先找到上一個(gè)結(jié)點(diǎn),才能根據(jù)它提供的下一結(jié)點(diǎn)的地址找到下一個(gè)結(jié)點(diǎn)。只有提供第一個(gè)結(jié)點(diǎn)的地址,即頭指針head,才能訪問(wèn)整個(gè)鏈表。如同一條鐵鏈一樣,一環(huán)扣一環(huán),中間是不能斷開(kāi)的。
建立動(dòng)態(tài)鏈表,要用到后面介紹的動(dòng)態(tài)分配內(nèi)存的運(yùn)算符new和動(dòng)態(tài)撤銷內(nèi)存的運(yùn)算符delete。
相關(guān)文章
C++獲得本機(jī)所有網(wǎng)卡的IP和MAC地址信息的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇C++獲得本機(jī)所有網(wǎng)卡的IP和MAC地址信息的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-10-10
完美解決QT?QGraphicsView提升到QChartView報(bào)錯(cuò)的問(wèn)題
使用QT提供的QChartView來(lái)繪制圖表,提升QGraphicsView控件繼承QChartView后,然后將QGraphicsView提升到我們自己寫的類,怎么才能確保提升后編譯不報(bào)錯(cuò)呢,下面小編給大家?guī)?lái)了QT QGraphicsView 提升到QChartView報(bào)錯(cuò)解決方案,感興趣的朋友一起看看吧2023-05-05
C語(yǔ)言容易被忽視的函數(shù)設(shè)計(jì)原則基礎(chǔ)
C語(yǔ)言的設(shè)計(jì)目標(biāo)是提供一種能以簡(jiǎn)易的方式編譯、處理低級(jí)存儲(chǔ)器、產(chǎn)生少量的機(jī)器碼以及不需要任何運(yùn)行環(huán)境支持便能運(yùn)行的編程語(yǔ)言.那么C語(yǔ)言函數(shù)設(shè)計(jì)的一般原則和技巧都是怎樣的呢,下面帶你了解2022-04-04
Java C++ 題解leetcode857雇傭K名工人最低成本vector pair
這篇文章主要為大家介紹了Java C++ 題解leetcode857雇傭K名工人最低成本vector pair示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
C語(yǔ)言中for循環(huán)問(wèn)題(一個(gè)小坑需注意)
這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中for循環(huán)問(wèn)題的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
解析C++中構(gòu)造函數(shù)的默認(rèn)參數(shù)和構(gòu)造函數(shù)的重載
這篇文章主要介紹了解析C++中構(gòu)造函數(shù)的默認(rèn)參數(shù)和構(gòu)造函數(shù)的重載,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-09-09

