《C語(yǔ)言程序設(shè)計(jì) 》課件第8章_第1頁(yè)
《C語(yǔ)言程序設(shè)計(jì) 》課件第8章_第2頁(yè)
《C語(yǔ)言程序設(shè)計(jì) 》課件第8章_第3頁(yè)
《C語(yǔ)言程序設(shè)計(jì) 》課件第8章_第4頁(yè)
《C語(yǔ)言程序設(shè)計(jì) 》課件第8章_第5頁(yè)
已閱讀5頁(yè),還剩135頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第8章指針8.1地址、指針與指針變量的基本概念8.2指針變量的定義、賦值和引用8.3數(shù)組指針和指向數(shù)組的指針變量8.4指針與函數(shù)8.5指針的指針8.6動(dòng)態(tài)內(nèi)存分配與指向它的指針變量本章小結(jié)

8.1地址、指針與指針變量的基本概念

8.1.1地址與指針

指針類型數(shù)據(jù)是一種與內(nèi)存相關(guān)的數(shù)據(jù)。要了解指針類型數(shù)據(jù),首先要了解計(jì)算機(jī)的內(nèi)存及內(nèi)存地址這兩個(gè)概念。程序處理的數(shù)據(jù)保存在內(nèi)存中。內(nèi)存是由許多順序排列的存儲(chǔ)單元組成的,一般把存儲(chǔ)器中的一個(gè)存儲(chǔ)單位稱為一個(gè)字節(jié)或內(nèi)存單元。而每一個(gè)內(nèi)存單元都有一個(gè)編號(hào),被稱為“內(nèi)存地址”。對(duì)內(nèi)存數(shù)據(jù)的訪問都通過地址進(jìn)行,程序的變量所占用的內(nèi)存單元的地址就叫變量的指針。使用高級(jí)語(yǔ)言變量掩蓋了內(nèi)存單元、地址等低級(jí)概念,使我們編寫程序時(shí)不必關(guān)心實(shí)現(xiàn)細(xì)節(jié),但實(shí)際上它在程序執(zhí)行的過程中發(fā)揮了巨大的作用。例如,在下面程序段中:

inti;

i=3;

printf("%d",i);當(dāng)程序開始執(zhí)行后,系統(tǒng)首先為變量i分配了地址為2000和2001的存儲(chǔ)單元,如圖8-1所示。然后,當(dāng)執(zhí)行語(yǔ)句“i=3;”時(shí),系統(tǒng)就將二進(jìn)制數(shù)的3存放到變量i所對(duì)應(yīng)的內(nèi)存單元中。最后,在執(zhí)行輸出語(yǔ)句時(shí),系統(tǒng)同樣到該地址處將變量i的值取出并輸出??梢?,程序?qū)ψ兞康乃性L問都與變量的地址有關(guān)。圖8-1變量地址8.1.2指針變量

在C語(yǔ)言中,允許用一個(gè)變量來存放指針,這種變量稱為指針變量。因此,一個(gè)指針變量的值就是某個(gè)內(nèi)存單元的地址或某內(nèi)存單元的指針。例如,將上例中變量i的地址放入另外的變量P中,當(dāng)需要訪問變量i時(shí),可以采用兩種不同的方式訪問。第一種就是之前我們一直使用的通過變量名訪問,即“直接訪問”方式;第二種可以通過訪問變量p,找到i的地址2000,再到2000地址對(duì)應(yīng)的內(nèi)存區(qū)域訪問變量i的值。這種訪問方式被稱為“間接訪問”方式。

8.2指針變量的定義、賦值和引用

8.2.1指針變量的定義

指針變量可以存儲(chǔ)另一個(gè)變量的地址,并可以通過其間接訪問該變量,這就需要在程序中定義指針變量,將其他變量的地址存儲(chǔ)在指針變量中,最終達(dá)到間接訪問變量的目的。

指針變量定義的一般形式為

類型說明符*變量名;其中:

類型說明符:規(guī)定指針變量指向的基類型,即指定指針變量存儲(chǔ)哪種類型數(shù)據(jù)的地址;

*:說明當(dāng)前定義的變量為指針變量;

變量名:指針變量的名稱,遵循C語(yǔ)言對(duì)標(biāo)識(shí)符定義的規(guī)則。

例如:

int*p1; /*p1是指向整型變量的指針變量*/

float*p2; /*p2是指向浮點(diǎn)變量的指針變量*/

char*p3; /*p3是指向字符變量的指針變量*/8.2.2指針變量的賦值

指針變量是一種特殊的變量,對(duì)它的賦值只能賦予其他變量地址。這個(gè)賦值的一般形式為

指針變量=&變量名;

其中:“&”叫做取地址運(yùn)算符,它的作用是返回變量的內(nèi)存起始地址。通過“=”把取出的變量地址賦值給指針變量。通過這種運(yùn)算取得聯(lián)系的指針變量與變量間存在一種“指向”關(guān)系。例如:

inti=100;

int*ip;

ip=&i;

在這里,假設(shè)變量i在內(nèi)存中分配的存儲(chǔ)單元的起始地址是2000,那么當(dāng)變量ip被賦值為i的地址之后,就可以說ip指向i。ip和i的指向關(guān)系可以用圖8-2所示的示意圖來表示。

指針變量與普通變量一樣可以進(jìn)行初始化,例如上例可以改寫如下:

inta;

int*p=&a;圖8-2指針與變量的“指向”關(guān)系在為指針變量進(jìn)行賦值的過程中,需要注意以下問題:

(1)不允許把一個(gè)數(shù)值賦予指針變量,故下面的賦值是錯(cuò)誤的:

int*p;

p=1000;

(2)賦給指針變量的變量地址不能是任意類型數(shù)據(jù)的地址,而只能是與指針變量的基類型具有相同類型的變量的地址。例如,整型變量的地址可以賦給指向整型變量的指針變量,但浮點(diǎn)型變量的地址不能賦給指向整型變量的指針變量。例如,下面的賦值是錯(cuò)誤的:

int*p;

floatx;

p=&x;

(3)被賦值的指針變量前不能再加“?*?”說明符,如寫為?*p=&a也是錯(cuò)誤的。8.2.3引用指針變量所指的值

當(dāng)一個(gè)指針變量指向另一個(gè)變量之后,就可以通過訪問這個(gè)指針變量來間接訪問它所指向的變量,其訪問的一般形式為

*指針變量名;

例如:

inti=200;

int*ip;

printf(“%d\n”,i);

ip=&i;

printf("%d\n",*ip);此程序的輸出結(jié)果如下:

200

200

這段程序中第一個(gè)輸出語(yǔ)句是對(duì)變量i的直接訪問,而第二個(gè)語(yǔ)句是對(duì)變量i的間接訪問,因?yàn)閕p中存放的是變量i的地址,所以ip是指向i的指針變量,在ip前加“?*?”是訪問變量ip中存儲(chǔ)的地址所對(duì)應(yīng)的存儲(chǔ)單元中的數(shù)據(jù)。從中可以看到上面程序段中的兩個(gè)輸出語(yǔ)句雖然訪問變量的方式不同,但結(jié)果相同。

【例8.1】用“間接訪問”方式輸入和輸出變量。

程序如下:

main()

{

inta,b;

int*pointer_1,*pointer_2;

pointer_1=&a; /*將變量a的地址賦值給pointer_1*/

pointer_2=&b; /*將變量b的地址賦值給pointer_2*/

scanf(“%d,%d”,pointer_1,pointer_2);

printf(“%d,%d\n”,*pointer_1,*pointer_2);/*訪問指向變量a、b的指針輸出變量*/

}

說明

(1)在開頭處雖然定義了兩個(gè)指針變量pointer_1和pointer_2,但它們并未指向任何一個(gè)整型變量,只是提供兩個(gè)指針變量,規(guī)定它們可以指向整型變量。語(yǔ)句“pointe_1=&a;pointe_2=&b;”的作用就是使pointer_1指向a,pointer_2指向b,如圖8-3所示。圖8-3指針變量與變量的指向關(guān)系

(2)在scanf語(yǔ)句中,因?yàn)閷?duì)a、b的輸入是通過指針變量進(jìn)行的,而指針變量本身存儲(chǔ)的是變量的地址,所以在輸入時(shí),輸入到列表的表達(dá)式中沒有“&”符號(hào)。

(3)倒數(shù)第二行的?*pointer_1和?*pointer_2就是訪問變量a和b。

思考

(1)如果已經(jīng)執(zhí)行了語(yǔ)句“pointer_1=&a;”,則?&*pointer_1的含義是什么?

(2)*&a的含義是什么?

(3)(pointer_1)++?和pointer_1++?的區(qū)別是什么?

【例8.2】輸入a和b兩個(gè)整數(shù),按先大后小的順序輸出a和b。

程序如下:

main()

{

int*p1,*p2,*p,a,b;

scanf(“%d,%d”,&a,&b);

p1=&a;p2=&b;

if(a<b)

{p=p1;p1=p2;p2=p;} /*p1、p2交換內(nèi)容*/

printf(“\na=%d,b=%d\n”,a,b);

printf("max=%d,min=%d\n",*p1,*p2);

}

說明

(1)“p=p1;”、“p1=p2;”、“p2=p;”三條語(yǔ)句的作用是交換p1和p2變量中的數(shù)據(jù),在交換之前p1和p2分別指向a和b,在交換之后p1和p2分別指向b和a。

(2)在此程序中a、b變量的值是保持不變的。對(duì)比程序:

main()

{

int*p1,*p2

intp,a,b;

scanf(“%d,%d”,&a,&b);

p1=&a;p2=&b;

if(a<b)

{p=*p1;*p1=*p2;*p2=p;}

/*實(shí)際是交換a、b的值*/

printf(“\na=%d,b=%d\n”,a,b);

printf("max=%d,min=%d\n",*p1,*p2);

}

思考

(1)在這段程序中,變量p1和p2的指向是否發(fā)生了變化?

(2)變量a和b的值是否發(fā)生了變化?

綜上所述,指針變量的相關(guān)運(yùn)算符有兩種,即取地址運(yùn)算符“&”和指針運(yùn)算符(或稱間接訪問運(yùn)算符)“?*?”。

需要注意的是,指針運(yùn)算符“?*?”和指針變量定義中的指針說明符“?*?”不是一回事。在指針變量說明中,“?*?”是類型說明符,表示其后的變量是指針類型。而表達(dá)式中出現(xiàn)的“?*?”則是一個(gè)運(yùn)算符,用以表示指針變量所指的變量值。當(dāng)一個(gè)指針變量p指向一個(gè)變量i以后,對(duì)于變量i的訪問方式可以由直接訪問改變?yōu)殚g接訪問。在程序中對(duì)變量的直接訪問通常表現(xiàn)為三種方式,同樣與之對(duì)應(yīng)的間接訪問也有三種方式,如表8-1所示?!纠?.3】輸出兩個(gè)數(shù)中的大者,要求通過直接訪問和間接訪問兩種方式進(jìn)行。

程序如下:

main()

{

inta,b,*pa,*pb;

pa=&a;

pb=&b;

printf(“inputa,b:\n”);

scanf(“%d%d”,&a,p2);

if(*pa>*pb)

/*比較pa和pb所指變量的值,實(shí)際是比較a、b的值*/

printf(“%d”,*pb);

else

printf("%d",b);

}

8.3數(shù)組指針和指向數(shù)組的指針變量

8.3.1指向一維數(shù)組的指針

數(shù)組在內(nèi)存中占有一段連續(xù)的存儲(chǔ)空間,數(shù)組的起始地址即為數(shù)組的指針。C語(yǔ)言中用數(shù)組名表示這塊連續(xù)內(nèi)存單元的首地址。若用一個(gè)指針指向一個(gè)數(shù)組,就可以通過間接訪問讀寫數(shù)組的每個(gè)元素。

下面舉例說明將指針指向一個(gè)數(shù)組的方法。例如:

inta[5]; /*定義a為包含5個(gè)整型數(shù)據(jù)的數(shù)組*/

int*p; /*定義p為指向整型變量的指針*/

p=a;

p=&a[0];

應(yīng)當(dāng)注意,因?yàn)閿?shù)組為int型,所以指針變量也應(yīng)為指向int型的指針變量。數(shù)組的首元素地址即為數(shù)組的起始地址,所以可以用“p=a;”向指針賦數(shù)組名或用“p=&a[0];”數(shù)組首元素地址的方法,使指針指向數(shù)組。賦值的結(jié)果如圖8-4所示,把a(bǔ)[0]元素的地址賦給指針變量p。也就是說,p指向a數(shù)組的第0號(hào)元素。在定義指針變量時(shí)可以賦初值為數(shù)組的起始地址:

int*p=&a[0];

int*p=a;

從圖8-4中可以看出有以下關(guān)系:a、&a[0]?均表示數(shù)組a的首地址。應(yīng)該說明的是,p是變量,而a、&a[0]?都是常量。在編程時(shí)應(yīng)予以注意。圖8-4指向一維數(shù)組的指針8.3.2通過指針引用一維數(shù)組元素

1.指針變量的數(shù)學(xué)運(yùn)算

指針在通常情況下是不能進(jìn)行數(shù)值運(yùn)算的,但是如果指針變量p已指向數(shù)組中的一個(gè)元素,則指針可以進(jìn)行以下運(yùn)算:

(1)加、減運(yùn)算。比如,指針p已經(jīng)指向數(shù)組中的某個(gè)元素了,那么p?+?1、p?-?1分別指向當(dāng)前元素的下一個(gè)元素和上一個(gè)元素。

在這里指針的加減運(yùn)算并不是單純將指針變量的值進(jìn)行加減。C語(yǔ)言規(guī)定,p+i實(shí)際上是p+(i*?指針?biāo)笖?shù)據(jù)類型所占的字節(jié)數(shù))。

例如,p指向a[0],p+i指向a[i]?的地址,a+i也得到a[i]?的地址。

(2)指向同一數(shù)組的指針之間可以進(jìn)行減法。比如,p2?-?p1得到兩個(gè)指針?biāo)冈刂g的地址差值。

例如,p2指向a[5],p1指向a[2],p2-p1得到3。

(3)指針的自加、自減運(yùn)算與*運(yùn)算相聯(lián)時(shí)的優(yōu)先級(jí)問題:

由于?++?和?*?同優(yōu)先級(jí),結(jié)合方向自右而左,故?*p++等價(jià)于?*(p++)。

*(p++)與?*(++p)作用不同。若p的初值為a,則?*(p++)等價(jià)于a[0],*(++p)等價(jià)于a[1]。

(*p)++?表示p所指向的元素值加1。

如果p當(dāng)前指向數(shù)組a中的第i個(gè)元素,則?*(p--)相當(dāng)于a[i--],*(++p)相當(dāng)于a[++i],*(--p)相當(dāng)于a[--i],*(p++)相當(dāng)于a[i++]。

2.通過指針訪問數(shù)組元素

引入指針變量后,就可以用下標(biāo)法和指針法兩種方法來訪問數(shù)組元素了。

(1)下標(biāo)法。引用數(shù)組元素可以用下標(biāo)法,即“數(shù)組名稱[下標(biāo)]”。

(2)指針法。指針法即采用?*(a+i)或?*(p+i)的形式,用間接訪問的方法來訪問數(shù)組元素,其中a是數(shù)組名,p是指向數(shù)組的指針變量。

例如,p指向數(shù)組a的首地址,如圖8-5所示。

①p+i和a+i就是a[i]?的地址,或者說它們指向a數(shù)組的第i個(gè)元素。

②*(p+i)或?*(a+i)就是p+i或a+i所指向的數(shù)組元素,即a[i]。例如,*(p+5)或?*(a+5)就是a[5]。

③指向數(shù)組的指針變量也可以帶下標(biāo),如p[i]?與?*(p+i)等價(jià)。圖8-5通過指針引用數(shù)組元素

【例8.4】輸出數(shù)組中的全部元素。(要求:用指針法輸出。)

指針法一:

main()

{

inta[10],i;

for(i=0;i<10;i++)

*(a+i)=i;/*將0~9分別賦值到a[0]~a[9]*/

for(i=0;i<10;i++)

printf("a[%d]=%d\n",i,*(a+i));

}

說明

數(shù)組名即數(shù)組的首地址,數(shù)組名加i即獲得數(shù)組中第i個(gè)元素的地址。

指針法二:

main()

{

inta[10],i,*p;

p=a; /*?p指向數(shù)組a的首地址*/

for(i=0;i<10;i++)

*(p+i)=i; /*通過指針加法將0~9分別賦值到a[0]~a[9]*/

for(i=0,p=a;i<10;i++)

printf("a[%d]=%d\n",i,*(p+i));

}

說明

p是指向數(shù)組的指針,對(duì)p進(jìn)行加i即獲得數(shù)組中第i個(gè)元素的地址。

指針法三:

main()

{

inta[10],i,*p;

for(p=&a[0],i=0;p<a+10;p++,i++)

{

*p=i;

printf(“a[%d]=%d\n”,i,*p);

}

}指針法四:

main()

{

inta[10],i=0,*p;

for(p=a;a<(p+10);a++,i++)

{

*a=i;

printf(“a[%d]=%d”,i,*a);

}

}注意

指針法四是錯(cuò)誤的,因?yàn)閿?shù)組名a代表數(shù)組首元素的地址,它是一個(gè)指針常量,它的值在程序運(yùn)行期間是固定不變的。既然a是常量,所以a++?是無法實(shí)現(xiàn)的。數(shù)組首地址通常不能被賦值。8.3.3字符指針與字符數(shù)組

在實(shí)際應(yīng)用中,字符指針常常用來指向一個(gè)字符數(shù)組、字符常量或字符串。例如:

char*pc;

pc=“China”;

定義字符指針時(shí)可以用字符串常量對(duì)它做初始化。例如:

char*pc=“China”;

我們知道,C語(yǔ)言對(duì)字符串常是以字符數(shù)組的形式存放的。因此,上述語(yǔ)句定義了指向字符的指針pc,其次在內(nèi)存中建立了常量字符串?"China",最后將字符串常量的起始地址存入pc變量中。指針pc與數(shù)組的指向情況如圖8-6所示。圖8-6字符指針與字符數(shù)組

【例8.5】用字符串指針分別指向一個(gè)常量字符串?“China!”?和?“English!”,并輸出這兩個(gè)字符串。

程序如下:

main()

{

char*pc=“China!”; /*指針pc指向字符串常量*/

printf(“%s\n”,pc); /*用%s控制方式輸出pc所指字符串*/

pc=“English!”; /*為pc所指地址處重新賦值*/

printf(“%s\n”,pc);

}

程序運(yùn)行結(jié)果:

China!

English!

說明

pc是指向字符的指針,初始化時(shí)指向了常量字符串?"China!",在后面的語(yǔ)句中,pc被重新賦值指向常量字符串?"English!"。因此,程序輸出結(jié)果得到了兩行不同的輸出。

【例8.6】用字符串指針實(shí)現(xiàn)strcat函數(shù)的功能,完成字符串的連接。

程序如下:

main()

{

char*s1=“Iam”;

char*s2=“astudent.”;

charc[80],*pc;

pc=c;

/*指針pc指向c字符數(shù)組*/

for(;*s1!='\0';s1++,pc++) /*循環(huán)變量s1所指的字符不等于?\0時(shí),即進(jìn)行循環(huán)*/*pc=*s1;

/*將s1所指的值賦值給指針pc指向的地址處*/

for(;*s2!='\0';s2++,pc++)

*pc=*s2;

pc='\0';

printf("%s\n",c);

}

程序運(yùn)行結(jié)果:

Iamastudent.

說明

(1)程序利用兩個(gè)循環(huán)分別將s1和s2指針?biāo)傅淖址群髮懭隿字符數(shù)組,實(shí)現(xiàn)字符串的拼接。

(2)在兩次寫入時(shí),并沒有寫入字符串結(jié)束標(biāo)志?'\0',因此在寫入s2后,需要為c字符數(shù)組添加一個(gè)結(jié)束標(biāo)志。

【例8.7】在輸入的字符串中查找有無字符?‘k’。

程序如下:

main()

{

charst[20],*ps;

inti;

printf(“inputastring:\n”);

ps=st;

scanf(“%s”,ps);

for(i=0;ps[i]!=‘\0’;i++)

/*?ps指針從st首元素開始循環(huán)*/

if(ps[i]==‘k’){

/*如果ps+i所指的元素值等于k,則輸出*/

printf(“thereisa‘k’inthestring\n”);

break;

}

if(ps[i]=='\0')printf("Thereisno'k'inthestring\n");

}8.3.4指向二維數(shù)組的指針

指針可以指向多維數(shù)組,但在應(yīng)用上比較復(fù)雜,較為常用的是指向二維數(shù)組的指針。二維數(shù)組的首地址即為數(shù)組名,也是第一個(gè)元素的地址。在C語(yǔ)言中,二維數(shù)組以行為單位在內(nèi)存中依次存放。

設(shè)有字符型二維數(shù)組num[3][6]如下:

charnum[3][6]={"one","two","three"};

num數(shù)組在內(nèi)存中存儲(chǔ)的情況如圖8-7所示。圖8-7字符二維數(shù)組的存儲(chǔ)設(shè)數(shù)組num的首地址為1000,則數(shù)組第0、1、2行的起始地址分別為1000、1006、1012。C語(yǔ)言允許把一個(gè)字符二維數(shù)組分解為多個(gè)一維數(shù)組來處理。因此數(shù)組num在邏輯上可分解為三個(gè)一維數(shù)組,即num[0]、num[1]、num[2]。每一個(gè)一維數(shù)組中存放一個(gè)字符串,如圖8-8所示。圖8-8二維數(shù)組數(shù)組及數(shù)組元素的地址表示如下:從二維數(shù)組的角度來看,num是二維數(shù)組名,num代表整個(gè)二維數(shù)組的首地址,也是二維數(shù)組0行的首地址,等于1000。num+i代表第i行的首地址。

【例8.8】輸入并輸出字符二維數(shù)組。

程序如下:

main()

{

charday[3][6];

inti;

printf(“inputdayarray:\n”);

for(i=0;i<3;i++)

scanf(“%s”,day[i]);

/*通過訪問二維數(shù)組的每行地址,對(duì)字符串進(jìn)行操作*/

printf(“thedayarrayare:\n”);

for(i=0;i<3;i++)

printf("%s\n",day+i);

}程序運(yùn)行結(jié)果:

inputdayarray:

one↙

two↙

three↙

thedayarrayare:

one

two

three

【例8.9】

編寫競(jìng)賽報(bào)名程序,輸入?yún)①愓咝彰⑴袛嗥渲惺欠裼心惩瑢W(xué)參加。

程序如下:

#definecol30

#definerow6

main()

{

charname[col][row];

charfindname[6];

intnum,i,flag=0;

printf(“inputstudentnum(<30):”);

scanf(“%d”,&num);

printf(“inputallstudentsname:”);

for(i=0;i<num;i++)

scanf(“%s”,name[i]);

printf(“inputfindname:”);

scanf(“%s”,findname);

for(i=0;i<num;i++)

{

if(strcmp(name[i],findname)==0)

/*比較name[i]和findname是否相同*/

{

flag=1;

break;

}

}

if(flag==1)

printf(“Yes,find%s”,findname);

else

printf("No,find%s",findname);

}8.3.5指針數(shù)組

C語(yǔ)言允許定義各種類型的數(shù)組,當(dāng)然也可以定義指針類型數(shù)組,簡(jiǎn)稱指針數(shù)組。指針數(shù)組的所有元素值均為指針。指針數(shù)組是一組有序的指針的集合。指針數(shù)組的所有元素都必須是具有相同存儲(chǔ)類型和指向相同數(shù)據(jù)類型的指針變量。

指針數(shù)組說明的一般形式為

類型說明符*數(shù)組名[數(shù)組長(zhǎng)度]

其中:類型說明符為指針值所指向的變量的類型。

1.字符指針數(shù)組

字符指針數(shù)組是一組指向字符數(shù)組的指針的集合。通常程序里有多個(gè)字符串時(shí),一種常見的做法就是用一個(gè)字符指針數(shù)組指向它們。然后,可以使用循環(huán)語(yǔ)句對(duì)多個(gè)字符串進(jìn)行批量操作,方便用戶編程。

定義一個(gè)字符指針數(shù)組的方法如下:

char*pc[10]

字符指針數(shù)組也可以在定義時(shí)初始化。人們常讓字符指針指向字符串,也常用字符串常量為字符指針數(shù)組中的指針提供初始值。下面是這種用法的一個(gè)例子:

char*country[]={"China","Japan","English"};這里定義了一個(gè)包含3個(gè)字符指針的數(shù)組,同時(shí)建立了3個(gè)字符串常量,讓數(shù)組里的指針分別指向各個(gè)字符串,如圖8-9所示。有了這個(gè)定義后,通過數(shù)組元素country[0]、country[1]和country[2]?等就可以訪問這些字符串了。圖8-9字符指針數(shù)組與一組字符串的指向關(guān)系例如,輸入以上所有字符串:

for(i=0;i<3;i++)

printf(“%s\n”,country[i]);

也可以對(duì)以上字符串進(jìn)行比較或重新輸入:

for(i=0;i<3;i++)

{

if(strcmp(country[i],“Japan”)==0) /*將變量字符串?“apan”?替換為?“Korea”*/

country[i]="Korea";

}

2.指針數(shù)組與二維數(shù)組

指針數(shù)組與二維數(shù)組兩種數(shù)據(jù)結(jié)構(gòu)在編程中可以配合使用。通常二維數(shù)組用來存儲(chǔ)數(shù)據(jù)本身。在C語(yǔ)言中,二維數(shù)組可以以行為單位分解為多個(gè)一維數(shù)組,因此利用指針數(shù)組來存放由二維數(shù)組分解出來的多個(gè)一維數(shù)組的地址,從而通過指針數(shù)組來操作二維數(shù)組中的某一行。

假設(shè)有下面兩個(gè)定義:

intnum[3][3]={1,2,3,4,5,6,7,8,9};

int*pa[3];

pa[0]=num[0];

pa[1]=num[1];

pa[2]=num[2];第一行定義建立了一個(gè)二維(3?×?3)的整型數(shù)組,它占用一片連續(xù)存儲(chǔ)區(qū),數(shù)組的邏輯存儲(chǔ)情況如圖8-10(a)所示。三個(gè)成員數(shù)組里各存一串?dāng)?shù)字。第二行定義一個(gè)包含三個(gè)指針的指針數(shù)組,三條賦值語(yǔ)句的作用是讓數(shù)組里的指針分別指向num數(shù)組的三行。賦值后的情況如圖8-10(b)所示。從這兩個(gè)圖可以清晰地看到兩個(gè)定義的不同。圖8-10二維數(shù)組和指針數(shù)組以上pa指針數(shù)組的應(yīng)用,為num二維數(shù)組建立了另一種以行為整體的聯(lián)系。對(duì)num二維數(shù)組的元素的訪問,可以更為靈活。

例如,用指針法訪問num二維數(shù)組的元素num[i][j]?的常用方法有?*(pa[i]+j)、*(*(pa+i)+j)等。

【例8.10】通過指針數(shù)組訪問二維數(shù)組。

程序如下:

main()

{

intnum[3][3];

int*pa[3];

inti,j;

pa[0]=num[0];

pa[1]=num[1];

pa[2]=num[2];

for(i=0;i<3;i++)

{

for(j=0;j<3;j++)

scanf(“%d”,(*(num+i)+j)); /*以行為單位,逐字訪問字符*/

}

for(i=0;i<3;i++)

{

for(j=0;j<3;j++)

printf(“%d”,*(pa[i]+j));

printf(“\n”);

}

}

指針數(shù)組在字符串常量編程中更為常用。當(dāng)多個(gè)字符串常量采用二維字符數(shù)組結(jié)構(gòu)存儲(chǔ)時(shí),如果字符串?dāng)?shù)量較多,且數(shù)據(jù)量較大,則需要一塊較大的連續(xù)存儲(chǔ)區(qū)。若將多個(gè)一維數(shù)組分別存儲(chǔ)在不同的存儲(chǔ)區(qū)域,則對(duì)內(nèi)存的要求降低,但是由于多個(gè)一維數(shù)組是一種分散的組織,不便于管理,所以可以使用字符指針數(shù)組分別指向字符串,通過字符指針數(shù)組操作字符串更為簡(jiǎn)便。

【例8.11】用冒泡排序法將5個(gè)國(guó)名按字母順序排列后輸出。

程序如下:

#include“string.h”

main()

{

char*name[]={“CHINA”,“AMERICA”,“AUSTRALIA”,“FRANCE”,“GERMAN”};

inti,j;

char*temp;

for(i=0;i<4;i++)

{

for(j=0;j<4-i;j++)

if(strcmp(name[j],name[j+1])>1)

/*比較相鄰字符串*/

{

temp=name[j];

name[j]=name[j+1];

name[j+1]=temp;

}

}

for(i=0;i<4;i++)

printf("%s\n",name[i]);

}程序運(yùn)行結(jié)果:

AMERICA

AUSTRALIA

CHINA

FRANCE

GERMAN

說明

把各個(gè)國(guó)家名稱的常量字符串分別放在5個(gè)一維數(shù)組中,把這些字符數(shù)組的首地址放在一個(gè)指針數(shù)組里,當(dāng)需要交換兩個(gè)字符串時(shí),只需交換指針數(shù)組相應(yīng)兩個(gè)元素的內(nèi)容(地址)即可,而不必交換字符串本身。這樣可以不必直接交換數(shù)據(jù),從而加速了交換的速度。

3.命令行參數(shù)及其處理

在運(yùn)行程序時(shí),有時(shí)需要將必要的參數(shù)傳遞給主函數(shù)。例如,一個(gè)打開文件的源程序文件名為openfile.c,所產(chǎn)生的可執(zhí)行文件名為openfile.exe,若在命令狀態(tài)下輸入命令:

openfile

這個(gè)程序就會(huì)被裝入并執(zhí)行,但是此處并未指明打開哪個(gè)文件,若想在鍵入命令的同時(shí)指明打開文件的名稱,就必須在鍵入可執(zhí)行程序文件名的同時(shí)輸入目標(biāo)文件名稱,這就需要使用命令行參數(shù)。要編寫能處理命令行參數(shù)的程序,需要了解C語(yǔ)言的命令行參數(shù)機(jī)制。在TurboC中,主函數(shù)的形式參數(shù)為下列形式:

main(intargc,char*argv[])

其中,兩個(gè)特殊的內(nèi)部形參argc和argv是用來接收命令行實(shí)參的,它們是只有main()才能擁有的實(shí)參。argc是整型變量,其作用是保存命令行的參數(shù)個(gè)數(shù);argv是指向命令行字符數(shù)組的指針數(shù)組。這個(gè)數(shù)組里的每個(gè)元素都指向命令行實(shí)參。所有命令行實(shí)參都是字符串,任何數(shù)字都必須由程序轉(zhuǎn)變?yōu)檫m當(dāng)?shù)母袷健O旅嫠o出的簡(jiǎn)單程序說明了命令行實(shí)參的用法。

【例8.12】在屏幕上顯示“Hello”,如果用戶在程序名后直接鍵入自己的名字,則顯示名字。

程序如下:

#include<stdio.h>

main(intargc,char*argv[])

{

if(argc!=2)

{

printf(“youforgottotypeyourname\n”);

exit(0);

}

printf(“Hello%s”,argv[l]);

}若命名該程序?yàn)閚ame.c,可在命令行方式下輸入:

nameMarry

則程序運(yùn)行結(jié)果為:

HelloMarry

說明

(1)以上命令由兩個(gè)參數(shù)組成,第一個(gè)參數(shù)是name,即執(zhí)行程序文件名本身。第二個(gè)參數(shù)是Marry,是要求“問候”的人名。這兩個(gè)參數(shù)分別是一個(gè)一維字符數(shù)組,第一個(gè)一維字符數(shù)組的起始地址放在argv[0]?中,第二個(gè)一維字符數(shù)組的起始地址放在argv[1]?中,如圖8-11所示。圖8-11命令行參數(shù)的用法

(2)

argc接收命令輸入時(shí)參數(shù)的個(gè)數(shù)。因此,在程序中判斷如果argc!=2,則說明用戶輸入的命令不規(guī)范,所以輸出提示信息。如果用戶命令輸入正確,則顯示“Hello”加第二個(gè)參數(shù)的字符串。

8.4指?針?與?函?數(shù)

8.4.1指針作為函數(shù)參數(shù)

1.指針變量作為函數(shù)參數(shù)

函數(shù)的參數(shù)可以是指針類型。它的作用是將一個(gè)變量的地址傳送到另一個(gè)函數(shù)的形參中。這屬于參數(shù)傳遞中的“傳址”方式。

【例8.13】輸入兩個(gè)整數(shù),按大小順序輸出。要求用函數(shù)處理,且用指針類型的數(shù)據(jù)作為函數(shù)參數(shù)。程序如下:

voidswap(int*pa,int*pb)

{

inttemp;

temp=*pa;

*pa=*pb;

*pb=temp;

}

#include<stdio.h>

voidmain()

{

inta,b;

int*p1,*p2;

printf(“inputa,b:”);

scanf(“%d,%d”,&a,&b);

p1=&a;

p2=&b;

if(a<b)

swap(p1,p2);

printf(“theMaxis%d,theMinis%d\n”,a,b);

}

程序運(yùn)行結(jié)果:

inputa,b:3,5↙

theMaxis5,theMinis3

說明

(1)swap是用戶定義的函數(shù),它的作用是交換兩個(gè)變量(a和b)的值。swap函數(shù)的形參pa、pb是指針變量。

(2)程序運(yùn)行時(shí),先執(zhí)行main函數(shù),輸入a和b的值。然后將a和b的地址分別賦給指針變量p1和p2,使p1指向a,p2指向b。接著執(zhí)行if語(yǔ)句,如果a?<?b,則執(zhí)行swap函數(shù)。注意,p1和p2是指針變量作為函數(shù)實(shí)參。在函數(shù)調(diào)用時(shí),將實(shí)參變量的值傳遞給形參變量,因此形參pa的值為&a,pb的值為&b。這時(shí)pa指向變量a,pb指向變量b,如圖8-12(a)所示。

(3)執(zhí)行swap函數(shù)的函數(shù)體,使pa所指的值和pb所指的值互換,其過程分別如圖8-12(b)、(c)、(d)所示。從圖示可以看出,a和b的值已經(jīng)實(shí)現(xiàn)互換。

(4)返回主程序后,將a和b的值輸出,得到交換后的結(jié)果。圖8-12指針作為函數(shù)參數(shù)對(duì)比程序一:

swap(int*pa,int*pb)

{

int*temp;

*temp=*pa;

*pa=*pb;

*pb=temp;

}

#include<stdio.h>

voidmain()

{

inta,b;

int*p1,*p2;

printf(“inputa,b:”);

scanf(“%d,%d”,&a,&b);

p1=&a;

p2=&b;

if(a<b)

swap(p1,p2);

printf("theMaxis%d,theMinis%d\n",a,b);

}

說明

此程序是錯(cuò)誤程序。因?yàn)樵趕wap函數(shù)中,temp變量是指針變量,但沒有指向任何其他變量。因此,在實(shí)現(xiàn)交換過程中,“*temp=*pa;”企圖將pa所指的值即a的值賦給temp所指的變量,但temp并未指向任何一個(gè)存儲(chǔ)單元,所以賦值語(yǔ)句錯(cuò)誤。對(duì)比程序二:

voidswap(intx,inty)

{

inttemp;

temp=x;

x=y;

y=temp;

}

#include<stdio.h>

voidmain()

{

inta,b;

printf(“inputa,b:”);

scanf(“%d,%d”,&a,&b);

if(a<b)

swap(a,b);

printf("theMaxis%d,theMinis%d\n",a,b);

}

說明

在此程序中,swap函數(shù)不能實(shí)現(xiàn)a和b互換。這是因?yàn)?,此處的參?shù)傳遞屬于“傳值”方式,形參的改變不會(huì)影響實(shí)參。

對(duì)比程序三:

swap(int*pa,int*pb)

{

int*temp;

temp=pa;

pa=pb;

pb=temp;

}

#include<stdio.h>

voidmain()

{

inta,b;

printf(“inputa,b:”);

scanf(“%d,%d”,&a,&b);

if(a<b)

swap(&a,&b);

printf("theMaxis%d,theMinis%d\n",a,b);

}

說明

(1)此程序的main函數(shù)中,調(diào)用swap函數(shù)的實(shí)參是a、b變量的地址,即&a和&b。既然實(shí)參傳遞的是指針,那么形參只能是指針變量。

(2)在swap函數(shù)中,交換的是pa和pb的指向,而a和b的值并沒有真正的交換。因此,返回主函數(shù)后再輸出a和b的值,它們的值并沒有按大小重新排列,而是保持不變。

2.?dāng)?shù)組名作為函數(shù)參數(shù)

數(shù)組名就是數(shù)組的指針,因此,數(shù)組名作為函數(shù)參數(shù)時(shí)傳遞的數(shù)據(jù)是整個(gè)數(shù)組的首地址。

數(shù)組名可以作為函數(shù)的實(shí)參,而與其對(duì)應(yīng)的形參應(yīng)為同類型的數(shù)組。例如:

main()

{

intarray[5];

f(array,5);

}

f(intarr[],intn);

{

}………

array是一個(gè)整數(shù)數(shù)組的名稱,作為實(shí)參,對(duì)應(yīng)的形參arr同樣為一個(gè)整數(shù)數(shù)組,但特殊的是,在定義arr數(shù)組時(shí),并沒有定義它的長(zhǎng)度。這是因?yàn)?,?shí)參array傳遞的實(shí)際上是數(shù)組的首地址,即一個(gè)指針,對(duì)應(yīng)的形參arr接收這一地址,那么arr與array指向同一起始地址,如圖8-13所示。因此,操作arr數(shù)組實(shí)際上就是操作array數(shù)組。圖8-13數(shù)組名作為實(shí)參

【例8.14】

編寫函數(shù)求數(shù)組的平均值,要求數(shù)組的值在主函數(shù)中輸入,平均值也在主函數(shù)中輸出。

程序如下:

floataver(float*pa,intn)

{

inti;

floatav,s=0;

for(i=0;i<n;i++)

s=s+*pa++; /*累加數(shù)組元素和*/

av=s/5;

returnav;

}

main()

{

floatscore[5],av;

inti;

printf(“\ninput5scores:\n”);

for(i=0;i<5;i++)

scanf(“%f”,&score[i]);

av=aver(score,5);

printf(“averagescoreis%5.2f”,av);

}

【例8.15】

將數(shù)組a中的n個(gè)整數(shù)按相反順序存放。

方法一:

voidinv(intx[],intn)

{

inttemp,i,j,m=(n-1)/2;

for(i=0;i<=m;i++)

{

j=n-1-i; /*

j,i是所要交換的對(duì)應(yīng)元素的下標(biāo)*/

temp=x[i];x[i]=x[j];x[j]=temp;

}

}

#include<stdio.h>

voidmain()

{

inti,a[10]={3,7,9,11,0,6,7,5,4,2};

printf(“Theoriginalarray:\n”);

for(i=0;i<10;i++)

/*輸出原始數(shù)組的值*/

printf(“%d”,a[i]);

printf(“\n”);

inv(a,10);

printf(“Thearrayhasbeeninverted:\n”);

for(i=0;i<10;i++)

printf("%d",a[i]); /*輸出調(diào)整后的數(shù)組的值*/

}

說明

先將a[0]與a[n-1]對(duì)換,再將a[1]與a[n-2]對(duì)換……直到將a[(n-1/2)]與a[n-int((n-1)/2)]對(duì)換?,F(xiàn)用循環(huán)處理此問題,設(shè)兩個(gè)“位置指示變量”i和j,i的初值為0,j的初值為n-1。將a[i]與a[j]交換,然后使i的值加1,j的值減1,再將a[i]與a[j]交換,直到i=(n-1)/2為止。方法二:

voidinv(int*x,intn) /*形參x為指針變量*/

{

int*p,temp,*i,*j,m=(n-1)/2;

i=x;j=x+n-1;p=x+m;

for(;i<=p;i++,j--)

{temp=*i;*i=*j;*j=temp;} /*

i,j是指向要交換的對(duì)應(yīng)元素的指針*/

return;

}

main()

{

inti,a[10]={3,7,9,11,0,6,7,5,4,2};

printf(“Theoriginalarray:\n”);

for(i=0;i<10;i++)

printf(“%d”,a[i]);

printf(“\n”);

inv(a,10);

printf(“Thearrayhasbeeninverted:\n”);

for(i=0;i<10;i++)

printf(“%d”,a[i]);

printf("\n");

}下面將在函數(shù)中改變實(shí)參數(shù)組值的方法作一歸納。

(1)形參和實(shí)參都用數(shù)組名。例如:

voidf(intx[],intn)

{

}

voidmain()

{

inta[10];

f(a,10);

}………

(2)實(shí)參用數(shù)組名,形參用指針變量。例如:

voidf(int*x,intn)

{

}

voidmain()

{

inta[10];

f(a,10);

}………

(3)形參和實(shí)參都用指針變量。例如:

voidf(int*x,intn)

{

}

voidmain()

{

inta[10],*p=a;

f(p,10);

}………圖8-14數(shù)組名作為實(shí)參與形參的對(duì)應(yīng)關(guān)系

(4)實(shí)參用指針變量,形參用數(shù)組名。例如:

voidf(intx[],intn

)

{

}

voidmain()

{

inta[10],*p=a;

f(p,10);

}………8.4.2指針函數(shù)

指針函數(shù)是指函數(shù)的類型是指針型的。在定義函數(shù)時(shí),每個(gè)函數(shù)都有自己的類型,所謂函數(shù)類型,是指函數(shù)返回值的類型。在C語(yǔ)言中允許一個(gè)函數(shù)的返回值是一個(gè)指針(即地址),這種返回指針值的函數(shù)稱為指針函數(shù)。

指針函數(shù)與非指針函數(shù)定義上的區(qū)別主要在于對(duì)函數(shù)名的聲明上,其定義的一般形式與其他函數(shù)定義相似,即

類型說明符*函數(shù)名(形參表)

{

…/*函數(shù)體*/

}在此定義之中,函數(shù)名之前加了“?*?”,表明這是一個(gè)指針型函數(shù),即返回值是一個(gè)指針。因此在指針函數(shù)的函數(shù)體中必有一個(gè)“return指針;”的返回語(yǔ)句。

例如:

int*ap(intx,inty)

{

…/*函數(shù)體*/

}

【例8.16】利用指針函數(shù)從數(shù)列中選擇最大數(shù),并最終完成選擇排序。

程序如下:

int*max(int*x,intnum)

{

inti,*this=x; /*this指向未排好序的數(shù)列的第一個(gè)元素*/

for(i=1;i<num;i++)

if(*(x+i)>*this)

this=x+i;

returnthis;

}

voidswap(int*first,int*max)

{

inttemp;

temp=*first;

*first=*max;

*max=temp;

}

voidsort(int*pa,intn)

/*pa指向array數(shù)組*/

{

int*pmax,i,j;

for(i=0;i<n;i++)

{

pmax=max(pa+i,n-i); /*調(diào)用求最大值函數(shù),將返回?cái)?shù)組元素中的最大元素

swap(pa+i,pmax); 指針并賦值在pmax中*/

}

}

main()

{

intarray[]={13,5,7,9,40,60,23,77,81,49};

inti;

printf(“Theoriginalarray:”);

for(i=0;i<10;i++)

printf(“%d”,array[i]);

printf(“\n”);

sort(array,10); /*調(diào)用排序函數(shù)*/

printf(“Thearrayhasbeensorted:”);

for(i=0;i<10;i++)

printf("%d",array[i]);

printf("\n");

}

說明

(1)本程序中有三個(gè)函數(shù),即sort、max和swap,分別用于排序、選擇最大值和交換。main函數(shù)在調(diào)用sort函數(shù)時(shí),以array數(shù)組名及數(shù)組長(zhǎng)度10作為實(shí)參,完成參數(shù)傳遞后,sort函數(shù)的形參指針pa指向array數(shù)組的首地址。

(2)sort函數(shù)實(shí)現(xiàn)選擇排序,在每一趟排序過程中選擇最大值的步驟是由函數(shù)max完成的。max函數(shù)是指針函數(shù),比較最大值的算法與“打擂臺(tái)”法基本一致,但在此函數(shù)中,沒有進(jìn)行任何交換,因?yàn)榻粨Q的過程耗時(shí)太多,特別是交換頻繁發(fā)生時(shí),會(huì)導(dǎo)致程序執(zhí)行效率下降。在這里,采用的方法是用this指針始終指向已經(jīng)比較過的數(shù)列中的最大數(shù)。函數(shù)最后返回this指針。8.4.3函數(shù)指針

盡管函數(shù)不是變量,但函數(shù)和變量同樣都要占用一段內(nèi)存單元,函數(shù)也有一個(gè)地址,該地址是編譯器分配給這個(gè)函數(shù)的,這個(gè)地址可以賦給一個(gè)指針,因此指針變量可以指向整型、實(shí)型等變量,也可以指向函數(shù)。指向函數(shù)的指針叫做函數(shù)指針。而函數(shù)的地址實(shí)際上是這個(gè)函數(shù)的入口位置,因此指針指向函數(shù)實(shí)際上是指向函數(shù)對(duì)應(yīng)的程序段的起始地址。正是由于這一點(diǎn),一個(gè)函數(shù)指針可以用來調(diào)用一個(gè)函數(shù)。

1.定義函數(shù)指針變量的一般格式

定義函數(shù)指針變量的一般格式為

函數(shù)類型(*函數(shù)指針標(biāo)識(shí)符)(形參類型說明表);

使用函數(shù)指針時(shí)應(yīng)注意以下幾點(diǎn):

(1)函數(shù)指針與它指向的函數(shù)的參數(shù)個(gè)數(shù)和類型都應(yīng)該是一致的。

(2)函數(shù)指針的類型和函數(shù)的返回值類型也必須是一致的。

2.函數(shù)指針的賦值

函數(shù)名和數(shù)組名一樣代表了函數(shù)代碼的首地址,因此在賦值時(shí),直接將函數(shù)指針指向函數(shù)名即可。

例如:

intfun(intx); /*聲明一個(gè)函數(shù)*/

int(*f)(intx); /*聲明一個(gè)函數(shù)指針*/

f=fun;

3.通過函數(shù)指針調(diào)用函數(shù)

函數(shù)指針是通過函數(shù)名及有關(guān)參數(shù)進(jìn)行調(diào)用的。與其他指針變量相類似,如果指針變量f是指向某整型變量i的指針,則?*f等于它所指的變量。如果?*f是指向函數(shù)func(x)的指針,則?*f就代表這個(gè)強(qiáng)制性指向的函數(shù)func。所以在執(zhí)行“f=func;”之后,(*f)和fun就代表同一函數(shù)。

由于函數(shù)指針指向存儲(chǔ)區(qū)中的某個(gè)函數(shù),因此可以通過函數(shù)指針調(diào)用相應(yīng)的函數(shù)。為實(shí)現(xiàn)這一過程,應(yīng)執(zhí)行以下三步:

(1)定義函數(shù)指針變量。例如:

int(*f)(intx);

(2)對(duì)函數(shù)指針變量賦值。例如:

f=fun;

(3)使用(*f)(參數(shù)表)進(jìn)行函數(shù)調(diào)用。

【例8.17】

利用指針函數(shù)實(shí)現(xiàn)調(diào)用求最大值函數(shù)max。

程序如下:

intmax(intx,inty)

{

if(x>=y)

returnx;

else

returny;

}

main()

{

inti,a,b;

int(*func)(

);

printf(“請(qǐng)輸入a,b的值:”);

scanf(“%d,%d”,&a,&b);

func=max;

/*func指向max函數(shù)*/

printf(“最大值是:”);

printf(“%d”,(*func)(a,b));

/*通過func指針訪問max函數(shù)*/

}

說明

在max函數(shù)中,返回x和y之中的大值。在主函數(shù)中,func指向max函數(shù),通過func調(diào)用max函數(shù)。 8.5指針?的?指?針

指針變量是存儲(chǔ)其他類型變量地址的變量,這里的其他類型也包括指針類型。也就是說,一個(gè)指針變量中存放的地址可以是另一個(gè)指針變量的地址,則稱這個(gè)指針變量為指向指針的指針,也叫做二級(jí)指針。

這種指針的指針與指向數(shù)據(jù)間的關(guān)系如圖8-15所示。圖8-15指針的指針定義二級(jí)指針的一般形式為

數(shù)據(jù)類型**變量標(biāo)識(shí)符;

例如:

int**pp;

其中:**?表示pp是二級(jí)指針;int表示pp中存放指向整型變量指針的地址。指針的指針只能存儲(chǔ)其他指針變量的地址,因此對(duì)指針的指針的一般賦值過程是:

數(shù)據(jù)類型*p1;

數(shù)據(jù)類型**p2;

p2=&p1;二級(jí)指針的數(shù)據(jù)類型定義必須與它所指的指針變量的類型定義相同。要引用二級(jí)指針?biāo)傅臄?shù)據(jù)值,其訪問的一般形式為

**指針變量名;

【例8.18】利用指針的指針編寫程序,判斷在全班同學(xué)中是否有某同學(xué)的名字。

程序如下:

main()

{

char*classmates[]={“WangLin”,“LiQi”,“ZhangMing”,“ChenLu”,“LiLan”};

charname[8];

char**p;

inti,flag=0;

printf("請(qǐng)輸入所要查找的學(xué)生姓名:");

scanf(“%s”,name);

/*name變量用來保存要查找的學(xué)生姓名*/

for(i=0;i<5;i++)

{

p=classmates+i; /*classmates是數(shù)組的首地址,p在循環(huán)中依次指向二維數(shù)組的每一行*/

if(strcmp(*p,name)==0)

{

flag=1;

break;

}

}

if(flag==1)

printf(“%s已報(bào)名\n”,name);

else

printf("%s尚未報(bào)名\n",name);

}

說明

(1)classmates是指針數(shù)組,分別指向5個(gè)常量字符串,如圖8-16所示。classmates是classmates指針數(shù)組的首地址。classmates+i是第i個(gè)常量字符串的起始地址。

(2)定義一個(gè)指針的指針變量p,使它指向指針數(shù)組元素。在循環(huán)中,通過p+i分別得到classmates[0]~classmates[4]?元素的地址。

(3)在訪問常量字符串時(shí),并沒有使用?**p,而使用?*p進(jìn)行訪問。這就是在本例中指針的指針指向的是字符串的緣故。圖8-16指針的指針與指針數(shù)組

【例8.19】

一個(gè)指針數(shù)組的元素指向數(shù)據(jù)的簡(jiǎn)單例子。

程序如下:

main()

{

staticinta[5]={1,3,5,7,9};

int*num[5]={&a[0],&a[1],&a[2],&a[3],&a[4]};

/*指針數(shù)組num的每一個(gè)元素指向?qū)?yīng)的a數(shù)組的每一個(gè)元素*/

int**p,i;

p=num;

for(i=0;i<5;i++)

{printf("%d\t",**p);p++;}

}

說明

(1)num是指針數(shù)組,在初始化時(shí),分別將a數(shù)組的5個(gè)元素的地址賦值給num數(shù)組的對(duì)應(yīng)元素,因此,num數(shù)組的每一個(gè)元素指向?qū)?yīng)的a數(shù)組的每一個(gè)元素。

(2)p是指向指針的指針,p被賦的初值為

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝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ù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論