指針引用與動(dòng)態(tài)內(nèi)存分配_第1頁(yè)
指針引用與動(dòng)態(tài)內(nèi)存分配_第2頁(yè)
指針引用與動(dòng)態(tài)內(nèi)存分配_第3頁(yè)
指針引用與動(dòng)態(tài)內(nèi)存分配_第4頁(yè)
指針引用與動(dòng)態(tài)內(nèi)存分配_第5頁(yè)
已閱讀5頁(yè),還剩25頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、6.1 選擇排序算法 1第六章指針,引用與動(dòng)態(tài)內(nèi)存分配在第四章,我們?cè)霐?shù)組類型,它與本章介紹的指針和引用類型是C+語(yǔ)言提供的三種導(dǎo)出類型,正確靈活地使用數(shù)組,指針和引用類型,是設(shè)計(jì)高質(zhì)量的C+程序所必經(jīng)掌握的技術(shù)。結(jié)構(gòu)在只有數(shù)據(jù)成員時(shí),也是一種導(dǎo)出數(shù)據(jù)類型,不過(guò),語(yǔ)言允許用戶為結(jié)構(gòu)設(shè)計(jì)函數(shù)成員,實(shí)際上是用戶為該結(jié)構(gòu)類型設(shè)計(jì)的運(yùn)算,因此,結(jié)構(gòu)也是用戶定義的類或類型,將在下一章介紹。C+程序中所處理的數(shù)據(jù)主要以變量(和對(duì)象)的形式出現(xiàn)。每個(gè)變量有兩個(gè)最主要的屬性,那就是變量的內(nèi)容和地址。例如: int a=3,b=5,c;c=a+b;在上面語(yǔ)句中,變量a,b,c已被賦值。在它們被重新賦值或被釋

2、放之前,變量名a,b,c就代表著它們的內(nèi)容,即整型數(shù)3,5,8。由變量a,b,c參加的任何運(yùn)算,都是對(duì)它們的值3,5,8進(jìn)行的運(yùn)算。另一方面,C+語(yǔ)言也為用戶對(duì)于變量所占空間的地址提供了進(jìn)行操作的機(jī)制,這就是指針類型和引用類型。指針和引用不是一種獨(dú)立的數(shù)據(jù)類型,而是一種導(dǎo)出數(shù)據(jù)類型。指針類型也是語(yǔ)言和語(yǔ)言的重要類型,而引用類型是語(yǔ)言中新的重要類型,在語(yǔ)言和語(yǔ)言等一些新的語(yǔ)言中,引用類型取代了指針類型,因此,兩者的使用都應(yīng)該熟練掌握。我們首先通過(guò)實(shí)例來(lái)說(shuō)明指針的使用。選擇排序算法排序的任務(wù)是把已經(jīng)存在一個(gè)數(shù)組里的n個(gè)數(shù)按從大到小的順序排列,可以采用多種不同的方法實(shí)現(xiàn),選擇排序算法的思路簡(jiǎn)單,容易

3、理解,每次總是從無(wú)序的序列中選出最大者,交換到序列的左端,于是,無(wú)序的序列越來(lái)越短,經(jīng)過(guò)步,達(dá)到排序的目的。程序program6_1的主要部分是介紹實(shí)現(xiàn)選擇排序算法的函數(shù)void ssort(float *,int ),在閱讀下面的程序時(shí),應(yīng)特別注意指針類型變量和函數(shù)參數(shù)的使用:/program6_1.cpp#include<iostream.h>#include<stdlib.h> #include<iomanip.h>void ssort(float *, int );void main(void)int i, seed, n=20;cout<&l

4、t;endl<<"seed=" ;cin>>seed;cout<<endl;srand(seed);float list20, *pf;for(i=0; i<n; i+)listi = rand( );cout<<setw(8)<<listi;if (i+1)%8=0)cout<<endl;i=0; cout<<endl;pf=&list0;ssort (pf,n);while ( i<n ) cout<<setw(8)<<listi;i+;if

5、(i % 8 = 0)cout<<endl;cout<<endl;void swap1(float *a, float *b) float temp;temp = *a;*a = *b;*b = temp;6.1 選擇排序算法 3void ssort (float *a, int m)int i, j, index;float elem;for (i=0; i<m-1; i+)elem = *(a+i);index = i;for (j=i+1; j<m; j+)if (*(a+j)>elem)elem = *(a+j);index = j;swap1

6、(a+i, a+index);運(yùn)行結(jié)果:seed=652321339 28822 26220 8712 18120 1280 27491 86477137 2030 24101 20505 4452 26942 10989 2991927130 20996 17227 1355929919 28822 27491 27130 26942 26220 24101 2133920996 20505 18120 17227 13559 10989 8712 86477137 4452 2030 1280程序說(shuō)明:這個(gè)程序重點(diǎn)是介紹函數(shù)ssort( ) 和swap1( ) 的設(shè)計(jì),應(yīng)特別注意指針變量、

7、函數(shù)()的指針類型參數(shù)和函數(shù)()的指針類型參數(shù),的說(shuō)明和使用方法。主函數(shù)做了三件事:)為長(zhǎng)度為的數(shù)組輸入個(gè)隨機(jī)數(shù),作為排序算法處理的對(duì)象,程序中取,是為了顯示輸出結(jié)果方便,也可取或更大,實(shí)際輸入的值是整數(shù)也是為了顯示清楚。利用庫(kù)函數(shù)()產(chǎn)生偽隨機(jī)數(shù)形成無(wú)序數(shù)組,由用戶輸入一個(gè)隨機(jī)數(shù)(例如)作為“”可使無(wú)序數(shù)組的個(gè)數(shù)的隨機(jī)性較好。)調(diào)用函數(shù)()進(jìn)行排序。)把經(jīng)過(guò)排序的數(shù)組的值輸出。函數(shù)swap1( )的定義中使用了指針類型的參數(shù)。參數(shù)a,b是float型的指針變量,即它們的值應(yīng)是浮點(diǎn)型變量的地址。在swap1( ) 的調(diào)用語(yǔ)句中,實(shí)參a+i, a+index, 其中a為float 型的指針,i,

8、 index為整型變量,C+ 語(yǔ)言允許指針變量+/-整數(shù),其結(jié)果仍為指針。即a+i, index應(yīng)表示數(shù)組List 中a指向的元素后面的元素變量的地址。在函數(shù)swap1( )中使用了*a和*b,這里符號(hào)*不是乘法運(yùn)算符,而是表示指針變量(a或b)所指向的那個(gè)變量。例如:int n=4, *p;p=&n;*p+;表示有整型變量n,和整型指針變量p,用&n表示變量n的地址,p=&n使指針p指向變量n,而這時(shí)*p正是表示變量n,*p+相當(dāng)于n+。由此可以看出,&和*是一對(duì)用于指針操作的互逆的單目運(yùn)算符,(在這里&不是“引用”的意思)。&n表示變量n的地

9、址,而*p表示指針p指向的變量或該變量的值。對(duì)于函數(shù)swap1(float *a,float *b),讀者可與上一章中介紹的swap(int &a, int &b)函數(shù)作一比較,雖然它們都達(dá)到交換兩個(gè)變量?jī)?nèi)容的目的,但采用的方式卻是不同的。在swap1( )中有兩個(gè)指針型參數(shù),屬于賦值形參,在調(diào)用時(shí)創(chuàng)建兩個(gè)新的指針變量a和b,把實(shí)參表達(dá)式計(jì)算的結(jié)果地址賦給a和b,從而使指針a和b指向相應(yīng)的變量。而在swap( )中形參a,b為引用型,它是在調(diào)用時(shí)直接由實(shí)參的變量代替a,b參加swap( )函數(shù)的函數(shù)體操作。函數(shù)ssort( )是一個(gè)用于對(duì)m個(gè)浮點(diǎn)數(shù)組進(jìn)行排序的函數(shù),其參數(shù)為 f

10、loat型指針和int 型整數(shù)。前者指明數(shù)組的首地址,后者為數(shù)組中元素的個(gè)數(shù),執(zhí)行結(jié)果是把這個(gè)數(shù)組中的浮點(diǎn)數(shù)按從大到小的順序排列好。按照C+語(yǔ)言的規(guī)定,數(shù)組名list除了作為名字之外,它還可表示該數(shù)組的首地址,即可以用list直接表示&list0。因此,行可以用下面一個(gè)調(diào)用語(yǔ)句取代:ssort(list,n)其效果完全相同。函數(shù)ssort(tist,n)的函數(shù)體是具體完成排序的過(guò)程,請(qǐng)注意如何表示數(shù)組的各個(gè)元素。從這里可以更清楚地了解到:程序中說(shuō)明的數(shù)組list20,實(shí)際上是n(=20)個(gè)float型變量,它們除可以用下標(biāo)變量list0,list1,list19表示之外,也可以用*li

11、st,*(list+1),*(list+19)來(lái)表示。指針可以和整數(shù)做加減法,這一點(diǎn)已在上6.2 導(dǎo)出數(shù)據(jù)類型(2),指針(Pointer) 5文指出,指針變量做加法要小心,C/C+的指針操作有些“過(guò)于自由”了。把個(gè)數(shù)排好次序可以有許多種不同的算法,這個(gè)函數(shù)是每次把尚未排好的元素中的最大元素選出,移到左端,最終形成從大到小的排列,故被稱為選擇排序算法。下節(jié)介紹有關(guān)指針類型的語(yǔ)法規(guī)則。指針()類型指針變量說(shuō)明指針類型的變量說(shuō)明格式為:類型名指針變量名初值;類型名:任一基本類型名,基本類型的派生類型名,用戶定義的類枚舉類型結(jié)構(gòu)及聯(lián)合類型名。類型名為void時(shí),稱為不確定類型的指針類型。類型名也可以

12、是由類型名表示的指針類型名,這時(shí)稱為多級(jí)指針(指針類型的指針)。符號(hào):表示其后說(shuō)明的變量為指針變量(這里的”不是運(yùn)算符)。指針變量名:標(biāo)識(shí)符。初值:可缺省。它可以是該類型的某一變量的地址。例如:int *ptr;float a=3.0, b, c4; float * pa=&a;float *p2=&a, &b;float *pn=NULL;float *pc=c;float *pf=new float;point *pp;其中:ptr是一個(gè)未賦初值的int型的指針變量。pa是float型的指針變量,被賦初值為&a,即pa當(dāng)前的值為變量a的地址,或說(shuō)pa指向變量

13、a。如把&a賦給ptr是不合法的,因?yàn)楹笳呤钦椭羔?。p 是浮點(diǎn)型指針數(shù)組,它由兩個(gè)指針元素組成,分別被賦值&a,&b。 pn是一被賦初值為NULL的指針變量,規(guī)則規(guī)定NULL與整數(shù)0通用,它是唯一可以賦給任一類型指針變量的值,表示當(dāng)前該指針未指向任一變量。因此,一個(gè)指針變量,可有三種狀態(tài):()未賦任何值,“懸空”狀態(tài)。()被賦予NULL值。未指向任一變量。()指向某一變量。pc是一浮點(diǎn)型指針變量,由于c是浮點(diǎn)型數(shù)組的名,因此c又是指向數(shù)組的首元的指針,這時(shí)把c的值賦給pc,意味著pc的值為數(shù)組c 的首元c0的地址。pf也是浮點(diǎn)型指針變量,它的初值是通過(guò)動(dòng)態(tài)內(nèi)存分配運(yùn)算

14、符new的“運(yùn)算”結(jié)果,生成一無(wú)名的float型變量,其地址賦給了pf。new的使用將在本章介紹。由于這樣產(chǎn)生的float型變量是無(wú)名的,因此在程序中對(duì)它的引用,主要是靠pf(用*pf表示)。pp是一個(gè)對(duì)象指針,因?yàn)閜oint是一個(gè)已定義的類名,pp將可用來(lái)存放一個(gè)point類對(duì)象的地址,或說(shuō)可用pp指向point類的一個(gè)對(duì)象(關(guān)于類和對(duì)象在第七章以后介紹)。指針變量的操作本節(jié)介紹與指針變量有關(guān)的運(yùn)算。1取地址運(yùn)算和取內(nèi)容運(yùn)算取地址運(yùn)算為一單目運(yùn)算,運(yùn)算符為,例如:int a=3,*pa=&a;其中&a表示變量a的地址。它可以作為指針pa的值。使用&時(shí)應(yīng)注意:()其后只

15、可用一變量名,而不可為一字面常量或一般表達(dá)式。()賦值時(shí),pa與a的類型應(yīng)一致。取內(nèi)容運(yùn)算為一單目運(yùn)算,運(yùn)算符為*,例如: int a=3,*pa=&a;*pa=5;cout<<a<<*pa;其中*pa5;和cout<<a<<*pa; 中的*pa表示指針pa當(dāng)前所指向的變量a, 因此,*pa=5;相當(dāng)于a=5; ,這里的*pa被稱為“左值“,相當(dāng)于變量a占用的空間,而后一個(gè)*pa則相當(dāng)于變量a的值,故二者顯示出的值應(yīng)都是。運(yùn)算*與&互為逆運(yùn)算,這兩個(gè)運(yùn)算符都有不只一種含義,應(yīng)注意不要混淆。2數(shù)組指針的算術(shù)運(yùn)算如果指針變量是指向數(shù)組

16、的,例如:6.2 導(dǎo)出數(shù)據(jù)類型(2),指針(Pointer) 7int a20;int *pa=a;則指針pa可以有限制地進(jìn)行運(yùn)算或增量()減量()運(yùn)算。 這時(shí),可以用三種方式表示該數(shù)組的元素:(1)下標(biāo)變量的形式:a0, a1, a2, a3, , a19;(2)用數(shù)組名a(一個(gè)常量指針):*a, *(a+1), *(a+2), *(a+3), ,*(a+19);(3)用指針變量pa(a):*pa,*(pa+1), *(pa+2), *(pa+3),,*(pa+19);雖然三種方式都可以,不過(guò)應(yīng)注意的是,這里pa是變量,它可能是變化的,例如:pa+=3;執(zhí)行后,pa已是指向a3,即*pa為a

17、3。pa-;執(zhí)行后,pa已是指向a2。下面兩個(gè)程序效果是一樣的:#include <iostream.h>void main()int i,a5;cout<<"input 5 integers:"<<endl;for(i=0; i<5; i+)cin>>ai;cout<<"= Reverse output: ="<<endl;for(i=4; i>=0; i-)cout<<ai<<" "cout<<endl;#inc

18、lude <iostream.h>void main()int i,a5;cout<<"input 5 integers:"<<endl;for(i=0; i<5; i+)cin>>*(a+i);/*(a+i)全同于ai , a為數(shù)組首地址(一個(gè)常量指針) cout<<"= Reverse output: ="<<endl; for(i=4; i>=0; i-) cout<<*(a+i)<<" " /*(a+i)全同于aicou

19、t<<endl;當(dāng)數(shù)據(jù)為多維數(shù)組時(shí),上述對(duì)應(yīng)關(guān)系為:int a23;int * pa=a; / 或*pa=a00;三種方式表示其六個(gè)元素:(1)a00,a01,a02,a10,a11,a12。(2)*a,*(a1),*(a2),*(a3),*(a4),*(a5)。(3)*pa,*(pa+1),*(pa+2),*(pa+3),*(pa+4),*(pa+5)。其中*(a4)即為a11,*(pa2)即為a02,應(yīng)注意:(1)隨時(shí)檢查當(dāng)前指針pa指向數(shù)組的哪個(gè)元素。例如pa=pa4;執(zhí)行后,pa指向了a11。這時(shí)如果再做:pa;pa;就會(huì)出現(xiàn)指針pa“超界”,已不知它該指向誰(shuí)了。(2)有時(shí)

20、可以把數(shù)組指針在限定范圍(數(shù)組元素?cái)?shù))內(nèi),當(dāng)作整數(shù)來(lái)運(yùn)算,例如:int a45,n;int *pa=a,*pb&a34;n=pb-pa+1;coutnendl;輸出的是數(shù)組的元素總數(shù)。C+的數(shù)組指針的+/-運(yùn)算,使用起來(lái)比較方便,但很不安全,極容易出錯(cuò), 必須予以注意。有的人把指針?lè)Q為“數(shù)據(jù)結(jié)構(gòu)中的goto語(yǔ)句”意思就是它的過(guò)于靈活容易造成程序出錯(cuò),這也是一些新的語(yǔ)言,如JAVA,C#語(yǔ)言中取消指針類型的原因之一。3指針的關(guān)系運(yùn)算指針變量可以參加關(guān)系運(yùn)算。這要分三種情況:6.2 導(dǎo)出數(shù)據(jù)類型(2),指針(Pointer) 9(1)一般指針可以進(jìn)行相等和不等的比較,指向同一變量(地址)者

21、為相等,否則不等。(2)任一指針可以和指針常量NULL進(jìn)行相等和不等的比較。如一指針p已經(jīng)指向了某變量,則它不等于NULL。(3)數(shù)組指針,可以指向該數(shù)組的各個(gè)元素,且一個(gè)數(shù)組的各個(gè)元素在內(nèi)存中是順序存放的,故數(shù)組指針之間不但可以進(jìn)行相等和不等比較,也可以進(jìn)行大于,小于,大于等于,小于等于等的比較。下面是有關(guān)的例子:float a,b,c10;float *pl=&a,*p2=NULL,*p3=C,*p4;if(pl != p2)p2=p32;if(p2p3)p2=1;順便說(shuō)明,指針和所有類型一樣,它也可進(jìn)行賦值運(yùn)算。指針與數(shù)組指針與數(shù)組都是導(dǎo)出類型,它們都是在其它類型的基礎(chǔ)上被定義的

22、。那么它們互相之間可否“導(dǎo)出”呢?1指向數(shù)組元素的指針前面被簡(jiǎn)單地稱為數(shù)組指針的,實(shí)際上應(yīng)更確切地稱之為指向數(shù)組元素的指針,例如:int n10;int *pn=n;則指針 pn指向數(shù)組n的首元n0。在這里pn=n與pn=&n0;起相同的效果,因?yàn)閿?shù)組名就是一個(gè)指向其首元的一個(gè)指針常量。2指向數(shù)組的指針把數(shù)組作為整體,稱為指向數(shù)組的指針,對(duì)于這類指針,其說(shuō)明語(yǔ)句格式為:類型名(*指針變量名)數(shù)組元素?cái)?shù);而指向多維數(shù)組的指針說(shuō)明中,最后一項(xiàng)數(shù)組元素?cái)?shù)可有多個(gè)??梢园l(fā)現(xiàn),指向多維(或一維)數(shù)組的指針說(shuō)明與多維(或一維)數(shù)組說(shuō)明只相差符號(hào)*和一對(duì)括號(hào)(*)。這個(gè)括號(hào)是很重要的,在下文介紹的指

23、針數(shù)組恰恰沒有這對(duì)括號(hào)。例如:int (*pa)4;表示指針變量pa是一個(gè)指向一維整型數(shù)組的指針,該數(shù)組包含四個(gè)整型元素。一般指向數(shù)組的指針由多維數(shù)組的操作中被賦值:float A24;float(*pa)4;pa=A;這時(shí)指針pa指向一維數(shù)組A0,(A0有四個(gè)元素),執(zhí)行增量運(yùn)算pa+;后,pa指向一維數(shù)組A1,數(shù)組A1的四個(gè)元素是A10,A11,A12,A13。它們也可表示為(*pa)0,(*pa)1,(*pa)2,(*pa)3。從指向數(shù)組指針和指向數(shù)組元素指針的區(qū)別,可以看到:雖然指針變量的內(nèi)容都是地址,但指針變量的類型(指向的對(duì)象類型)則決定了該地址指向的存儲(chǔ)區(qū)的大小,例如:float

24、 *P=&A00;float(*pa)4;pa=A;雖然這時(shí)指針p和指針pa指向的地址是一樣的,但P是指向一個(gè)整型下標(biāo)變量A00,而pa則是指向整型一維數(shù)組A0,前者占內(nèi)存空間可能是4bytes,而后者則占16bytes。3指針數(shù)組由指針組成的數(shù)組,常常在程序中出現(xiàn),其說(shuō)明格式為:類型名*數(shù)組名元素?cái)?shù)n維指針數(shù)組為:類型名*數(shù)組名元素?cái)?shù)元素?cái)?shù)2元素?cái)?shù)n; 從上面格式可知:(1)它比一般數(shù)組增加了符號(hào)*。(2)它比指向數(shù)組的指針,少了一對(duì)括號(hào)“()”。例如:int a,b,c,d,A24;int *p14=&a,&b,&c,&d;int *p22=A0,A

25、1;其中,指針數(shù)組pl由四個(gè)整型指針組成,把四個(gè)整型變量a,b,c,d的6.2 導(dǎo)出數(shù)據(jù)類型(2),指針(Pointer) 11地址賦給它們作初值是合法的。指針數(shù)組p2由兩個(gè)整型指針組成,A0,A1是兩個(gè)一維整型(含四個(gè)元素的)數(shù)組名,它們表示A00,A10的地址,作為p2的元素的初值也是合法的。從上面三個(gè)小節(jié)的內(nèi)容可以看出下面定義的指針的區(qū)別:int *p;int *p12;int(*p2)4;p是指向int型變量的指針,p1是由兩個(gè)整型指針組成的指針數(shù)組,而p2則是一個(gè)指向一維整型數(shù)組的指針。字符串指針字符串是一種特殊的數(shù)據(jù)形式,在數(shù)組一節(jié),我們已經(jīng)指出字符串和字符數(shù)組的關(guān)系。C+語(yǔ)言對(duì)于

26、字符串的操作提供了多種手段,其中利用字符串指針是最方便的一種。 說(shuō)明與初始化字符串指針沒有自己獨(dú)立的形式,其說(shuō)明語(yǔ)句的格式與字符類型指針相同,例如:char ch= 'a':char *pc1=&ch;char *pc2="world";char as10="Chinese";char *pc3=as;在上面的幾個(gè)說(shuō)明語(yǔ)句中:變量ch是字符型,它被賦初值字符a。變量pcl是字符指針,它被賦初值為字符變量的地址。這時(shí)pcl是一個(gè)字符型指針。變量pc2和pcl一樣說(shuō)明為字符指針,但它被賦初值為字符串常量“world”,于是pc2就成為

27、一個(gè)字符串指針。它的內(nèi)容是字符串第一個(gè)字符w的存儲(chǔ)地址。數(shù)組as 是一個(gè)長(zhǎng)度為10的字符數(shù)組。為as所賦的初值為字符串常量“Chinese”,這個(gè)常量在數(shù)組中占八個(gè)分量的位置,七個(gè)字母和一個(gè)串尾符0。變量pc3說(shuō)明為字符指針,并令其指向字符數(shù)組as的首元,這時(shí),pc3也是一個(gè)字符串指針。字符串指針可以按一般字符指針的規(guī)則工作,例如:while(*pc2 != '0')cout*pc2+;執(zhí)行上述while語(yǔ)句將在屏幕上顯示world。類似地:while(*pc3 != '0')cout*pc3+;執(zhí)行的結(jié)果是顯示Chinese。字符串指針有時(shí)可以按不同于一般指針

28、變量的方式操作,即有時(shí)它可以表示字符串整體,而不是單單表示當(dāng)前指向的那個(gè)字符。這一點(diǎn)為用戶提供了方便,但也應(yīng)在概念上搞清楚,以免混淆,請(qǐng)看下面介紹。 字符串的整體輸入輸出把字符串作為字符數(shù)組,然后按字符依次進(jìn)行輸入輸出是可行的(如上述),但比較麻煩。因此,再提供整體輸入輸出的方法。把字符串變量用字符數(shù)組或字符串指針的形式表示,然后直接進(jìn)行I/O操作:cin字符串;cout字符串;這里的字符串可以用字符串指針pc2,pc3或字符數(shù)組名as來(lái)表示,例如: char as 10="world";char *pc2"world";char *pc3=as;cou

29、tas;coutpc2;coutpc3;cout"world";后四個(gè)輸出語(yǔ)句產(chǎn)生相同效果,都是輸出了字符串world。char str 20;char *pc2=new char20;char *pc3=str;cinstr;cinpc2;cinpc3;6.2 導(dǎo)出數(shù)據(jù)類型(2),指針(Pointer) 13后三個(gè)輸入語(yǔ)句允許輸入長(zhǎng)度不超過(guò)20的字符串,忽略前導(dǎo)空格,以空格作為串尾。 字符串指針數(shù)組以字符串指針組成的數(shù)組使用起來(lái)比較方便,例如:char *menu "File","Edit","Search",&

30、quot;Help";就是一個(gè)字符串指針數(shù)組,它的每個(gè)元素指向一個(gè)字符串常量。于是menu0,menu1,menu2,menu3將分別表示“File”,“Edit”,“Search”,“He1p”。4利用字符串指針的標(biāo)準(zhǔn)函數(shù)在頭文件string.h中,C系統(tǒng)提供若干串處理函數(shù)的說(shuō)明,它們大都利用字符串指針,下面列出幾例:(1)求字符串長(zhǎng)度。unsigned strlen(const char *str );返回字符串str的長(zhǎng)度(不包括串尾符)。(2)字符串拷貝:char *strcpy(char *str1 ,char *str2);把字符串str2拷貝給字符串strl(覆蓋原來(lái)內(nèi)

31、容),返回strl的地址。(3)字符串連接:char *strcat(char *str1 ,char *str2);把字符串str2連接到字符串str1的后面(使str1加長(zhǎng)),返回str1的地址。(4)字符串比較:int strcmp(char *str1 ,char *str2);此函數(shù)把ASCII碼表作為字符表,按字典序比較兩個(gè)字符串str1和str2。例如串“abc”小于串“abd”,串“xy”小于串“xyz”等等。根據(jù)兩個(gè)串之間的大于,等于,小于關(guān)系,返回正整數(shù),0和負(fù)整數(shù)。在C+程序中,有關(guān)指針、字符數(shù)組和字符串的操作是初學(xué)者較難掌握的,下面的程序?qū)嵗梢詭椭x者加深理解。#in

32、clude <iostream.h>void main()char s21, *ps=s;for (int i=0; i<20; i+)si='A'+i;s20='0' ps+; cout<<"ps="<<ps<<endl; ps+=2; cout<<"ps="<<ps<<endl;for (ps=&s19; ps>&s11; ps-=2)cout<<"*ps="<<*

33、ps<<endl;cout<<"ps="<<ps<<endl;運(yùn)行結(jié)果:ps=BCDEFGHIJKLMNOPQRSTps=DEFGHIJKLMNOPQRST*ps=Tps=T*ps=Rps=RST*ps=Pps=PQRST*ps=Nps=NOPQRST指針與函數(shù)指針與函數(shù)的關(guān)系密切,主要分三部分,指針作函數(shù)參數(shù),作函數(shù)返回類型和指向函數(shù)的指針。函數(shù)指針在Pascal語(yǔ)言是沒有的。1指針作函數(shù)參數(shù)指針是一種特殊類型的數(shù)據(jù),它的值是另外某種類型的變量的地址。因此,指針作函數(shù)的參數(shù)可以起到其它類型參數(shù)所起不到的作用。C語(yǔ)言中,函數(shù)的

34、參數(shù)(引用型參數(shù)除外)在調(diào)用過(guò)程中,須把實(shí)參(表達(dá)式)的值賦給僅在調(diào)用過(guò)程中有意義的形參,參加到函數(shù)體的運(yùn)算之中。這樣的機(jī)制很難實(shí)現(xiàn)對(duì)相對(duì)于函數(shù)的外部的“全局”變量作某些處理。例如要6.2 導(dǎo)出數(shù)據(jù)類型(2),指針(Pointer) 15編寫一個(gè)交換兩個(gè)浮點(diǎn)型變量?jī)?nèi)容(值)的函數(shù):float a=1.0, b=2.1,c=3.2,d=4.5;為了交換變量a,b的值,當(dāng)然可以直接用三條語(yǔ)句完成:float ta;a=b;b=t;就可達(dá)到目的。若要以函數(shù)形式表示,該函數(shù)應(yīng)為無(wú)參函數(shù):void swap(void)float t=a;a=b;bt;這個(gè)函數(shù)當(dāng)然是對(duì)的。其中變量a,b是在函數(shù)外定義的全

35、局變量。它的明顯缺點(diǎn)是沒有“參數(shù)化”,沒有通用性。當(dāng)我們需要交換b和c,或交換c和d的值時(shí),它就不能用,但是把它寫成有參的形式:void swap(float x,float y)float tx;x=y;y=t;這個(gè)函數(shù)就是錯(cuò)的,當(dāng)要把變量a,b內(nèi)容交換時(shí),函數(shù)調(diào)用:swap(a,b);不會(huì)把變量a和b的內(nèi)容真的交換,它只是在函數(shù)執(zhí)行時(shí)把臨時(shí)的形參x和y的內(nèi)容交換了,而這個(gè)x和y在函數(shù)執(zhí)行完成就被釋放掉。利用指針可以解決上面的問(wèn)題,swap( )函數(shù)可以定義為:void swap(float *pa,float *pb)float t=*pa;*pa=*pb;*pb=t;;為了交換a和b,交

36、換c和d,只需調(diào)用二次:swap(&a,&b);swap(&c,&d);因?yàn)樗ㄟ^(guò)參數(shù)傳進(jìn)了要改變內(nèi)容的全局變量的地址,從而可以達(dá)到以參數(shù)形式輸入,又能改變函數(shù)外變量?jī)?nèi)容的目的。2函數(shù)返回指針?lè)祷刂禐橹羔樀暮瘮?shù)稱為指針型函數(shù),其返回類型的說(shuō)明應(yīng)指明指針的對(duì)象類型后加“*”符號(hào)。例如:char *menu "Error!","File","Edit","Search","Help"char *menuitem(int m)return(m1 | m4)?menu0:

37、menum;這個(gè)函數(shù)menuitem()返回的是字符串指針,可直接調(diào)用函數(shù)menuitem( )來(lái)進(jìn)行字符串的輸入輸出。指針型函數(shù)的設(shè)計(jì),應(yīng)注意返回的指針在該函數(shù)被調(diào)用的域內(nèi)是有確切的對(duì)象變量的。切不可返回指向函數(shù)內(nèi)說(shuō)明的局部變量或參數(shù)變量的指針,或無(wú)指向的指針。3函數(shù)指針函數(shù)不是數(shù)據(jù),但它與變量還是有兩點(diǎn)相通之處:一個(gè)是它有類型(返回類型),另一個(gè)是它也有地址,稱為人口地址,故在有的書中也勉強(qiáng)地把函數(shù)仍歸為一種特殊的數(shù)據(jù)“類型”。函數(shù)的地址也可作指針的值,這就是函數(shù)指針。函數(shù)指針的說(shuō)明格式與函數(shù)的原型相似,主要區(qū)別是:原來(lái)的函數(shù)名,用 *函數(shù)指針名所代替,例如:int(*pf)(float)

38、;其中pf是一個(gè)函數(shù)指針變量,由于對(duì)pf的說(shuō)明中已規(guī)定了函數(shù)的返回類型(有時(shí)還包括存儲(chǔ)類型)和參數(shù)表,因此,指針pf只能夠指向這類函數(shù)。例如:int f1(float);int f2(char);int f3(float);int f4(float);設(shè)f1,f2,f3,f4是4個(gè)已說(shuō)明的函數(shù),這時(shí),下面的說(shuō)明和賦值,就有合法與不合法的區(qū)別:int(*pf)(float)=&f1; /合法int(*pf1)(char)=&f1; /不合法pf=&f4; /合法pf=&f2; /不合法6.2 導(dǎo)出數(shù)據(jù)類型(2),指針(Pointer) 17pf=&f3;

39、/合法C語(yǔ)言本身不允許把函數(shù)作為參數(shù),然而有了函數(shù)指針,就可以通過(guò)函數(shù)指針,起到把函數(shù)作為參數(shù)的作用。 例如:用來(lái)計(jì)算函數(shù)定積分的函數(shù)simpson(),對(duì)于不同的函數(shù)計(jì)算其定積分值,應(yīng)該有一個(gè)函數(shù)參數(shù),在C程序中用函數(shù)指針可以方便地解決這個(gè)問(wèn)題:float simpson(float a,float b,float(*pf)(float);參數(shù)a,b給出定積分的上下限,函數(shù)指針pf則指向被積函數(shù)(其函數(shù)體從略)。在使用時(shí)可以對(duì)不同的浮點(diǎn)函數(shù)和上下限,調(diào)用simpson()計(jì)算其定積分:float a=3.2,b=4.2;float f1(float); /函數(shù)體從略float f2(floa

40、t); /函數(shù)體從略float(*pfl)(float)=&f1: /函數(shù)指針pf1指向函數(shù)f1 coutsimpson(a,b,pfl)endl ;a4.0;b=10.5;pfl=&f2; /pf1指向函數(shù)f2coutsimpson(a,b,pfl)endl;兩次調(diào)用分別計(jì)算兩個(gè)不同函數(shù)fl和f2的定積分值,這樣的功能沒有函數(shù)指針是難以實(shí)現(xiàn)的。函數(shù)指針的使用屬于較深入的話題,這里就不進(jìn)一步展開了。指針與動(dòng)態(tài)內(nèi)存分配動(dòng)態(tài)分配運(yùn)算符在第四章,我們已經(jīng)介紹了動(dòng)態(tài)分配運(yùn)算符new和delete。new和delete的使用,也是C+語(yǔ)言優(yōu)于C語(yǔ)言的特征之一。New運(yùn)算是程序中除了變量說(shuō)

41、明之外,又一種生成變量的方法,不過(guò)用new生成的變量為無(wú)名動(dòng)態(tài)變量,它返回的是一個(gè)該類型的指針值,程序通過(guò)指針對(duì)這個(gè)變量進(jìn)行操作。例如:int *pi,a=5;char *pc;float *pf,f=3.0;pi=new int; /生成一動(dòng)態(tài)int類型變量pc=new char4; /生成動(dòng)態(tài)char類型數(shù)組pf=new float(4.7); /生成動(dòng)態(tài)float類型變量且賦初值 *pia*a; /動(dòng)態(tài)變量*pi被賦值for(int i=0;i4;i) /動(dòng)態(tài)char型數(shù)組的每個(gè)分量被賦值 *(pci)a;f+=*pf; /動(dòng)態(tài)變量*pf參加運(yùn)算我們可以把用new生成的一個(gè)動(dòng)態(tài)變量與用變

42、量說(shuō)明語(yǔ)句說(shuō)明的一個(gè)變量作比較:·都要指出變量的類型,類型名要放在new之后。·都可以賦初值,不是用初值的方式而是用括號(hào)(初值)的方式。·都可以說(shuō)明為數(shù)組,加數(shù)組運(yùn)算符。·動(dòng)態(tài)變量沒有變量名,須用指針變量接收到它的地址后,通過(guò)指針運(yùn)算符進(jìn)行操作。Delete運(yùn)算用來(lái)撤消或釋放由ne生成的動(dòng)態(tài)變量,例如:delete pa; /釋放pa指向的動(dòng)態(tài)int變量delete pf; /釋放pf指向的動(dòng)態(tài)float變量delete pc; /釋放pc指向的動(dòng)態(tài)數(shù)組動(dòng)態(tài)變量與一般變量的主要區(qū)別就是它可以在程序運(yùn)行過(guò)程中任意被撤銷。而一般變量則必須在其所說(shuō)明的程序塊結(jié)

43、束時(shí)自動(dòng)撤銷。用指針進(jìn)行內(nèi)存動(dòng)態(tài)分配C程序中對(duì)變量、數(shù)組等的說(shuō)明實(shí)際上就是為它們進(jìn)行內(nèi)存分配,所分配的空間及其內(nèi)容,通過(guò)變量名引用。用這種方式為變量分配空間,其占用形式比較死板。有了運(yùn)算符和,就可以實(shí)現(xiàn)一種動(dòng)態(tài)分配內(nèi)存的形式,即通過(guò)指針引用,而內(nèi)存的分配和釋放可以在程序的任何地方進(jìn)行。語(yǔ)言中沒有運(yùn)算符和,其動(dòng)態(tài)內(nèi)存分配依靠若干庫(kù)函數(shù)完成,比較復(fù)雜,這也是語(yǔ)言優(yōu)于語(yǔ)言的特點(diǎn)之一。例如:int *pint;char *pchar;float *pfloat;pfloat = new float;指針與動(dòng)態(tài)內(nèi)存分配19pchar = new char;pint = new int;這樣就生成了三個(gè)(

44、浮點(diǎn)型、字符型、整型)變量,但它們沒有名字。由于三個(gè)變量的地址分別存在指針pfloat,pchar和pint,故在程序中使用這三個(gè)變量時(shí),全通過(guò)指針:*pchar = A;*pint = 5;*pfloat = 4.7;*pint+;當(dāng)不再需要這些變量時(shí),可在程序的任何地點(diǎn)釋放掉它們: delete pchar;delete pint;delete pfloat;注意,這里釋放的是動(dòng)態(tài)的(,)變量,而不是指針變量(pchar, pint, pfloat)。這種動(dòng)態(tài)生成的變量,在使用上方便靈活,其必要條件就是應(yīng)用相應(yīng)的指針來(lái)操縱它。讀者在使用動(dòng)態(tài)變量時(shí)應(yīng)注意的是,要保護(hù)動(dòng)態(tài)變量的地址。例如在執(zhí)行

45、pi=new int;之后,不要輕易地沖掉指針pi中的值,假如執(zhí)行了pi=&a;語(yǔ)句之后,再釋放原來(lái)生成的動(dòng)態(tài)變量:delete pi;已經(jīng)達(dá)不到原來(lái)的目標(biāo)了。 C中new運(yùn)算類似于Pascal語(yǔ)言中new過(guò)程的使用,不過(guò)它不作為相應(yīng)的函數(shù)處理。C還保留了從C語(yǔ)言中繼承下來(lái)用于動(dòng)態(tài)存儲(chǔ)分配的malloc(),free( )等標(biāo)準(zhǔn)函數(shù),它們已經(jīng)可以為new和delete運(yùn)算所取代。導(dǎo)出數(shù)據(jù)類型(),引用()引用(reference)是C語(yǔ)言特有的(C和Pascal語(yǔ)言不具備)數(shù)據(jù)形式。它的存在不僅像數(shù)組和指針那樣依賴于已有的類型,而且它還依賴于一個(gè)已有的變量。從直觀上說(shuō),一個(gè)引用變量是一

46、個(gè)已定義的變量的別名。這種引用型變量在作為函數(shù)的參數(shù)和返回類型時(shí),其使用方式與指針類型有相似性。上文已經(jīng)提到指針類型的缺點(diǎn),因此建議讀者在學(xué)習(xí)和掌握C語(yǔ)言過(guò)程中,應(yīng)體會(huì)引用類型的重要性,理解它的原理和特征,掌握它的使用方法,在既可以使用指針類型又可以使用引用類型時(shí),多用引用類型。由于一些新的語(yǔ)言,如,等,取消了指針類型而僅保留引用類型,引用類型的重要性就更容易理解了。引用變量的說(shuō)明引用變量的說(shuō)明格式與指針變量說(shuō)明相似:類型名變量名=對(duì)象變量名;與指針說(shuō)明的區(qū)別是:()用符號(hào)代替符號(hào)*。()賦初值部分不可缺省。例如: int size=5,color;int refs=size;int refc

47、=color;引用變量refs,refc相當(dāng)于整型變量size和co1or的別名,即:refc3;其效果為變量color和refc同時(shí)被賦值為3。refs+=2;其效果是變量size和refs同時(shí)在原來(lái)值5的基礎(chǔ)上加2,即改變?yōu)?。 引用和指針的比較C語(yǔ)言中增加引用這種數(shù)據(jù)形式,主要是用于在一定的范圍內(nèi),代替或改進(jìn)指針的作用。雖然在說(shuō)明方式上十分相似,但在概念上卻有著明顯的不同。其區(qū)別最主要有兩點(diǎn):()指針表示的是一個(gè)對(duì)象變量的地址,而引用則表示一個(gè)對(duì)象變量的別名。因此在程序中表示其對(duì)象變量時(shí),前者要通過(guò)取內(nèi)容運(yùn)算符*,而后者可直接代表: int m,n;int *p = m;int r =

48、m;而在對(duì)m賦值時(shí),下面三者是等價(jià)的:m = 5;*p = 5;6.4 導(dǎo)出數(shù)據(jù)類型(3), 引用(Reference) 21r = 5;引用類型變量與其他類型變量不同,它沒有自己的值和地址空間,只是作為另一變量的別名,在它的生存期期間兩個(gè)名字綁定在一起,因此,引用類型的使用是有限制的:引用類型變量不能被引用;引用類型不能組成數(shù)組;引用類型不能定義指針。正是這些限制,保證了它的安全性,反而成為人們選擇它取代方便靈活的指針的原因。()指針是可變的,它可以指向變量m,也可以指向變量n,而引用變量只能在定義時(shí)一次確定,不可改變。 int m,n;int * p = m;int r = m:以后執(zhí)行

49、p = n;是合法的,而引用變量r只可與m相聯(lián)。因此,有人說(shuō)可以把引用看成指針常量,即:const int * p = m;int r = m;二者更相近。不過(guò)這里p對(duì)應(yīng)的是m的地址,而引用變量r不關(guān)心m的地址,它直接與變量m本身相關(guān)。引用型參數(shù)把函數(shù)的參數(shù)說(shuō)明為某一類型(或類)的引用類型,意味著這個(gè)參數(shù)為“變量參數(shù)”,稱為引用調(diào)用。引用型參數(shù)在函數(shù)被調(diào)用時(shí),相應(yīng)的實(shí)參必須是對(duì)應(yīng)類型的變量或?qū)ο?;在調(diào)用函數(shù)體運(yùn)行前,生成該實(shí)參的引用變量;在整個(gè)函數(shù)體運(yùn)行過(guò)程中,這個(gè)引用變量相當(dāng)于作為實(shí)參的變量或?qū)ο蟮膭e名,直到函數(shù)調(diào)用結(jié)束返回。引用型參數(shù)的優(yōu)點(diǎn)是:()它可以把函數(shù)外的變量以別名的形式引入到函數(shù)

50、體內(nèi)參加運(yùn)算,非常方便,這種方式比用指針解決這個(gè)問(wèn)題更合理。()它不必在調(diào)用時(shí)創(chuàng)建與實(shí)參變量或?qū)ο髮?duì)應(yīng)的值參數(shù)變量,當(dāng)實(shí)參變量或?qū)ο笳加脙?nèi)存較多時(shí),這可以節(jié)省內(nèi)存。()用指針也可以實(shí)現(xiàn)類似于引用調(diào)用的效果,但由于指針可以改變內(nèi)容,任意賦值,因此它不如引用型參數(shù)安全。關(guān)于引用調(diào)用,在后面的章節(jié)有更多的實(shí)例介紹。引用型的函數(shù)返回值一般的函數(shù)要返回一個(gè)值,例如: int max(int a,int b)return(ab)?a : b;;這個(gè)函數(shù)返回二者之中較大的值,可令:int cmax(3,5);當(dāng)把函數(shù)的返回類型說(shuō)明為引用型時(shí),這個(gè)函數(shù)返回的不僅僅是某一變量或?qū)ο蟮闹?,而且返回了它的“別名”,

51、該函數(shù)的調(diào)用也可以被賦值。讓我們舉例說(shuō)明:int a = 2,b = 3,c = 4;int * p a;int r = b;下面的一些表達(dá)式:c,ab,*p,rc*b,r其中ab,rc*b是表達(dá)式,它們僅可計(jì)算出一個(gè)值。另外c,*p,r也是表達(dá)式,而且它們又可被賦值:c=5,*p=6,r=7,等等,因此這類表達(dá)式被稱為“左值表達(dá)式”。引用型返回類型的函數(shù)調(diào)用就是一種左值表達(dá)式,可以作為值,也可被賦值: int a=3,b=5,c;int maxr(int & m,int & n)if(m>n)return m;return n;函數(shù)maxr( )可以有兩個(gè)用法: c =

52、 maxr(a,b);它把變量a,b中較大者的值賦給了變量c,返回的是較大者的值。 maxr(a,b)=10;它把變量a,b中較大者的值改變?yōu)?0,返回的是較大者本身。maxr(a,b)+;它把變量a,b中當(dāng)前較大者的值加1,返回的也是較大者本身。函數(shù)的調(diào)用本身也可以作為變量和對(duì)象來(lái)使用,這是引用概念在C程序設(shè)計(jì)中非常重要的應(yīng)用,它所提供的編程靈活性,在運(yùn)算符的重載,在C6.5 程序?qū)嵗?23語(yǔ)言提供的I/O系統(tǒng)中有十分重要的體現(xiàn)。在有些場(chǎng)合下,以引用代替指針,除了可以實(shí)現(xiàn)相同的目標(biāo)外,同時(shí)增加程序的安全性,引用型函數(shù)可以作為“左值”,它的這種功能可以說(shuō)是程序設(shè)計(jì)語(yǔ)言的一個(gè)重要發(fā)展,C程序員在

53、程序設(shè)計(jì)中應(yīng)充分使用引用概念,必然有利于提高程序的水平。程序?qū)嵗慈嗣值湫蚺帕须娫挷颈竟?jié)的程序涉及應(yīng)用編程經(jīng)常碰到的字符串和文本的處理,已知有n個(gè)人的姓名,以及每個(gè)人有一個(gè)電話號(hào)碼,然后按這些人名的字典序排列且輸出其電話號(hào)碼表。/program6_2.cpp# include <iostream.h># include <iomanip.h>void swap (char* & ,char* & );int compword (char*,char*);void main(void)const int n=5,t=8;int i,j,index;cha

54、r *telen,*sele;char *namen="Zhaolin","Mazhigang","Liguoping","Sunyingmin","Mazilan"for (i=0; i<n; i+)cout<<"Input"<<namei<<"'s telephone number:" ;telei=new(chart);cin>>telei;cout<<endl;cout<<setw(15)<<"NAME"<<setw(15)<<"TELE NO" ;for (i=0;i<n-1;i+)sele=namei;index=i; for (j=i+1;j<n;j+) if (compword(namej,sele) sele=namej; index=j;swap (nameindex, namei);swap(teleindex, telei);for(i=0;i<n;i+)cout<<endl<<" "<

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝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)論