吳昊 朱林麗
[摘 要]本文主要對C程序中引用結(jié)構(gòu)體類型數(shù)據(jù)中成員的一些方法做了比較詳細(xì)的探討,分析了使用結(jié)構(gòu)體變量和指針變量引用成員的區(qū)別,并結(jié)合具體案例,讓初學(xué)者對結(jié)構(gòu)體成員的引用有進(jìn)一步認(rèn)識。
[關(guān)鍵詞]C程序;結(jié)構(gòu)體變量;指針變量;成員
doi:10.3969/j.issn.1673 - 0194.2021.04.105
[中圖分類號]G642[文獻(xiàn)標(biāo)識碼]A[文章編號]1673-0194(2021)04-0-02
0 ? ? 引 言
結(jié)構(gòu)體類型是C語言程序設(shè)計課程中比較重要的一種構(gòu)造性數(shù)據(jù)類型,這種數(shù)據(jù)類型是由多個成員構(gòu)成,一般用來定義結(jié)點(diǎn)型的數(shù)據(jù)類型。雖然結(jié)構(gòu)體類型的數(shù)據(jù)中所有的成員是一個整體,但對成員不可以整體訪問,只能單獨(dú)訪問。一般對成員的訪問有兩種方式,一種是使用“.”,一種是使用“->”。然而在實(shí)際的教學(xué)中,有許多學(xué)生容易混淆這兩種引用方式,不能很好地理解結(jié)構(gòu)體變量和結(jié)構(gòu)體指針變量在訪問成員時的具體指向,從而導(dǎo)致學(xué)生在編寫涉及結(jié)構(gòu)體數(shù)據(jù)類型的程序時遇到許多麻煩。為了幫助初學(xué)者在學(xué)習(xí)C語言程序設(shè)計這門課程時,能夠?qū)νㄟ^結(jié)構(gòu)體變量引用成員和通過結(jié)構(gòu)體指針變量引用成員這兩種方式有更深的了解,本文將做比較詳細(xì)的探討。
1 ? ? 結(jié)構(gòu)體類型
1.1 ? 結(jié)構(gòu)體數(shù)據(jù)類型的聲明
結(jié)構(gòu)體數(shù)據(jù)類型與基本的數(shù)據(jù)類型(如整形、字符型、浮點(diǎn)型)是有區(qū)別的,基本的數(shù)據(jù)類型是由系統(tǒng)定義的,用戶可以直接使用,而結(jié)構(gòu)體數(shù)據(jù)類型是由用戶根據(jù)解決問題的實(shí)際需要自己聲明[2]。聲明結(jié)構(gòu)體數(shù)據(jù)類型的一般形式如下。
struct 結(jié)構(gòu)體名
{ 成員表列 };
例如,一名學(xué)生包含學(xué)號、姓名、性別、年齡和專業(yè)等一些基本信息,則聲明學(xué)生結(jié)構(gòu)體數(shù)據(jù)類型如下。
struct ?student
{
int ?num; ? ? ? ? //學(xué)號
char ?name[10]; ? //姓名
char ?sex; ? ? ? ?//性別
int ?age; ? ? ? ? //年齡
char ?pro[20]; ? ?//專業(yè)
};
1.2 ? 結(jié)構(gòu)體變量和結(jié)構(gòu)體指針變量的定義
聲明好結(jié)構(gòu)體數(shù)據(jù)類型以后,就可以使用它來定義結(jié)構(gòu)體變量或結(jié)構(gòu)體指針變量。例如,利用上面已經(jīng)聲明好的學(xué)生結(jié)構(gòu)體數(shù)據(jù)類型來定義結(jié)構(gòu)體變量p和指針變量q的形式為:
struct ?student ?p, *q;
此外,還可以在聲明類型的同時定義變量或指針變量,因此,利用學(xué)生結(jié)構(gòu)體數(shù)據(jù)類型定義結(jié)構(gòu)體變量p和指針變量q,還可以表示為:
struct ?student
{
int ?num;
char ?name[10];
char ?sex;
int ?age;
char ?pro[20];
} p, *q;
2 ? ? 引用結(jié)構(gòu)體數(shù)據(jù)成員的方法
定義好結(jié)構(gòu)體變量或指針變量以后,就可以通過它們來引用結(jié)構(gòu)體數(shù)據(jù)中的成員,引用結(jié)構(gòu)體數(shù)據(jù)成員主要有以下3種方法。
2.1 ? 通過結(jié)構(gòu)體變量來引用成員
使用結(jié)構(gòu)體變量來引用成員是通過“.”來實(shí)現(xiàn)的,且它引用的是自己的成員,如文中第二部分定義的p是一個結(jié)構(gòu)體變量,引用結(jié)構(gòu)體變量p中的成員可表示:p.num,p.name,p.sex,p.age,p.pro。
2.2 ? 通過結(jié)構(gòu)體指針變量和“->”來引用成員
結(jié)構(gòu)體指針變量只能存儲和它同類型的變量或存儲單元的地址,它沒有自己的成員,在使用結(jié)構(gòu)體指針變量之前,必須把同類型的變量的地址或動態(tài)創(chuàng)建的同類型的存儲單元(用malloc函數(shù)創(chuàng)建)的地址賦值給它,讓它有所指向,否則使用結(jié)構(gòu)體指針變量是無意義的。當(dāng)結(jié)構(gòu)體指針變量有指向以后,可以通過“->”來引用指針變量所指向的變量或存儲單元中的成員。如文中第二部分定義的q是一個結(jié)構(gòu)體指針變量,而p是一個結(jié)構(gòu)體變量,如果把p的地址賦值給q(即q=& p),則可通過q來引用p中的成員,使用q來引用結(jié)構(gòu)體變量p中的成員可表示為:q->num,q->name,q->sex,q->age,q->pro。
2.3 ? 通過結(jié)構(gòu)體指針變量和“.”來引用成員
當(dāng)把變量的地址賦值給同類型的指針變量以后(指針變量指向該變量),“*指針變量”和“變量”的作用是一樣的,如文中第二部分定義的變量p和指針變量q,如果把p的地址賦值給q(即q=& p),則*q的作用相當(dāng)于p,使用q來引用結(jié)構(gòu)體變量p中的成員可表示為:(*q).num,(*q).name,(*q).sex,(*q).age,(*q).pro。(注:在C語言程序中,由于“.”的優(yōu)先級比“*”的優(yōu)先級高,故*q外面的括號不可以省略)
3 ? ? 具體的案例實(shí)現(xiàn)
以創(chuàng)建一個具有三個結(jié)點(diǎn)的單鏈表為例,分別介紹以結(jié)構(gòu)體變量創(chuàng)建、結(jié)構(gòu)體變量加指針變量創(chuàng)建以及結(jié)構(gòu)體變量加動態(tài)開辟存儲單元創(chuàng)建的3種情況,單鏈表的結(jié)點(diǎn)是一個結(jié)構(gòu)體類型,主要包括整形的數(shù)據(jù)成員和指針成員,結(jié)點(diǎn)的結(jié)構(gòu)體類型聲明如下。
struct ?node
{
int ?data;
struct ?node ?*next;
};
3.1 ? 結(jié)構(gòu)體變量創(chuàng)建單鏈表
void main()
{
struct ?node ?a1,a2,a3;
scanf(“%d%d%d”,&a1.data, &a2.data, &a3.data);
a1.next=&a2; ?//把a(bǔ)2鏈在a1的后面
a2.next=&a3; ?//把a(bǔ)3鏈在a2的后面
a3.next=NULL; //最后一個結(jié)點(diǎn)的指針成員賦值為空
}
注:a1,a2,a3定義的是結(jié)構(gòu)體變量,所以在程序中都是用“.”來引用成員
3.2 ? 結(jié)構(gòu)體變量加指針變量創(chuàng)建單鏈表
void main()
{
struct ?node ?a1,a2,a3,*t1,*t2,*t3;
t1=&a1; ?t2=&a2; ? t3=&a3; ?//分別把a(bǔ)1、a2、a3的地址賦值給t1、t2、t3
scanf(“%d%d%d”,&t1->data, &t2->data, &t3->data);
t1->next=t2; ?//把t2所指結(jié)點(diǎn)鏈在t1所指向結(jié)點(diǎn)之后
t2->next=t3; ?//把t3所指結(jié)點(diǎn)鏈在t2所指向結(jié)點(diǎn)之后
t3->next=NULL; //最后一個結(jié)點(diǎn)的指針成員賦值為空
}
注:t1,t2,t3定義的是結(jié)構(gòu)體指針變量,所以在程序中都是用“->”來引用成員
3.3 ? 結(jié)構(gòu)體變量加動態(tài)開辟存儲單元創(chuàng)建單鏈表
void main()
{
/* h和r分別指向鏈表的頭結(jié)點(diǎn)和最后一個結(jié)點(diǎn),t指向新建的結(jié)點(diǎn)*/
struct ?node ?*t,*r,*h;
int ?i=1;
while(i<=3) ?//判斷循環(huán)的次數(shù)
{
t=(* struct ?node)malloc(sizeof(struct ?node)); ?//新建一個結(jié)點(diǎn)
scanf(“%d”,&t->data);
if(i==1) ?//如果創(chuàng)建的是第一個結(jié)點(diǎn)
{
h=r=t; ?// h和r都指向該結(jié)點(diǎn)
continue;
}
r->next=t; ?//把t所指向的結(jié)點(diǎn)插到r所指向結(jié)點(diǎn)的后面
r=t; ? ?//讓r重新指向鏈表中最后一個結(jié)點(diǎn)
}
r->next=NULL; ?//最后一個結(jié)點(diǎn)的指針成員賦值為空
}
注:t,r,h定義的是結(jié)構(gòu)體指針變量,所以在程序中都是用“->”來引用成員
以上3種方法雖然都可以創(chuàng)建一個具有三個結(jié)點(diǎn)的單鏈表,但不難發(fā)現(xiàn),第一、第二兩種方法在創(chuàng)建單鏈表時需要定義結(jié)構(gòu)體變量,鏈表中有多少個結(jié)點(diǎn)就需要定義多少個結(jié)構(gòu)體變量,而第三種方法不需要定義結(jié)構(gòu)體變量,只需使用malloc函數(shù)創(chuàng)建結(jié)點(diǎn)即可,需要多少建多少,程序設(shè)計比前兩種方法要靈活許多。
4 ? ? 結(jié) 語
本文主要對C程序中使用結(jié)構(gòu)體變量和指針變量來引用成員的兩種情況做了較詳細(xì)的分析和總結(jié),在引用結(jié)構(gòu)體成員時,一定要注意變量引用和指針變量引用兩者之間的區(qū)別,即變量引用成員使用的是“.”,用的是自己的成員,而指針變量可以使用 “->”或 “(*指針變量).成員”的方式來引用它所指向的結(jié)構(gòu)體變量或存儲單元的成員,用的不是自己的成員。
主要參考文獻(xiàn)
[1]譚浩強(qiáng).C程序設(shè)計[M].第5版.北京:清華大學(xué)出版社,2017:309-314.
[2]王敬.用C語言結(jié)構(gòu)體類型指針實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)鏈表操作[J].數(shù)字技術(shù)與應(yīng)用,2013(4):165-166.