版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第十章教學(xué)重點(diǎn)1、指針變量的定義、引用2、指針變量的初始化及運(yùn)算3、指向數(shù)組的指針變量4、指向字符串的指針變量5、指針數(shù)組、二級(jí)指針6、指向函數(shù)的指針教學(xué)難點(diǎn)1、指針的運(yùn)算2、指向二維數(shù)組的指針3、用指針處理字符串4、指針數(shù)組、二級(jí)指針5、指針的應(yīng)用10.1地址和指針的概念 為了說(shuō)清楚什么是指針,必須弄清楚數(shù)據(jù)在內(nèi)存中是如何存儲(chǔ)的,又是如何讀取的。 內(nèi)存區(qū)的每一個(gè)字節(jié)有一個(gè)編號(hào),這就是“地址” 。如果在程序中定義了一個(gè)變量,在對(duì)程序進(jìn)行編譯時(shí),系統(tǒng)就會(huì)給這個(gè)變量分配相應(yīng)的內(nèi)存單元。 假設(shè)程序已定義了3個(gè)整型變量i、j、k,編譯時(shí)系統(tǒng)分配2000和2001兩個(gè)字節(jié)給變量i,2002,2003字節(jié)
2、給j,2004,2005給k。、通過(guò)變量名來(lái)對(duì)內(nèi)存單元進(jìn)行存取操作。程序經(jīng)過(guò)編譯后己經(jīng)將變量名轉(zhuǎn)換為變量的地址,按變量地址存取變量值的方式稱為“直接訪問(wèn)”方式 訪問(wèn)方式: k=i+j;的執(zhí)行是:從2000、2001字節(jié)取出i的值(3),再?gòu)?002、2003字節(jié)取出j的值(6),將它們相加后再將其和(9)送到k所占用的2004、2005字節(jié)單元中。例如: printf(%d,i);的執(zhí)行是:根據(jù)變量名與地址的對(duì)應(yīng)關(guān)系(這個(gè)對(duì)應(yīng)關(guān)系是在編譯時(shí)確定的),找到變量i的地址2000,然后從由2000開始的兩個(gè)字節(jié)中取出數(shù)據(jù)(即變量的值3),把它輸出。 scanf(%d,&i);的執(zhí)行是:把從鍵盤輸入的
3、值送到地址為2000開始的整型存儲(chǔ)單元中。2、另一種存取變量值的方式稱為“間接訪問(wèn)”方式。即將變量的地址存放在另一個(gè)變量中。然后通過(guò)這個(gè)變量去訪問(wèn)變量i。 在語(yǔ)言中, 可以定義一種特殊的變量, 它是專門用來(lái)存放其它變量地址的。這種變量稱為“指針變量” 假設(shè)我們定義了一個(gè)指針變量i_pointer用來(lái)存放整型變量的地址,它被分配地址為(3010)、(3011)的兩個(gè)字節(jié)。可以通過(guò)語(yǔ)句: i_pointer ;將i的地址(2000)存放到i_pointer中。 這時(shí),i_pointer的值就是(2000),即變量所占用單元的起始地址。 要存取變量的值,可以采用間接方式:先找到存放 “的地址” 的變
4、量 i_pointer ,從中取出的地址(2000),然后到2000 、 2001字節(jié)取出的值()。 打個(gè)比方,為了開一個(gè)A抽屜,有兩種辦法: 一種是將A鑰匙帶在身上,需要時(shí)直接找出該鑰匙打開抽屜,取出所需的東西。 另一種辦法是:為安全起見,將該A鑰匙放到另一抽屜B中鎖起來(lái)。如果需要打開A抽屜,就需要先找出B鑰匙,打開B抽屜,取出A鑰匙,再打開A抽屜,取出A抽屜中之物,這就是“間接訪問(wèn)”。直接訪問(wèn)將3送到變量i所標(biāo)志的單元中。間接訪問(wèn)將3送到變量i_pointer所“指向”的單元(即i所標(biāo)志的單元)中。 所謂“指向”就是通過(guò)地址來(lái)體現(xiàn)的。i_pointer中的值為2000,它是變量i的地址,這
5、樣通過(guò)i_pointer能知道i的地址,從而找到變量i的內(nèi)存單元。即由于通過(guò)地址能找到所需的變量單元,我們可以說(shuō),地址“指向”該變量單元(如同說(shuō),房間號(hào)“指向”某一房間一樣)。 一個(gè)變量的地址稱為該變量的“指針”。例如,地址2000是變量的指針。如果有一個(gè)變量專門用來(lái)存放另一變量的地址(即指針),則它稱為“指針變量”。上述的i_pointer就是一個(gè)指針變量。指針和指針變量的定義: 指針變量的值(即指針變量中存放的值)是地址(即指針)。請(qǐng)區(qū)分“指針”和“指針變量”這兩個(gè)概念。 例如,可以說(shuō)變量i的指針是2000,而不能說(shuō)i的指針變量是2000。10.2 變量的指針和指向變量的指針變量 變量的指
6、針就是變量的地址。存放變量地址的變量是指針變量,用來(lái)指向另一個(gè)變量。為了表示指針變量和它所指向的變量之間的聯(lián)系,在程序中用“*”符號(hào)表示“指向”,例如: i_pointer代表指針變量,而*i_pointer是i_pointer所指向的變量,如下圖。10.1 定義一個(gè)指針變量定義指針變量的一般形式為: 基類型 *指針變量名;下面都是合法的定義: float *pointer_3; /pointer_3是指向float型變量的指針變量 char *pointer_4; /pointer_4是指向字符型變量的指針變量 可以用賦值語(yǔ)句使一個(gè)指針變量得到另一個(gè)變量的地址,從而使它指向一個(gè)該變量。如:
7、pointer_1&i; pointer_2&j;在定義指針變量時(shí)要注意兩點(diǎn): (1)指針變量前面的“*”,表示該變量的類型為指針型變量。 例: float *pointer_1;指針變量名是pointer_1 ,而不是* pointer_1 。 (2)在定義指針變量時(shí)必須指定基類型。 需要特別注意的是,只有整型變量的地址才能放到指向整型變量的指針變量中。下面的賦值是錯(cuò)誤的 float a; int * pointer_1; pointer_1=&a; /* 將float型變量的地址放到指向整型變量的指針變量中,錯(cuò)誤 */10. 指針變量的引用 請(qǐng)牢記,指針變量中只能存放地址(指針),不要將一
8、個(gè)整數(shù)(或任何其他非地址類型的數(shù)據(jù))賦給一個(gè)指針變量。 下面的賦值是不合法的: pointer-1=100; (pointer-1為指針變量,100為整數(shù))有兩個(gè)有關(guān)的運(yùn)算符: (1) &:取地址運(yùn)算符。 (2) *:指針運(yùn)算符(或稱“間接訪問(wèn)”運(yùn)算符)。 例如:&a為變量a的地址,*p為指針變量p所指向的存儲(chǔ)單元。例10. 通過(guò)指針變量訪問(wèn)整型變量#include stdio.hvoidmain( ) int a,b; int *pointer_1,*pointer_2; a=100;b=10; pointer_1=&a; /*把變量a的地址賦給pointer_1 */ pointer_2=
9、&b; /*把變量b的地址賦給pointer_2*/ printf(%d,%dna,b); printf(%d,%dn,*pointer_1,*pointer_2); 表示定義兩個(gè)指針變量pointer_1、pointer_2。表示pointer_1和pointer_2所指向的變量。 注意區(qū)分注意:不應(yīng)寫成 *pointer_1=&a; *pointer_2=&b; 對(duì)“&”和“*”運(yùn)算符說(shuō)明: 如果已執(zhí)行了語(yǔ)句 pointer_1=&a;(1)*pointer_1的含義是什么? “”和“*”兩個(gè)運(yùn)算符的優(yōu)先級(jí)別相同,但按自右而左方向結(jié)合,因此先進(jìn)行*pointer_1的運(yùn)算,它就是變量a,再
10、執(zhí)行&運(yùn)算。 因此,&*pointer_1與&a相同,即變量a的地址。如果有pointer_2=&*pointer_1;它的作用是將&a(a的地址)賦給pointer_2,如果pointer_2原來(lái)指向b,經(jīng)過(guò)重新賦值后它已不再指向b了,而指向了a。 如下圖(2) *&a的含義是什么? 先進(jìn)行&a運(yùn)算,得a的地址,再進(jìn)行*運(yùn)算。即&a所指向的變量,也就是變量a。*&a和*pointer_的作用是一樣的,它們都等價(jià)于變量a。即*&a與a等價(jià)。(3) (*pointer_1)+相當(dāng)于a+。 注意括號(hào)是必要的,如果沒(méi)有括號(hào),就成為了*pointer_1+,從附錄可知:+和*為同一優(yōu)先級(jí)別,而結(jié)合方向
11、為自右而左。因此它相當(dāng)于*(pointer_1+)。由于+在pointer_1的右側(cè),是“后加”,因此先對(duì)pointer_1的原值進(jìn)行*運(yùn)算,得到a的值,然后使pointer_1的值改變,這樣pointer_1不再指向a了。例10 . 2 輸入a和b兩個(gè)整數(shù),按先大后小的順序輸出 a和b。#include stdio.hvoid main() int *p1,*p2,a,b; scanf(%d,%d,&a,&b); p1=&a;p2=&b; if (ab) p=p1;p1=p2;p2=p;printf(a=%d,b=%dnn,a,b); printf(max=%d,min=%dn,*p1,*p
12、2);指針變量應(yīng)用例子運(yùn)行情況如下: 5,9 a=5,b=9 max=9,min=5當(dāng)輸入a=5,b=9時(shí),由于ab,將p1和p2交換。交換前的情況見圖(a),交換后見圖(b)。注意:a和b并未交換,它們?nèi)员3衷担玴1和p2的值改變了。p1的值原為&a,后來(lái)變成&b,p2原值為&b,后來(lái)變成&a。這個(gè)問(wèn)題的算法不是交換整型變量的值,而是交換兩個(gè)指針變量的值(即a和b的地址)。10.3 指針變量作為函數(shù)參數(shù)例10 . 3 對(duì)輸入的兩個(gè)整數(shù)按大小順序輸出 #include void main() void swap(int *p1,int *p2); int a,b; int *pointer
13、_1,*pointer_2; scanf(%d,%d,&a,&b); pointer_1=&a;pointer_2=&b; if (ab) swap(pointer_1,pointer_2); printf(n%d,%dn,a,b); void swap(int *p1,int *p2) int temp; temp=*p1; *p1=*p2; *p2=temp;注意:本例采取的方法是,交換a和b的值,而p1和p2的值不變。這恰和例10.2相反。如果寫成以下這樣會(huì)怎樣?void swap1(int *p1,int *p2) int temp; *temp=*p1; p1=*p2; p2=*te
14、mp;請(qǐng)注意交換*p1和*p2的值是如何實(shí)現(xiàn)的。 *p1就是a,是整型變量。而*temp是指針變量temp所指向的變量。但temp中并無(wú)確定的地址值,它的值是不可預(yù)見的,*temp所指向的單元也是不可預(yù)見的。因此,對(duì)*temp賦值可能會(huì)破壞系統(tǒng)的正常工作狀況。此語(yǔ)句有問(wèn)題 應(yīng)該將*p1的值賦給一個(gè)整型變量,如程序所示那樣,用整型變量temp作為臨時(shí)輔助變量實(shí)現(xiàn)*p1和*p2的交換。 這個(gè)改變不是通過(guò)將形參值傳回實(shí)參來(lái)實(shí)現(xiàn)的。而是因?qū)崊⒑托螀⒍际侵羔樧兞浚瑢?shí)參傳遞給形參后,實(shí)參和形參指向共同的變量,在被調(diào)用函數(shù)中,交換了形參指針?biāo)赶虻淖兞恐?,也即是交換了實(shí)參指針?biāo)赶蜃兞康闹怠?例10.3中,
15、在執(zhí)行Swap函數(shù)后,變量a和b的值改變了。這個(gè)改變是怎么實(shí)現(xiàn)的?能否通過(guò)下面的函數(shù)實(shí)現(xiàn)a和b的互換。void swap2(int x,int y)int temp; temp=x; x=y; y=temp; 如果在main函數(shù)中調(diào)用Swap2函數(shù): swap(a,b); 會(huì)有什么結(jié)果呢? 如圖所示。在函數(shù)調(diào)用時(shí),a的值傳送給x,b的值傳送給y。執(zhí)行完Swap2函數(shù)后,x和y的值是互換了,但main函數(shù)中的a和b并未互換。也就是說(shuō)由于“單向傳送”的“值傳遞”方式,形參值的改變無(wú)法傳給實(shí)參。 為了使在函數(shù)中改變了的變量值能被main函數(shù)所用,不能采取上述的辦法,而應(yīng)該用指針變量作為函數(shù)參數(shù),在函
16、數(shù)執(zhí)行過(guò)程中使指針變量所指向的變量值發(fā)生變化,函數(shù)調(diào)用結(jié)束后,這些變量值的變化依然保留下來(lái),這樣就實(shí)現(xiàn)了“通過(guò)調(diào)用函數(shù)使變量的值發(fā)生變化,在主調(diào)函數(shù)(如main函數(shù))中使用這些改變了的值”的目的。 如果想通過(guò)函數(shù)調(diào)用得到n個(gè)要改變的值,可以:在主調(diào)函數(shù)中設(shè)n個(gè)變量,用n個(gè)指針變量指向它們;然后將指針變量作實(shí)參,將這n個(gè)變量的地址傳給所調(diào)用的函數(shù)的形參指針;通過(guò)形參指針變量,改變?cè)搉個(gè)變量的值;主調(diào)函數(shù)中就可以使用這些改變了值的變量。請(qǐng)讀者按此思路仔細(xì)理解例10.3程序。viod swap(int *p1,int *p2) intp; p=p1;p1=p2;p2=p;void main( ) i
17、nt a,b; int pointer-1,*pointer-2;scanf(%d,%d,&a,&b); pointer-1=&a;pointer-2=&b;if(ab) swap(pointer-1,pointer-2); printf(n%d,%dn,*pointer-1,*pointer-2); 請(qǐng)注意,不能企圖通過(guò)改變指針形參的值而使指針實(shí)參的值改變。請(qǐng)看下面的程序:作者的意圖是:交換pointer-1和pointer-2的值,使pointer-1指向值大的變量。其設(shè)想是:先使pointer-1指向a,pointer-2指向b,見下圖(a)。調(diào)用swap函數(shù),將pointer-1的值傳
18、給p1,pointer-2傳給p2,見下圖(b)。在swap函數(shù)中使p1與p2的值交換,見下圖(c)。形參p1和p2將地址傳回實(shí)參pointer-1和pointer-2,使pointer-1指向B,pointer-2指向a,見下圖(d)。輸出*pointer-1和*pointer-2,得到輸出“9,5”。 但是這是辦不到的,程序?qū)嶋H輸出為“5,9”。問(wèn)題出在第步。C語(yǔ)言中實(shí)參變量和形參變量之間的數(shù)據(jù)傳遞是單向的“值傳遞”方式。指針變量作函數(shù)參數(shù)也要遵循這一規(guī)則。 調(diào)用函數(shù)不可能改變實(shí)參指針變量的值,但可以改變實(shí)參指針變量所指變量的值。我們知道,函數(shù)的調(diào)用可以(而且只可以)得到一個(gè)返回值(即函數(shù)
19、值),而運(yùn)用指針變量作參數(shù),可以得到多個(gè)變化了的值。如果不用指針變量是難以做到這一點(diǎn)的。例10. 輸入 a,b,c 三3個(gè)整數(shù),按大小順序輸出#include void main() void exchange(int *q1,int *q2,int *q3);int a,b,c,*p1,*p2,*p3; scanf(%d,%d,%d,&a,&b,&c); p1=&a;p2=&b;p3=&c; exchange(p1,p2,p3); printf(n%d,%d,%dn,a,b,c);void exchange(int *q1,int q2,int q3) void swap(int *pt1,
20、int *pt2); if(*q1q2) swap(q1,q2);if(*q1q3) swap(q1,q3);if(*q2q3) swap(q2,q3); void swap(int *pt1,int *pt2)int temp; temp*pt1; *pt1=*pt2; *pt2=temp; 10.3 數(shù)組與指針 一個(gè)變量有地址,一個(gè)數(shù)組包含若干元素,每個(gè)數(shù)組元素都在內(nèi)存中占用存儲(chǔ)單元,它們都有相應(yīng)的地址。指針變量既然可以指向變量,當(dāng)然也可以指向數(shù)組元素(把某一元素的地址放到一個(gè)指針變量中)。所謂數(shù)組元素的指針就是數(shù)組元素的地址。 定義一個(gè)指向數(shù)組元素的指針變量的方法,與以前介紹的指向變量的
21、指針變量相同。例如: ; (定義為包含個(gè)整型數(shù)據(jù)的數(shù)組)*; (定義為指向整型變量的指針變量)應(yīng)當(dāng)注意,如果數(shù)組為型,則指針變量的基類型亦應(yīng)為型。 10.3.1 指向數(shù)組元素的指針對(duì)該指針變量賦值:;把元素的地址賦給指針變量。也就是使指向數(shù)組的第號(hào)元素,如圖:10.通過(guò)指針引用數(shù)組元素引用一個(gè)數(shù)組元素,可以用:() 下標(biāo)法,如形式;() 指針?lè)?,?()或*()。其中是數(shù)組名,是指向數(shù)組元素的指針變量,其初值。例10.5 輸出數(shù)組中的全部元素 假設(shè)有一個(gè)數(shù)組,整型,有個(gè)元素。要輸出各元素的值有三種方法: (1)下標(biāo)法#include void main() int ; int;for(;)sc
22、anf(,); printf();for(;)printf(,); (2) 通過(guò)數(shù)組名計(jì)算數(shù)組元素地址,找出元素的值。#include voidmain() int ; int ;for(; )scanf(,);printf(); for(;) printf(,*(); (3) 用指針變量指向數(shù)組元素。#include void main() int ; int *,; for(;) scanf(,); printf(); for(;();) printf( ,*); 例10. 通過(guò)指針變量輸出數(shù)組的個(gè)元素。 有人編寫出以下程序:#include void main() int*,;for(;
23、 )scanf(,); printf(); for(;, ) printf(,*);這個(gè)程序乍看起來(lái)好像沒(méi)有什么問(wèn)題。有的人即使已被告知此程序有問(wèn)題,還是找不出它有什么問(wèn)題。我們先看一下運(yùn)行情況:1 2 3 4 5 6 7 8 9 022153 234 0 0 30036 25202 11631 8259 8237 28483顯然輸出的數(shù)值并不是數(shù)組中各元素的值 解決這個(gè)問(wèn)題的辦法,只要在第二個(gè)循環(huán)之前加一個(gè)賦值語(yǔ)句:;#include void main() int*,;for(;)scanf(,); printg(); p=a; for(;, ) printf(,*);10.3 用數(shù)組名作
24、函數(shù)參數(shù)在第8章8.7節(jié)中介紹過(guò)可以用數(shù)組名作函數(shù)的參數(shù)如: void main() i(int ,int ); int ; (,); void (int ,int ) f (int arr , int n)但在編譯時(shí)是將arr按指針變量處理的,相當(dāng)于將函數(shù)f的首部寫成f (int *arr, int n)以上兩種寫法是等價(jià)的。 需要說(shuō)明的是:C語(yǔ)言調(diào)用函數(shù)時(shí)虛實(shí)結(jié)合的方法都是采用“值傳遞”方式,當(dāng)用變量名作為函數(shù)參數(shù)時(shí)傳遞的是變量的值,當(dāng)用數(shù)組名作為函數(shù)參數(shù)時(shí),由于數(shù)組名代表的是數(shù)組首元素地址,因此傳遞的值是地址,所以要求形參為指針變量。例10 將數(shù)組中個(gè)整數(shù)按相反順序存放#include
25、void main() void inv(int ,int ); int , ,;printf(The original array:);for(;)printf (,);printf(); inv (,); printf(The array has been in verted:); for(;) printf (,); printf ();void inv(int ,int ) /*形參x是數(shù)組名*/ int temp,();for(;) ;temp; ; temp; return; 運(yùn)行情況如下:The original array:,The array has been inverte
26、d:,#include void main()void inv(int *,int ); int , ,; printf( The original array: ); for(;) printf (,); printf (); inv(,); printf ( The array has been in verted: ); for(;)printf (,);printf ();對(duì)這個(gè)程序可以作一些改動(dòng)。將函數(shù)inv中的形參改成指針變量。 void inv(int *,int ) /*形參x為指針變量*/int,temp,*,*,(); ; for(;,) emp*;*;*temp;retu
27、rn; 歸納起來(lái),如果有一個(gè)實(shí)參數(shù)組,想在函數(shù)中改變此數(shù)組中的元素的值,實(shí)參與形參的對(duì)應(yīng)關(guān)系有以下種情況: (1) 形參和實(shí)參都用數(shù)組名,如:void main() void (int ,int ) int ; (,); (2) 實(shí)參用數(shù)組名,形參用指針變量。如:void () void (int *,int )int ; (,); (3)實(shí)參形參都用指針變量。例如:void main() void (int *,int )int , *p=a; (p,); (4) 實(shí)參為指針變量,形參為數(shù)組名。如: void main() void (int x ,int ) ,*p=a; (p,); #i
28、nclude void main() void inv(int *,int ); int ,*; printf(The original array:n ); for(;,)scanf(,);printf(); ; inv(,); /* 實(shí)參為指針變量 */ printf(The array has been inverted :); for(; ) printf(,*); printf(); void inv(int *,int )int,temp,*,*;(); ;for(;,)emp*;*;*temp;return; 例109 用選擇法對(duì)個(gè)整數(shù)按由大到小順序排序 #include voi
29、d main() void sort(int ,int ); int*,10; ; for(;) scanf(,); ; sort(,); for(,;)(,*);void sort(int ,int ) int ,; for(;);for(;)() ; (!); ; ; 10. 多維數(shù)組與指針 用指針變量可以指向一維數(shù)組中的元素,也可以指向多維數(shù)組中的元素。但在概念上和使用上,多維數(shù)組的指針比一維數(shù)組的指針要復(fù)雜一些。 1. 多維數(shù)組元素的地址先回顧一下多維數(shù)組的性質(zhì),可以認(rèn)為二維數(shù)組是“數(shù)組的數(shù)組”,例 :定義int a34=1,3,5,7,;則二維數(shù)組a是由3個(gè)一維數(shù)組所組成的。設(shè)二維數(shù)
30、組的首行的首地址為 ,則表 示 形 式含義地 址a 二維數(shù)組名,指向一維數(shù)組a0,即0行首地址2000a0,*(a+0),*a0行0列元素地址2000a+1,&a11行首地址2008a1,*(a+1)1行0列元素a10的地址2008a1+2,*(a+1)+2,&a121行2列元素a12 的地址2012*(a1+2),*(*(a+1)+2),a121行2列元素a12的值元素值為13例10.0 輸出二維數(shù)組有關(guān)的值 #include define FROMAT,void main() int 341,3,5,7,9, ,; printf(,*); printf(,0 , *();printf(,0
31、,00);printf(,1,);printf(,10,*(+)+);printf(,*();printf(,); printf(,*(*( ); 某一次運(yùn)行結(jié)果如下:, (0行首地址和0行0列元素地址), (0行0列元素地址), (0行0首地址和0行0列元素地址), (1行0列元素地址和1行首地址), (1行0列元素地址), (2行0列元素地址), (2行首地址), (1行0列元素的值)2 . 指向多維數(shù)組元素的指針變量在了解上面的概念后,可以用指針變量指向多維數(shù)組的元素。(1) 指向數(shù)組元素的指針變量例10.11 用指針變量輸出二維數(shù)組元素的值 #include void main() i
32、nt 341,3,5,7,9,11,13,15,17,19,21,23; int*; for(;) () printf(); printf(,*); 運(yùn)行結(jié)果如下:1 3 5 7 9 11 13 1519 21 23 可將程序最后兩個(gè)語(yǔ)句改為printf(addr, value2,*);在TC+環(huán)境下某一次運(yùn)行時(shí)輸出如下:,例10.13 出二維數(shù)組任一行任一列元素的值 (2) 指向由個(gè)元素組成的一維數(shù)組的指針變量#include void main ( ) int 1,3,5,7,9,11, 13,15,;int (*),; ;scanf( ,); printf(, ,*(*(); 運(yùn)行情況如
33、下:, (本行為鍵盤輸入),運(yùn)行情況如下:,(本行為鍵盤輸入),3. 用指向數(shù)組的指針作函數(shù)參數(shù)例10.13 有一個(gè)班,個(gè)學(xué)生,各學(xué)門課,計(jì)算總平均分?jǐn)?shù)以及第個(gè)學(xué)生的成績(jī)。這個(gè)題目是很簡(jiǎn)單的。只是為了說(shuō)明用指向數(shù)組的指針作函數(shù)參數(shù)而舉的例子。用函數(shù)求總平均成績(jī),用函數(shù)找出并輸出第個(gè)學(xué)生的成績(jī)。#include void main() void average(float *p,int n); void search(float (*p)4,int n); float score34=65,67,70,60,80, 87,90,81,90,99,100,98; average(*score,12
34、);*求12個(gè)分?jǐn)?shù)的平均分*search(score,);*求序號(hào)為的學(xué)生的成績(jī)*void average(float *,int ) float*_; float ,; _; (;_;) (*); ; printf(average,aver);void search(float (*)4,int ) / * p是指向具有4個(gè)元素的一維數(shù)組的指針 */int ; printf(the score of No. % are:,); for(;) printf(5.2,*(*(); 程序運(yùn)行結(jié)果如下: :.例10.4 在上題基礎(chǔ)上,查找有一門以上課程不及格的學(xué)生,打印出他們的全部課程的成績(jī)。 #i
35、nclude void main()void search(float (*p)4,int n);/*函數(shù)聲明*/ float score34=65,57,70,60,58,87, 90,81,90,99,100,98; search(score,);void search(float (*p)4,int )int ,; for(;) flag; for(;) if(*(*()flag; if() printf(No.%d fails,his scores are:n,j+1); for(;) printf(%.,*(*(); printf(); 程序運(yùn)行結(jié)果如下: s, :. . . . s
36、, . . . .10. 字符串與指針10字符串的表示形式 例 10.5 定義一個(gè)字符數(shù)組,對(duì)它初始化, 然后輸出該字符串 #include void main()char string ??; printf(,); (1) 用字符數(shù)組存放一個(gè)字符串,然后輸出該字符串。(2) 用字符指針指向一個(gè)字符串 可以不定義字符數(shù)組,而定義一個(gè)字符指針。用字符指針指向字符串中的字符。例106 定義字符指針#include void main()charstring !;printf(,);對(duì)字符串中字符的存取,可以用下標(biāo)方法,也可以用指針?lè)椒?例10.7 將字符串復(fù)制為字符串 #include void (
37、)char am a boy,20; int ; for(;*()??;) *()*(); *(); printf(string a is :,); printf( :); for(;!;) printf(,); printf(); 也可以設(shè)指針變量,用它的值的改變來(lái)指向字符串中的不同的字符。 例10.8 用指針變量來(lái)處理例107問(wèn)題。#include void main() char =I am a boy. ,20,*p1,*p2; int ; ; for(;*!;p1,p2)*;*;printf(string is:,); printf( :);for(;??;) printf(,); pr
38、intf();程序必須保證使和同步移動(dòng)。 10. 字符指針作函數(shù)參數(shù)例1019 用函數(shù)調(diào)用實(shí)現(xiàn)字符串的復(fù)制 #include void main() void copy_string(char from , char to ); char a = am a teacher; char =you are a student; printf(“string a= string , ,); printf(copy string a to string b:n ); copy_string (,); printf(nstring a=%snstring b=%sn,a,b); (1) 用字符數(shù)組作參數(shù)
39、void copy_string(char from , char to ) int ; while(!); 程序運(yùn)行結(jié)果如下: copy string a to string b: () 形參用字符指針變量 #include void main() void copy_string(char *, char *); char * am a teacher .; char *you are a student ; printf(string a= ,); printf(copy string a to string b:n ); _(,); printf(nstring a=%snstring
40、 b=%sn,a,b); void copy_string(char *,char *) for(;*from!;from,to)*;*; () 對(duì) copy_string 函數(shù)還可作簡(jiǎn)化 1、將copy_string函數(shù)改寫為void copy_string (char *,char *) while(*)!) ; 2、 copy_string函數(shù)的函數(shù)體還可改為 while(*to*from)!); 3、copy_string函數(shù)的函數(shù)體還可寫成 while(*!)*; *; 4、上面的while語(yǔ)句還可以進(jìn)一步簡(jiǎn)化為下面的while語(yǔ)句:while(*);它與下面語(yǔ)句等價(jià):while(*
41、to*from)!);將*賦給*,如果賦值后的*值等于,則循環(huán)終止(已賦給*) 5、函數(shù)體中語(yǔ)句也可以改用語(yǔ)句:for(;(*to*from)?。?;或for(;*to*from;);6、也可用指針變量,函數(shù)copy_string可寫為void copy_string (char from ,char )*,*; ;while(*p2*p1)!);10. 對(duì)使用字符指針變量和字符數(shù)組的討論雖然用字符數(shù)組和字符指針變量都能實(shí)現(xiàn)字符串的存儲(chǔ)和運(yùn)算,但它們二者之間是有區(qū)別的,不應(yīng)混為一談,主要有以下幾點(diǎn):(1) 字符數(shù)組由若干個(gè)元素組成,每個(gè)元素中放一個(gè)字符,而字符指針變量中存放的是地址(字符串第1
42、個(gè)字符的地址),決不是將字符串放到字符指針變量中。(2)賦值方式。對(duì)字符數(shù)組只能對(duì)各個(gè)元素賦值,不 能用以下辦法對(duì)字符數(shù)組賦值。 char str; str ?。?而對(duì)字符指針變量,可以采用下面方法賦值: char*; ?。?但注意賦給的不是字符,而是字符串第一個(gè)元素 的地址。(3)對(duì)字符指針變量賦初值: char * love China??;等價(jià)于 char*; ??; 而對(duì)數(shù)組的初始化: char str love China!; 不能等價(jià)于 char str; str ??;(4) 如果定義了一個(gè)字符數(shù)組,在編譯時(shí)為它分配內(nèi)存單元,它有確定的地址。而定義一個(gè)字符指針變量時(shí),給指針變量分配內(nèi)存
43、單元,在其中可以放一個(gè)字符變量的地址也就是說(shuō),該指針變量可以指向一個(gè)字符型數(shù)據(jù),但如果未對(duì)它賦予一個(gè)地址值,則它并未具體指向一個(gè)確定的字符數(shù)據(jù)。 如: char str; scanf(,str);是可以的。而常有人用下面的方法,目的是想輸入一個(gè)字符串,雖然一般也能運(yùn)行,但這種方法是危險(xiǎn)的 : char*; scanf(,);應(yīng)當(dāng)這樣:*,;(,);(5) 指針變量的值是可以改變的,如:例10.0改變指針變量的值#include void ()char*I love China!; ; printf(,); 需要說(shuō)明,若定義了一個(gè)指針變量,并使它指向一個(gè)字符串,就可以用下標(biāo)形式引用指針變量所指的
44、字符串中的字符。例101 #include voidmain()char* love hina!; int ; printf ( “ The sixth character is %cn,a5); for(;??;) printf(,); 10. 指向函數(shù)的指針10. 用函數(shù)指針變量調(diào)用函數(shù)可以用指針變量指向整型變量、字符串、數(shù)組,也可以指向一個(gè)函數(shù)。一個(gè)函數(shù)在編譯時(shí)被分配給一個(gè)入口地址。這個(gè)函數(shù)的入口地址就稱為函數(shù)的指針。 例10.2 求和中的大者。先列出按一般 方法的程序。#include voidmain() int max(int,int); int ,;scanf(,); (,);pr
45、intf(, ,); int max(int ,int ) int ; if();else ; return(); 將 main 函數(shù)改寫為#include voidmain() int (int,int); int (*)(); int ,; ; scanf(,); (*)(,); printf(, ,); 10. 用指向函數(shù)的指針作函數(shù)參數(shù)函數(shù)指針變量常用的用途之一是把指針作為參數(shù)傳遞到其他函數(shù)。前面介紹過(guò),函數(shù)的參數(shù)可以是變量、指向變量的指針變量、數(shù)組名、指向數(shù)組的指針變量等?,F(xiàn)在介紹指向函數(shù)的指針也可以作為參數(shù),以實(shí)現(xiàn)函數(shù)地址的傳遞,這樣就能夠在被調(diào)用的函數(shù)中使用實(shí)參函數(shù)。它的原理可以
46、簡(jiǎn)述如下:有一個(gè)函數(shù)(假設(shè)函數(shù)名為sub),它有兩個(gè)形參(x1和x2),定義x1和x2為指向函數(shù)的指針變量。在調(diào)用函數(shù)sub時(shí),實(shí)參為兩個(gè)函數(shù)名和,給形參傳遞的是函數(shù)和的地址。這樣在函數(shù)中就可以調(diào)用和函數(shù)了。 實(shí)參函數(shù)名 f1 void (int (*x1)(int),int (*x2)(int,int) int ,; (*)(); *調(diào)用函數(shù)* (*)(,);*調(diào)用函數(shù)* 例10.3 設(shè)一個(gè)函數(shù)process,在調(diào)用它的時(shí)候,每次實(shí)現(xiàn)不同的功能。輸入和兩個(gè)數(shù),第一次調(diào)用process時(shí)找出和中大者,第二次找出其中小者,第三次求與之和。 #include void main() int max
47、(int,int); /* 函數(shù)聲明 */ int min(int,int); /* 函數(shù)聲明 */ int add(int,int); /* 函數(shù)聲明 */ void process (int,int,int(*fun)(); /* 函數(shù)聲明 */ int ,; printf( :); scanf(,);(); (,);();(,);();(,);int (int ,int ) /* 函數(shù)定義 */ ; (); ; ();int (int ,int ) /* 函數(shù)定義 */ ; (); ;(); int (int ,int ) /* 函數(shù)定義 */ ; ; ();void process(i
48、nt ,int ,int (*fun)(int,int) ; (*)(,); (,);10. 返回指針值的函數(shù)一個(gè)函數(shù)可以帶回一個(gè)整型值、字符值、實(shí)型值等,也可以帶回指針型的數(shù)據(jù),即地址。其概念與以前類似,只是帶回的值的類型是指針類型而已。這種帶回指針值的函數(shù),一般定義形式為類型名 *函數(shù)名(參數(shù)表列);例如:*(int ,int );例104 有若干個(gè)學(xué)生的成績(jī)(每個(gè)學(xué)生有門課程),要求在用戶輸入學(xué)生序號(hào)以后,能輸出該學(xué)生的全部成績(jī)。用指針函數(shù)來(lái)實(shí)現(xiàn)。 #include void main()float score 4=60,70,80,90, 56,89,67,88,34,78,90,66
49、; float*search(float (*pointer)4,int n); float*; int ,; printf(enter the number of student:); scanf(,); printf(The scores of No are:,); search(,);for(;)printf(,*(); float * search(float (*)4,int ) float *; *(); return(); 運(yùn)行情況如下:enter the number of student:The scores of No. are:56.00 89.00 67.00 88.0
50、0例105 對(duì)上例中的學(xué)生,找出其中有不及格課程的學(xué)生及其學(xué)生號(hào)。#include void main()float score 4=60,70,80,90,56, 89,67,88,34,78,90,66; float search(float (*pointer)4); float*; i ,; for(;)(); (*()printf(scores:,); for(;) printf(,*(); printf(); 10.指針數(shù)組和指向指針的指針10. 指針數(shù)組的概念 一個(gè)數(shù)組,若其元素均為指針類型數(shù)據(jù),稱為指針數(shù)組,也就是說(shuō),指針數(shù)組中的每一個(gè)元素都相當(dāng)于一個(gè)指針變量。一維指針數(shù)組的定
51、義形式為類型名*數(shù)組名數(shù)組長(zhǎng)度;例如:*; 由于 比*優(yōu)先級(jí)高,因此p先與4結(jié)合,形成p4形式,這顯然是數(shù)組形式,它有4個(gè)元素。然后再與p前面的“*”結(jié)合,“*”表示此數(shù)組是指針類型的,每個(gè)數(shù)組元素(相當(dāng)于一個(gè)指針變量)都可指向一個(gè)整型變量。注意與 int(*p)4 的區(qū)別。 為什么要用到指針數(shù)組呢?它比較適合于用來(lái)指向若干個(gè)字符串,使字符串處理更加方便靈活。 例如,圖書館有若干本書,想把書名放在一個(gè)數(shù)組中(圖10.41(a),然后要對(duì)這些書目進(jìn)行排序和查詢。按一般方法,字符串本身就是一個(gè)字符數(shù)組。因此要設(shè)計(jì)一個(gè)二維的字符數(shù)組才能存放多個(gè)字符串。但在定義二維數(shù)組時(shí),需要指定列數(shù),也就是說(shuō)二維數(shù)
52、組中每一行中包含的元素個(gè)數(shù)(即列數(shù))相等。而實(shí)際上各字符串(書名)長(zhǎng)度一般是不相等的。如按最長(zhǎng)的字符串來(lái)定義列數(shù),則會(huì)浪費(fèi)許多內(nèi)存單元。見圖10.41(b)。 可以分別定義一些字符串,然后用指針數(shù)組中的元素分別指向各字符串,見圖10.41(C)。如果想對(duì)字符串排序,不必改動(dòng)字符串的位置,只需改動(dòng)指針數(shù)組中各元素的指向(即改變各元素的值,這些值是各字符串的首地址)。這樣,各字符串的長(zhǎng)度可以不同,而且移動(dòng)指針變量的值(地址)要比移動(dòng)字符串所花的時(shí)間少得多。例106 將若干字符串按字母順序(由小到大)輸出。#include #include void main()void sort(char *na
53、me ,int n); void printf(char *name ,int n); char *name =Follow me,BASIC,Great Wall,F(xiàn)ORTRAN,Computer design; int ;sort(,); print(,);void sort(char * ,int )char *; int ,; for(;); for(;) if(strcmp(name,name)0)=; if(!) temp=namei; namei=namek; namek=temp; void print(char * ,int ) ; (;) printf(,); 運(yùn)行結(jié)果為:
54、 在main函數(shù)中定義指針數(shù)組name。它有5個(gè)元素,其初值分別是“Follow me”、“BASIC”、“Great all”、“FORTRAN”,“Computer Design”的首地址。見圖10.41(C)。這些字符串是不等長(zhǎng)的(并不是按同一長(zhǎng)度定義的)。Sort函數(shù)的作用是對(duì)字符串排序。Sort函數(shù)的形參name也是指針數(shù)組名,接受實(shí)參傳過(guò)來(lái)的name數(shù)組的首地址,因此形參name數(shù)組和實(shí)參name數(shù)組指的是同一數(shù)組。用選擇法對(duì)字符串排序。strcmp是字符串比較函數(shù),namek和namej是第k個(gè)和第j個(gè)字符串的起始地址。strcmp(namek,namej)的值為:如果namek所指的字符串大于namej所指的字符串,則此函數(shù)值為正值;若相等,則函數(shù)值為0;若小于, 則函數(shù)值為負(fù)值。if語(yǔ)句的作用是將兩個(gè)串中“小”的那個(gè)串的序號(hào)(i或j之一)保留在變量k中。當(dāng)執(zhí)行完內(nèi)循環(huán)for語(yǔ)句后,從第i個(gè)串到第n個(gè)串這么多字符串中,第k個(gè)串最“小”。若ki就表示最小的串不是第i串。故將namei和namek對(duì)換,也就是將指向第i個(gè)串的數(shù)組元素(是指針型元素)與指向第k個(gè)串的數(shù)組元素對(duì)換。執(zhí)行完Sort函數(shù)后指針數(shù)組的情
溫馨提示
- 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ù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年民房買賣合同社區(qū)配套服務(wù)協(xié)議4篇
- 二零二五版鋁型材產(chǎn)品研發(fā)與市場(chǎng)推廣合作協(xié)議4篇
- 二零二五版房產(chǎn)買賣合同公證與風(fēng)險(xiǎn)評(píng)估報(bào)告3篇
- 二零二五年度醫(yī)院?jiǎn)T工勞動(dòng)爭(zhēng)議處理與調(diào)解合同4篇
- 二零二五年度大型商場(chǎng)智能門禁系統(tǒng)裝修合同正本規(guī)范版2篇
- 2025年度綠色生態(tài)工程苗木供應(yīng)合同范本4篇
- 二零二五年度創(chuàng)業(yè)項(xiàng)目合作協(xié)議范本4篇
- 二零二五版建筑工程內(nèi)部承包合同(裝配式)2篇
- 2025年度地質(zhì)勘探測(cè)繪技術(shù)合作協(xié)議4篇
- 2025年度產(chǎn)學(xué)研合作開發(fā)合同:5G通信技術(shù)與應(yīng)用4篇
- 2205雙相不銹鋼的焊接工藝
- 2023年全國(guó)高中數(shù)學(xué)聯(lián)賽江西省預(yù)賽試題及答案
- 啤酒廠糖化車間熱量衡算
- 英文標(biāo)點(diǎn)符號(hào)用法(句號(hào)分號(hào)冒號(hào)問(wèn)號(hào)感嘆號(hào))(課堂)課件
- 22部能夠療傷的身心靈療愈電影
- 領(lǐng)導(dǎo)干部有效授權(quán)的技巧與藝術(shù)課件
- DB37-T 1915-2020 安全生產(chǎn)培訓(xùn)質(zhì)量控制規(guī)范-(高清版)
- 陜西省商洛市各縣區(qū)鄉(xiāng)鎮(zhèn)行政村村莊村名居民村民委員會(huì)明細(xì)
- 實(shí)習(xí)生請(qǐng)假條
- 光伏電站繼電保護(hù)運(yùn)行規(guī)程
- 廚房的管理流程與制度及廚房崗位工作流程
評(píng)論
0/150
提交評(píng)論