国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

C語言指針導(dǎo)學(xué)(5)——指針與結(jié)構(gòu)

2019-11-06 06:03:47
字體:
供稿:網(wǎng)友
 

C語言指針導(dǎo)學(xué)(5)——指針與結(jié)構(gòu)

  ——理解C++和數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ)

指針不僅可以指向變量、數(shù)組、函數(shù),還可以和結(jié)構(gòu)(structure)聯(lián)系起來,這使得C語言的威力倍增,初學(xué)C語言的朋友對(duì)結(jié)構(gòu)可能不太重視,對(duì)它的理解也不夠深入,但事實(shí)上,結(jié)構(gòu)是一個(gè)非常重要的工具,有了它我們可以很輕松的構(gòu)建一些僅靠其它C語言特性做起來很復(fù)雜的程序。深入地理解結(jié)構(gòu)會(huì)對(duì)你理解C++的面向?qū)ο笥泻艽髱椭⑶視?huì)讓在你學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)時(shí)有一份愜意的心情。(本講中默認(rèn)讀者已經(jīng)對(duì)結(jié)構(gòu)有了基本的認(rèn)識(shí))

附:在本講的最后,會(huì)提供上一講復(fù)雜聲明的答案。

1.深入理解結(jié)構(gòu)

<1>.為什么需要結(jié)構(gòu)

C語言中有很多內(nèi)置類型,如int型、double型、char型等,但僅僅使用這些類型并不能很好地表達(dá)我們的意圖。假如我們想表示一輛汽車,汽車有很多自身的屬性,如:最大功率、車重、顏色、最高時(shí)速、價(jià)格等等。這些屬性都應(yīng)該和汽車緊密相連,我們每構(gòu)造一輛車時(shí),這些固有的屬性都應(yīng)該一并被定義。有了這種需求,就催生了結(jié)構(gòu)。結(jié)構(gòu)有時(shí)也被翻譯為結(jié)構(gòu)體。當(dāng)我們定義了一個(gè)結(jié)構(gòu)后,就意味著定義了一種新的類型,結(jié)構(gòu)是C語言中為數(shù)不多的能讓我們自己掌控所定義類型的語言特性,在C中使用結(jié)構(gòu)可以把不同類型的值存儲(chǔ)在一起。

<2>.使用結(jié)構(gòu)

首先看一個(gè)例子,我將用這個(gè)例子貫穿本講的內(nèi)容:

struct car

{

char name[50];

int max_power;

      int weight;

      char color[20];

      int max_speed;

      int PRice;

      struct car *next;

} one_car, famous_cars[12];

關(guān)鍵字struct表示將要定義一個(gè)結(jié)構(gòu),編譯器會(huì)將從struct直到分號(hào)為止的部分識(shí)別為一個(gè)結(jié)構(gòu)。花括號(hào)中存放我們要進(jìn)行組合的內(nèi)容,car是一個(gè)可選(optional)的結(jié)構(gòu)標(biāo)簽(tag),也叫結(jié)構(gòu)名,有了這個(gè)標(biāo)簽我們就可以在將來的程序中用struct car作為struct{int max_power; int weight; char color[20]; int max_kph; float price;}的簡(jiǎn)寫形式。右花括號(hào)后的one_car是一個(gè)structcar類型的變量,而famous_cars[12]是一個(gè)數(shù)組,這個(gè)數(shù)組包含了20個(gè)structcar類型的元素。

結(jié)構(gòu)中的所有內(nèi)容都稱作成員,所有成員必須在結(jié)構(gòu)的內(nèi)部聲明,一旦結(jié)構(gòu)定義完成后,就沒有任何辦法可以增加成員了。當(dāng)定義了一個(gè)結(jié)構(gòu)后不僅定義了一個(gè)新的類型,同時(shí)也定義了一個(gè)新的作用域,在struct car中有7個(gè)成員,這些成員的作用范圍只是這個(gè)結(jié)構(gòu)中,我們?cè)诮Y(jié)構(gòu)外是看不到也用不了的,如果想用怎么辦呢。可以通過成員操作符(.)來訪問結(jié)構(gòu)中的成員。(.)的左操作數(shù)是結(jié)構(gòu)變量名,右操作數(shù)是成員名,如果我想把one_car的顏色設(shè)置成紅色,那么可以寫one_car.color= "red";現(xiàn)在我還想將12輛名車中的第一輛車的價(jià)格調(diào)整到525萬元,如:famous_cars[0].price = 525;此時(shí)的famous_cars[0]和one_car是同一類的對(duì)象,都是struct car類型的變量,只不過famous_cars[0]是隸屬于famous_cars[12]這個(gè)數(shù)組的一個(gè)元素,而one_car是個(gè)自由身罷了。

<3>.結(jié)構(gòu)的自引用

大家應(yīng)該早已注意到struct car中的最后一個(gè)成員struct car *next了,有些朋友對(duì)此不太理解。結(jié)構(gòu)可以包含任意類型的成員,包括其他類型的結(jié)構(gòu),當(dāng)然也可以包含自身類型的結(jié)構(gòu),但在定義這種結(jié)構(gòu)時(shí),只能寫成包含指向自身類型的指針,而不能寫成以下這種形式:

struct car

{

 char name[50];

 int max_power;

       int weight;

       char color[20];

       int max_speed;

       int price;

 struct car next;     //錯(cuò),此時(shí)類型不完整,不能包含自身類型的變量

};

因?yàn)閚ext是另一個(gè)完整的結(jié)構(gòu)變量,它的內(nèi)部同樣會(huì)包含一個(gè)成員struct car next,這個(gè)成員還會(huì)包括一個(gè)成員struct car next,如此下去永無休止,編譯器將無法確定這個(gè)結(jié)構(gòu)struct car的大小。為了解決這個(gè)問題,我們可以把第一個(gè)成員聲明為struct car *next;,一個(gè)struct car結(jié)構(gòu)的指針就是用來存儲(chǔ)同類型結(jié)構(gòu)變量的地址的,是有固定長度的,此時(shí)編譯器可以輕松確定struct car的大小。

2.指向結(jié)構(gòu)的指針

剛剛說過的struct car *next就是一個(gè)指向結(jié)構(gòu)的指針,它既可以在結(jié)構(gòu)內(nèi)作為一個(gè)結(jié)構(gòu)成員,也可以作為一個(gè)自由的對(duì)象出現(xiàn)在結(jié)構(gòu)定義后面的任何地方,現(xiàn)在我們?cè)賮矶x一個(gè)指向struct car類型的指針car_pointer:structcar *car_pointer = &one_car;。現(xiàn)在我們擁有了一個(gè)指向結(jié)構(gòu)的指針,如何通過這個(gè)指針來訪問結(jié)構(gòu)變量中的成員呢?同樣是通過解引用操作符,比如現(xiàn)在想將one_car的發(fā)動(dòng)機(jī)進(jìn)行調(diào)教,把最大功率增加100千瓦:(*car_pointer).max_power += 100;首先通過*操作符獲取結(jié)構(gòu)變量one_car,然后再對(duì)它的max_power成員進(jìn)行修改。特別要注意括號(hào)不能丟,因?yàn)槌蓡T操作符.的優(yōu)先級(jí)高于*操作符,如果沒有括號(hào)的話將會(huì)導(dǎo)致錯(cuò)誤。正是由于這個(gè)有些令人厭煩的訪問方式,C語言提供了更加快捷且易于理解的方式——(->)操作符。通過這個(gè)操作符,我們就無需再受丟括號(hào)的困擾了。 -> 操作符和 操作符具有同樣的優(yōu)先級(jí)。使用方法:car_pointer-> max_power += 100;

3.鏈?zhǔn)酱鎯?chǔ)

有了以上的基礎(chǔ),現(xiàn)在可以來討論通過結(jié)構(gòu)與指向結(jié)構(gòu)的指針構(gòu)建的一種存儲(chǔ)數(shù)據(jù)的方式——鏈?zhǔn)酱鎯?chǔ)了。假設(shè)現(xiàn)在要組織一次名車的巡礼活動(dòng),車輛的排列順序按品牌的字典序進(jìn)行。為了保證車隊(duì)的連貫性,車與車之間通過繩索連接起來。這幅圖景如果用程序來表現(xiàn)是這樣的:

#include <stdio.h>

#include <stdlib.h>

 

struct car

{

   char name[50];

   int max_power;

   int weight;

   char color[20];

   int max_speed;

   int price;

   struct car *next;

};

 

int main()

{

   int i = 0;

   struct car*car_pointer = (struct car *)malloc(sizeof(struct car));

   struct car *record = car_pointer;

   struct car *remove = car_pointer;

   struct car *current = car_pointer;

   for (i; i < 2; i++)

   {

       car_pointer->next = (struct car *)malloc(sizeof(structcar));

       printf("Please input car's name : ");

       scanf("%s",car_pointer->name);

       printf("%s's max_power : ",car_pointer->name);

       scanf("%d",&car_pointer->max_power);

       printf("%s's weight : ",car_pointer->name);

       scanf("%d",&car_pointer->weight);

       printf("%s's color : ",car_pointer->name);

       scanf("%s",car_pointer->color);

       printf("%s's max_speed : ",car_pointer->name);

       scanf("%d",&car_pointer->max_speed);

       printf("%s's price : ",car_pointer->name);

       scanf("%d",&car_pointer->price);

       printf("/n");

       car_pointer = car_pointer->next;

   }

   car_pointer->next =NULL;

 

   printf("巡礼車輛如下:/n");

   for (record;record->next != NULL; record = record->next)

   {

       printf("%s/n",record->name);

       printf("%s's max_power : %dKW/n", record->name, record->max_power);

       printf("%s's weight : %dKG/n", record->name, record->weight);

       printf("%s's color : %s/n",record->name, record->color);

       printf("%s's max_speed : %dKM/H/n", record->name, record->max_speed);

       printf("%s's price : %d萬元(¥)/n",record->name, record->price);

       printf("/n");

   }

 

   while(current->next != NULL)

   {

       remove = current;

       current = current->next;

       free(remove);

   }

   return 0;

}

首先,我們定義一個(gè)結(jié)構(gòu),然后在主函數(shù)中開辟一段能容納結(jié)構(gòu)struct car的內(nèi)存,并定義一個(gè)指向此結(jié)構(gòu)類型的指針car_pointer將其指向剛才所開辟的內(nèi)存空間。接下來定義幾個(gè)同類型的指針并初始化為car_pointer留作他用。在鏈?zhǔn)酱鎯?chǔ)中,每一塊這樣的內(nèi)存空間都被稱作結(jié)點(diǎn),代表著鏈中的一個(gè)實(shí)體。接下來的for循環(huán)用來控制創(chuàng)建多少個(gè)結(jié)點(diǎn),每一次循環(huán),都創(chuàng)建一個(gè)新的結(jié)點(diǎn),并用前一個(gè)結(jié)點(diǎn)的next成員指向新創(chuàng)建的結(jié)點(diǎn),再通過相應(yīng)的輸入來初始化每個(gè)結(jié)點(diǎn)的各個(gè)成員。在循環(huán)結(jié)束后,將最后一個(gè)結(jié)點(diǎn)的next成員置為NULL。

然后,用先前創(chuàng)建的指針record來控制這個(gè)車隊(duì)的輸出,因?yàn)榇藭r(shí)car_pointer已經(jīng)走到了車隊(duì)的末尾,無法再用它從頭進(jìn)行遍歷了。

最后將動(dòng)態(tài)分配的內(nèi)存釋放掉。注意此時(shí)同樣需要另一個(gè)指向車隊(duì)頭部的指針current,用來遍歷車隊(duì)鏈表,并創(chuàng)建一個(gè)remove指針指向要?jiǎng)h除的結(jié)點(diǎn)。如果我們不設(shè)置remove指針而是直接將current所指的結(jié)點(diǎn)釋放掉,就找不到下一個(gè)結(jié)點(diǎn)了。本例使用鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)所創(chuàng)建的車隊(duì)鏈表如下圖所示:

4.用typedef給結(jié)構(gòu)創(chuàng)建別名

本將的最后一個(gè)話題,我們?cè)賮碚務(wù)則ypedef。關(guān)鍵字typedef用來給一種類型起一個(gè)別名,理所當(dāng)然地可以給一個(gè)結(jié)構(gòu)類型定義一個(gè)別名,用法上沒有什么區(qū)別。如果想給struct car定義一個(gè)別名Car可以這樣處理:

typedef struct car

{

   char name[50];

   int max_power;

   int weight;

   char color[20];

   int max_speed;

   int price;

   struct car *next;

} Car;

通過typedef引入Car這個(gè)名字作為struct car {……}的簡(jiǎn)寫形式。此后我們就可以用Car來定義變量了,如Car one_car;或Car famous_cars[12]; 當(dāng)然也可以按如下的方式來起別名,而且會(huì)更清晰易讀:

struct car         

{

   char name[50];

   int max_power;

   int weight;

   char color[20];

   int max_speed;

   int price;

   struct car *next;

};

typedef struct car Car;

typedef struct car *CarPointer;

此時(shí)的CarPointer是struct car *類型的別名,即指向struct car的指針類型。理解了這種表示法對(duì)于理解C++中的類是很有幫助的。

差一點(diǎn)兒忘了,在第四講中復(fù)雜聲明還有懸而未決的問題,現(xiàn)在給出解答,如果有不明白或者有興趣深入研究的朋友可以聯(lián)系我:郵箱:porscheyin@hotmail.com,以下是原題及答案:

1.  int *( *( *a[5]) ( ) ) ( );

Answer:a是一個(gè)數(shù)組,它的5個(gè)元素都是指向函數(shù)的指針,該函數(shù)仍舊返回一個(gè)指向函數(shù)的指針。

2.  void * (*b) ( char, int (*) ( ) );

Answer:b是一個(gè)函數(shù)指針,該函數(shù)接受兩個(gè)形參,分別是char型和一個(gè)函數(shù)指針,返回值類型為void *。

3.  float ( *(*c[10]) (int *) ) [5]; 

Answer:c是一個(gè)數(shù)組,它的10個(gè)元素都是指向函數(shù)的指針,所指函數(shù)接受int *型形參并返回一個(gè)指向數(shù)組的指針,這個(gè)數(shù)組包含5個(gè)float元素。

4.  int ( *(*d)[2][3] ) [4][5];

Answer:d是一個(gè)指向數(shù)組的指針,此數(shù)組的元素又是一個(gè)指向數(shù)組的指針。

5.  int (*(*(*e) ( int* ))[15]) (int*);

Answer:e是一個(gè)函數(shù)指針,該函數(shù)的返回值是一個(gè)指向數(shù)組的指針,所指向數(shù)組的元素又是函數(shù)指針,指向的函數(shù)具有int *型形參,返回值類型為int。

6.  int ( *(*f[4][5][6]) (int*) ) [10];

Answer:f是一個(gè)數(shù)組,這個(gè)數(shù)組的元素是函數(shù)指針,這類函數(shù)具有int *型形參并返回指向數(shù)組的指針,所指向的數(shù)組的元素是具有10個(gè)int型元素。

7.  int *(*(*(*g)( ))[10]) ( );

Answer:g是個(gè)指向函數(shù)的指針,它所指向的函數(shù)返回一個(gè)指向包含10個(gè)元素的數(shù)組的指針,數(shù)組元素的類型是指向函數(shù)的指針,所指向的函數(shù)不接受參數(shù)且返回值類型為int *。

 

另外,對(duì)于本講中的巡礼車隊(duì)程序,如果進(jìn)行相應(yīng)輸入后,會(huì)得到類似下面的輸出。我選了一些最新的世界知名車輛,它們的品牌與第四講中指針數(shù)組例子中的車輛品牌一致,我只是在每個(gè)品牌中選了一個(gè)車系,下面是輸出結(jié)果:

巡礼車輛如下:

ASTON-MATIN--DB9

ASTON-MATIN--DB9's max_power : 335KW

ASTON-MATIN--DB9's weight : 1760 KG

ASTON-MATIN--DB9's color : GREEN

ASTON-MATIN--DB9's max_speed : 300 KM/H

ASTON-MATIN--DB9's price : 304萬元(¥)

 

AUDI--R8

AUDI--R8's max_power : 309 KW

AUDI--R8's weight : 1560 KG

AUDI--R8's color : SILVER

AUDI--R8's max_speed : 301 KM/H

AUDI--R8's price : 180萬元(¥)

 

BENZ--SLR-722

BENZ--SLR-722's max_power : 478 KW

BENZ--SLR-722's weight : 1550 KG

BENZ--SLR-722's color : BLACK

BENZ--SLR-722's max_speed : 337 KM/H

BENZ--SLR-722's price : 888萬元(¥)

 

BENTLEY--CONTINENTAL-GTC

BENTLEY--CONTINENTAL-GTC'smax_power : 411 KW

BENTLEY--CONTINENTAL-GTC's weight: 2495 KG

BENTLEY--CONTINENTAL-GTC's color :AZURE

BENTLEY--CONTINENTAL-GTC'smax_speed : 312 KM/H

BENTLEY--CONTINENTAL-GTC's price :358萬元(¥)

 

BMW--M6

BMW--M6's max_power : 373 KW

BMW--M6's weight : 1785 KG

BMW--M6's color : BLUE

BMW--M6's max_speed : 250 KM/H

BMW--M6's price : 229萬元(¥)

 

BUGATTI--VEYRON-16.4

BUGATTI--VEYRON-16.4's max_power :736 KW

BUGATTI--VEYRON-16.4's weight : 1888 KG

BUGATTI--VEYRON-16.4's color :RED&BLACK

BUGATTI--VEYRON-16.4's max_speed :407 KM/H

BUGATTI--VEYRON-16.4's price :2500萬元(¥)

 

FERRARI--599GTB

FERRARI--599GTB's max_power : 456KW

FERRARI--599GTB's weight : 1690 KG

FERRARI--599GTB's color : RED

FERRARI--599GTB's max_speed : 330 KM/H

FERRARI--599GTB's price : 376萬元(¥)

 

JAGUAR--XK

JAGUAR--XK's max_power : 224 KW

JAGUAR--XK's weight : 1595 KG

JAGUAR--XK's color : GREEN

JAGUAR--XK's max_speed : 250 KM/H

JAGUAR--XK's price : 142萬元(¥)

 

LAMBORGHINI--MURCIELAGO-LP640

LAMBORGHINI--MURCIELAGO-LP640'smax_power : 471 KW

LAMBORGHINI--MURCIELAGO-LP640'sweight : 1665 KG

LAMBORGHINI--MURCIELAGO-LP640'scolor : BLACK

LAMBORGHINI--MURCIELAGO-LP640'smax_speed : 340 KM/H

LAMBORGHINI--MURCIELAGO-LP640'sprice : 438萬元(¥)

 

MASERATI--GRANTURISMO

MASERATI--GRANTURISMO's max_power: 298 KW

MASERATI--GRANTURISMO's weight : 1955 KG

MASERATI--GRANTURISMO's color :RED

MASERATI--GRANTURISMO's max_speed: 285 KM/H

MASERATI--GRANTURISMO's price :219萬元(¥)

 

MAYBACH--62S

MAYBACH--62S's max_power : 450 KW

MAYBACH--62S's weight : 2855 KG

MAYBACH--62S's color : WHITE

MAYBACH--62S's max_speed : 250 KM/H

MAYBACH--62S's price : 900萬元(¥)

 

ROLLS-ROYCE--PHANTOM-101EX

ROLLS-ROYCE--PHANTOM-101EX'smax_power : 338 KW

ROLLS-ROYCE--PHANTOM-101EX'sweight : 2590 KG

ROLLS-ROYCE--PHANTOM-101EX's color: BLUE

ROLLS-ROYCE--PHANTOM-101EX'smax_speed : 250 KM/H

ROLLS-ROYCE--PHANTOM-101EX's price: 680萬元(¥)


上一篇:Go Interface

下一篇:OC--面向?qū)ο?/a>

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 桦甸市| 嵊州市| 思茅市| 大田县| 和平区| 临江市| 东兰县| 怀宁县| 利川市| 繁峙县| 香格里拉县| 西贡区| 民乐县| 哈密市| 宝应县| 博乐市| 龙山县| 吉林省| 连山| 镇赉县| 南丹县| 会泽县| 大洼县| 如东县| 天柱县| 东港市| 台前县| 郧西县| 开化县| 济阳县| 洞口县| 建昌县| 佛冈县| 巨野县| 望都县| 通河县| 汕尾市| 横山县| 怀安县| 石嘴山市| 石嘴山市|