C語言程序設計項目化教程課件-模塊6_第1頁
C語言程序設計項目化教程課件-模塊6_第2頁
C語言程序設計項目化教程課件-模塊6_第3頁
C語言程序設計項目化教程課件-模塊6_第4頁
C語言程序設計項目化教程課件-模塊6_第5頁
已閱讀5頁,還剩72頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

模塊六

使用指針實現(xiàn)學生成績操作模塊學習目標1.理解和掌握指針的含義;2.掌握指針的定義、初始化和使用方法;3.了解指針和數組的關系。指針的相關概念指針與一維數組指針與二維數組指針與字符串指針與函數指向指針的指針和指針數組使用指針實現(xiàn)學生成績操作6.1指針的相關概念一、地址和指針系統(tǒng)的內存就好比是帶有編號的房間,如果想使用內存就需要得到房間編號。定義一個整型變量i,一個整型變量需要4個字節(jié),如果該變量的起始編號為1000,那么編譯器為該變量分配的編號為1000~1003。地址就是內存區(qū)中對每個字節(jié)的編號,如1000、1001、1002和1003就是地址。C程序中所定義的每一個變量都會被分配若干個連續(xù)的內存單元,變量的值就存放在這些內存單元中;變量被分配的內存單元數量由變量的類型決定,除了共用體外,不同的變量使用不同的內存單元。6.1指針的相關概念下圖中所示的1000、1004等就是內存單元的地址,而0、1就是內存單元的內容,也就是基本整型變量i在內存中的地址從1000開始,因基本整型占4個字節(jié),所以變量j在內存中的起始地址為1004。6.1指針的相關概念二、指針與指針變量指針就是某個對象所占用的內存單元的首地址。例如,變量i的首地址1000就是變量i的指針。變量的地址就是變量和指針二者之間連接的紐帶,如果一個變量包含了另一個變量的地址,則可以理解成第一個變量指向第二個變量。存放變量地址的變量稱為指針變量,指針變量是指向一個變量的地址。指針變量與變量在內存中的關系右圖所示:

通過1000這個地址能訪問2000的存儲單元,再通過2000找到對應的數據。6.1指針的相關概念1.指針變量的一般形式指針變量的一般形式為:

類型說明*指針變量名其中“*”表示該變量是一個指針變量,類型說明表示該指針變量所指向的變量的數據類型,例如int*q6.1指針的相關概念2.指針變量的賦值指針變量同普通變量一樣,使用之前不僅需要定義,而且必須賦予具體的值,未經賦值的指針變量不能使用,同時,指針變量賦值只能賦予地址,而不能賦予任何其他數據,賦值的一般形式為:

指針變量名=&變量名;6.1指針的相關概念例如,&a表示變量a的地址,&b表示變量b的地址。給一個指針變量賦值可以有以下兩種方法:(1)在定義指針變量的同時進行賦值,例如:

inta;

int*p=&a;(2)先定義指針變量,然后再賦值,例如:

inta;

int*p;

p=&a;注意:這兩種賦值語句的區(qū)別在于如果在定義完指針變量之后再賦值不能加“*”。6.1指針的相關概念實例6-1-1:輸出變量地址。本實例定義一個變量,之后以十六進制格式輸出變量的地址。具體代碼如下:#include<stdio.h>intmain(){inta;int*ipointer1;/*聲明指針變量*/printf("請輸入數據:\n");scanf("%d",&a);ipointer1=&a;/*將地址賦給指針變量*/

printf("轉化十六進制為:%x\n",ipointer1);/*以十六進制輸出*/return0;}6.1指針的相關概念3.指針變量的引用引用指針變量是對變量進行間接訪問的一種形式。指針變量的引用形式為:

*指針變量6.1指針的相關概念實例6-1-2:利用指針編寫程序,將兩個數予以交換。本實例定義一個swap函數,要求它的參數是指針類型,所要實現(xiàn)的功能是將兩個數進行交換。具體代碼如下:

#include<stdio.h>voidswap(int*a,int*b)/*自定義交換函數*/{

intt=*a;/*實現(xiàn)兩數交換*/

*a=*b;

*b=t;}

intmain()/*主函數main*/{

intx=10,y=5;

swap(&x,&y);/*調用函數實現(xiàn)兩數交換值*/

printf("交換數據是:x=%d,y=%d\n",x,y);

return0;}6.1指針的相關概念4.運算符“&”和“*”運算符&是一個返回操作數地址的單目運算符,也叫取地址運算符,例如:p=&i;就是將i的內存地址賦值給p,這個地址是該變量在計算機內部的存儲位置。運算符*是單目運算符,也叫指針運算符,作用是返回指定的地址內的變量的值。例如:q=*p;如果p中裝有變量i的內存地址,則變量i的值賦給q,假設變量i的值是5,則q的值也是5。6.1指針的相關概念5.“&*”和“*&”區(qū)別“&”和“*”運算符優(yōu)先級別相同,按自右而左的方向結合。

inta;

p=&a;“&*p”先進行“*”運算,“*p”相當于變量a,再進行“&”運算,“&*p”相當于取變量a的地址?!?&a”先進行“&”運算,“&a”就是取變量a的地址,然后執(zhí)行“*”運算,“*&a”相當于取變量a所在地址的值,實際就是變量a。6.1指針的相關概念實例6-1-3:輸出i、j、c的地址。本實例定義了3個指針變量i、j、c,計算“c=i+j”,計算后使用“&*”分別輸出i、j、c的地址值,具體代碼如下:#include<stdio.h>intmain(){longi,j,c;long*p,*q,*n;/*定義指針變量*/printf("pleaseinputthenumbers:\n");scanf("%ld,ld",&i,&j);c=i+j;p=&i;/*將地址賦給指針變量*/q=&j;n=&c;printf("%ld\n",&*p);/*輸出變量i的地址*/printf("%ld\n",&*q);/*輸出變量j的地址*/printf("%ld\n",&*n);/*輸出變量c的地址*/return0;}6.1指針的相關概念拓展訓練一:某工程隊修一條公路,第一天修600米,第二天修全長的20%,第三天修全長的25%,這三天共修全長的75%,求這條公路全長為多少米?編寫程序計算并輸出此公路總長變量的內存地址。6.1指針的相關概念三、指針的自增自減運算指針的自增自減運算不同于普通變量的自增自減運算,也就是說并非簡單地加1或減1。例如:基本整型變量i在內存中占4個字符,假設指針p是指向變量i的地址,那么p++不是簡單地在地址上加1,而是指向下一個存放基本整型變量的地址。6.1指針的相關概念實例6-1-4:指針自增。本實例定義一個指針變量,將這個指針進行自增運算,利用printf函數輸出該指針變量的值,具體代碼如下:

#include<stdio.h>voidmain(){inti;int*p;printf("pleaseinputthenumber:\n");scanf("%d",&i);p=&i;/*將變量i的地址賦給指針變量*/printf("theresult1is:%d\n",p);p++;/*地址加1,這里的1并不代表一個字節(jié)*/printf("theresult2is:%d\n",p);}6.1指針的相關概念指針是按照它所指向的數據類型的直接長度進行增或減??梢詫嵗?-1-4用下圖表示6.1指針的相關概念拓展訓練二:

利用指針統(tǒng)計“IdeeplyloveChina.”的單詞個數。6.2指針與一維數組一、指針與一維數組的關系數組是最基本的構造類型,是相同類型數據的有序集合。數組中的元素按順序存放在地址連續(xù)的內存單元中,每一個數組元素都有各自的地址,數組名是數組首元素的地址。對數組元素的訪問,可以使用下標,也可以使用指針變量,移動指針可以指向數組中的任意一個元素。6.2指針與一維數組實例6-2-1:訪問數組元素的四種等價方式。#include<stdio.h>intmain(){inti,a[5]={1,2,3,4,5},*p=&a[0];printf("\na[i]:");for(i=0;i<5;i++)/*常規(guī)下標法訪問數組元素*/printf("%3d",a[i]);printf("\n*(a+i):");for(i=0;i<5;i++)/*數組名作為指針訪問數組元素*/printf("%3d",*(a+i));printf("\np[i]:");for(i=0;i<5;i++)/*指針變量下標法訪問數組元素*/printf("%3d",p[i]);printf("\n*(p+i):");for(i=0;i<5;i++)/*使用指針變量訪問數組元素*/printf("%3d",*(p+i));return0;}6.2指針與一維數組二、一維數組與指針的定義當定義一個一維數組時,系統(tǒng)會在內存中為該數組分配一個存儲空間,其數組的名稱就是數組在內存中的首地址,若再定義一個指針變量,并將數組的首地址傳遞給指針變量,則該指針就指向了這個一維數組。例如:int*p,a[10];p=a;這里a是數組名,也就是數組的首地址,將它賦給指針變量p,也就是將數組a的首地址賦給p。也可以寫成如下形式:int*p,a[10];p=&a[0];上面的語句是將數組a中的首個元素的地址賦給指針變量p,由于a[0]的地址就是數組的首地址,因此兩條賦值操作效果完全相同。6.2指針與一維數組實例6-2-2:輸出數組中的元素。本實例是使用指針變量輸出數組中的每個元素,具體代碼如下:

#include<stdio.h>voidmain(){int*p,*q,a[5],b[5],i;p=&a[0];

q=b;printf("pleaseinputarraya:\n");for(i=0;i<5;i++)scanf("%d",&a[i]);/*為數組a中的元素賦初值*/printf("pleaseinputarrayb:\n");for(i=0;i<5;i++)scanf("%d",&b[i]);/*為數組b中的元素賦初值*/printf("arrayais:\n");for(i=0;i<5;i++)printf("%5d",*(p+i));/*輸出數組a中的元素*/printf("\n");printf("arraybis:\n");for(i=0;i<5;i++)printf("%5d",*(q+i));/*輸出數組b中的元素*/printf("\n");}6.2指針與一維數組說明:(1)本實例中第5行和第6行的語句為:05p=&a[0];06q=b;以上這兩種表示方法都是將數組首地址賦給指針變量。(2)p+n與a+n表示數組元素a[n]的地址,即&a[n]。對數組a來說,共有5個元素,n的取值為0~4,則數組元素的地址就可以表示為p+0~p+4或a+0~a+4。(3)表示數組中的元素用到了前面介紹的數組元素的地址,用*(p+n)和*(a+n)來表示數組中的各元素。6.2指針與一維數組實例6-2-2中第15行的語句為:

15printf("%5d",*(p+i));實例6-2-2中第19行語句為:

19printf("%5d",*(q+i));上述兩條語句分別表示輸出數組a和數組b中對應的元素。實例6-2-2中使用指針指向一維數組及通過指針引用數組元素的過程可以通過左圖和右圖來表示。6.2指針與一維數組在C語言中,可以用a+n表示數組元素的地址。*(a+n)表示數組元素,這樣就可以將實例6-2-2中的程序第13行到第20行代碼改成下列形式1:13printf("arrayais:\n");14for(i=0;i<5;i++)15printf("%5d",*(a+i));16printf("\n");17printf("arraybis:\n");18for(i=0;i<5;i++)19printf("%5d",*(b+i));20printf("\n");程序運行的結果與實例6-2-2的運行結果相同。6.2指針與一維數組表示指針的移動可以使用“++”和“--”兩個運算符,利用“++”運算符可將程序的第13行到第20行的代碼改寫成下列形式2:13printf("arrayais:\n");14for(i=0;i<5;i++)15printf("%5d",*p++);16printf("\n");17printf("arraybis:\n");18for(i=0;i<5;i++)19printf("%5d",*q++);20printf("\n");6.2指針與一維數組還可將實例6-2-2代碼再進一步改寫,運行結果仍相同,在上面修改后的基礎上修改實例6-2-2程序的第7行到第12行代碼,修改后的程序代碼如下列形式3:7printf("pleaseinputarraya:\n");8for(i=0;i<5;i++)9scanf("%d",p++);10printf("pleaseinputarrayb:\n");11for(i=0;i<5;i++)12scanf("%d",q++);

p=a;

q=b;6.2指針與一維數組將上述形式3中的程序與實例6-2-2程序對比,可以看出,如果在輸出數組元素時需要使用指針變量,則需加上如下兩條語句:p=a;q=b;這兩條語句的作用是將指針變量p和q重新指向數組a和數組b在內存中的起始位置。若沒有這兩條語句,而直接使用*p++的方法進行輸出,就會產生錯誤。拓展訓練三:使用指針尋找字符串“howareyou,andiamfine,doyouknow?”中“,”的位置。6.3指針與二維數組一、指針與二維數組的關系與一維數組相同,二維數組在內存中也是連續(xù)存儲的。設有定義inta[3][3],假設a[0][0]的地址為2000,數組中各元素的首地址下圖所示??梢詮纳蠄D中看出,a數組中的元素從地址2000開始按照行的順序連續(xù)存放在內存中。6.3指針與二維數組一、指針與二維數組的關系在C語言中,二維數組被看成一維數組的一維數組,二維數組的每一行都被看作是一個一維數組,其數組名分別為a[0]、a[1]和a[2],如下圖所示。6.3指針與二維數組二維數組名代表二維數組首元素的地址,由于二維數組的元素被看作為一維數組的一維數組,故數組a[3][3]可分解為3個一維數組,分別是a[0]、a[1]、a[2]。每一個一維數組又含有3個元素,如a[0]數組含有a[0][0]、a[0][1]、a[0][2]3個元素。數組及數組元素的地址表示如下:a是二維數組名,也是二維數組0行的首地址,等于2000。a[0]是第一個一維數組的數組名和首地址,因此也為2000。*(a+0)或*a是與a[0]等效的,它表示一維數組a[0]的0號元素的首地址,也為2000。&a[0][0]是二維數組a的0行0列元素的首地址,同樣是2000。因此a、a[0]、*(a+0)、*a、&a[0][0]都是相等的。同理a+i、a[i]、*(a+i)、&a[i][0]也都是相等的,此外&a[i]和a[i]也是相等的,因為在二維數組中不能把&a[i]理解為元素a[i]的地址,所以不存在元素a[i]。另外,a[0]也可以看成是a[0]+0,是一維數組a[0]的0號元素的首地址,而a[0]+1則是a[0]的1號元素首地址,由此得出a[i]+j是一維數組a[i]的j號元素首地址,它等于&a[i][j]。6.3指針與二維數組實例6-3-1:用二維數組名的方式訪問a[1][2]的常見方式的具體實現(xiàn)代碼如下:#include<stdio.h>intmain(){inta[3][3]={1,2,3,4,5,6,7,8,9};printf("a[1][2]=%d\n",a[1][2]);printf("*(a[1]+2)=%d\n",*(a[1]+2));printf("*(*(a+1)+2)=%d\n",*(*(a+1)+2));return0;}6.3指針與二維數組二、指向二維數組元素的指針二維數組的各個元素在內存中是連續(xù)存放的,存放方式與一維數組并無區(qū)別,可以將二維數組當做一維數組進行處理,指針變量指向二維數組某元素的格式如下:指針變量名=&二維數組[行下標][列下標]指針變量名=*二維數組名指針變量名=二維數組[行下標]當行下標和列下標均為0時,指針變量指向二維數組首元素的地址,引用該數組元素的方法是:

*指針變量6.3指針與二維數組實例6-3-2:將輸入的數以二維數組顯示。輸入15個整型數據,將這些數據以3行5列的二維數組的形式顯示。具體代碼如下:

#include<stdio.h>voidmain(){inta[3][5],*p,i,j;printf("pleaseinput:\n");for(i=0;i<3;i++)/*控制二維數組的行數*/for(j=0;j<5;j++)/*控制二維數組的列數*/scanf("%d",&a[i][j]);/*給二維數組元素賦初值*/p=&a[0][0];printf("thearrayis:\n");for(i=0;i<15;i++){printf("%5d",*(p+i));/*輸出二維數組中元素*/if((i+1)%5==0)printf("\n");}}6.3指針與二維數組拓展訓練四:某校班級有5×5個座位,輸出位置最好的一行座位號。(提示:第2行最受歡迎)6.3指針與二維數組三、指向二維數組的行指針變量由于二維數組的每一行都被視為一個一維數組,所以可以定義一個指針來指向每一行的一維數組,則行指針變量是指向一行數組元素的起始地址。聲明行指針變量的一般格式為:類型名(*指針變量名)[n]其中:類型名為指針變量名所指向數組的數據類型。n表示由一個二維數組分解為多個一維數組的長度,也就是所指向的二維數組的列數。格式中,()、*和[n]都不可省略。注意:行指針變量用于指向一行數組元素的起始地址,而非數組中的元素。定義行指針變量以后,只要將二維數組的首地址賦給行指針變量,則行指針變量就與二維數組建立了聯(lián)系,二維數組也就成為行指針變量指向的對象。此時,就可以用指針法訪問該二維數組的元素了。6.3指針與二維數組實例6-3-3:行指針變量訪問二維數組示例。

#include<stdio.h>#definerow3#definecol4intmain(){inta[row][col]={1,2,3,4,5,6,7,8,9,10,11,12};int(*p)[col]=a;/*定義行指針p,并指向數組a*/inti,j;for(i=0;i<row;i++)for(j=0;j<col;j++)printf("%3d",*(*(p+i)+j));/*可以在此處替換訪問a[i][j]的方式*/printf("\n");return0;}6.3指針與二維數組實例6-3-4:將停車場的第2行停車號輸出。某停車場有3×3個停車位,利用指針將第2行的停車號輸出,具體代碼如下:

#include<stdio.h>voidmain(){inta[3][3],i,j;printf("pleaseinput:\n");for(i=0;i<3;i++)/*控制二維數組的行數*/for(j=0;j<3;j++)/*控制二維數組的列數*/scanf("%d",*(a+i)+j);/*為二維數組中的元素賦值*/printf("thesecondlineis:\n");for(j=0;j<3;j++)printf("%5d",*(*(a+1)+j));/*輸出二維數組中的元素*/printf("\n");}6.3指針與二維數組實例6-3-5:求每個學生的總分與平均成績。有5名學生,每人有3門考試成績,計算每個學生的總分與平均成績。查找有1門及1門以上課程不及格的學生,并輸出這些學生的全部課程成績。#include<stdio.h>average(intstudent[5][6]){inti,j;printf("學號數學英語計算機總分平均分\n");for(i=0;i<5;i++){student[i][4]=student[i][1]+student[i][2]+student[i][3];/*總分*/student[i][5]=student[i][4]/3;/*平均分*/}for(i=0;i<5;i++){for(j=0;j<6;j++)printf("%-12d",student[i][j]);/*打印數組的元素*/printf("\n");}}

search(int(*p1)[6],intn)/*查找成績不及格學生函數*/{inti,j,flag;printf("\n有一門以上課程成績不及格的學生如下:\n");for(i=0;i<n;i++)/*n=5,對5個學生3門課程進行查找*/{flag=0;/*用flag標記,若成績<60,flag=1*/for(j=1;j<4;j++)if(*(*(p1+i)+j)<60)flag=1;/**(*(p1+i)+j就是score[i][j]*/if(flag==1)for(j=0;j<6;j++)/*用循環(huán)輸出該行6個數*/printf("%-12d",*(*(p1+i)+j));printf("\n");}}

intmain(){intscore[5][6]={{201101,78,93,82},{201102,67,83,72},{201103,55,83,62},{201104,65,59,70},{201105,80,78,90}};average(score);/*調用求平均分函數*/search(score,5);/*調用查找并輸出有成績不及格學生的函數*/return0;}6.4指針與字符串一、字符串與字符指針字符串操作是數據處理中常見的操作。在C語言中,可以使用字符指針來操作字符串,相比使用字符數組操作字符串,前者更加便利。在C語言中,字符串有兩種表示方式:字符數組或字符指針。字符數組的表示方式如下:

charstr[]="VisualC++2010";

puts(str);在這種表示方式中,str是數組名,也是指向字符串的指針。除了在定義字符數組時可以將字符串整體以賦值的形式存儲到數組中之外,在其他位置的代碼中使用“str="VisualC++2010";”語句都是錯誤的。6.4指針與字符串字符指針的表示方式如下:

char*str="hello";

puts(str);字符串“hello”在內存中以字符數組形式存儲,語句“char*str="hello";”的含義是指針str指向字符串“hello”的首字符,這里的“=”號表示將字符串“hello”的第一個字符的地址賦給str。6.4指針與字符串實例6-4-1:利用指針實現(xiàn)字符串復制。本實例中,在不使用strcpy函數的情況下,利用指針實現(xiàn)字符串復制功能,具體代碼如下:#include<stdio.h>

voidmain(){charstr1[]="youarebeautiful",str2[30],*p1,*p2;p1=str1;p2=str2;while(*p1!='\0'){*p2=*p1;p1++;/*指針移動*/p2++;}*p2='\0';/*在字符串的末尾加結束符*/printf("Nowthestring2is:\n");puts(str2);/*輸出字符串*/}從實例6-4-1代碼和運行結果可以看出:該實例中定義了兩個指向字符型數據的指針變量。首先使指針變量p1和p2分別指向字符串str1和字符串str2的第一個字符的地址。再將p1所指向的內容賦給p2所指向的元素,然后使p1和p2分別加1,即指向下一個元素,如此反復循環(huán),直到*p1的值為“\0”為止。6.4指針與字符串二、使用字符數組與字符指針處理字符串的區(qū)別雖然字符數組和字符指針都可以用于處理字符串,但二者之間還是有區(qū)別的。(1)賦值方法不同。如下面給字符指針賦值的方法是正確的:

char*str;

str="hello";其含義是字符指針指向字符串“hello”的首地址。而下面字符數組的賦值方法是錯誤的:

charstr[10];

str="hello";因為字符數組名str為一常量地址,不能被賦值。6.4指針與字符串(2)系統(tǒng)為其分配內存單元的方法不同。字符數組被定義以后,系統(tǒng)為其分配一段連續(xù)的內存單元,字符數組名為這段連續(xù)內存單元的首地址;而字符指針變量被定義以后,系統(tǒng)為其分配一個存放指針值(地址)的內存單元,其指向的對象并不明確,即下面的用法是錯誤的:

char*str;

scanf("%s",str);而下面的字符數組的用法是正確的:

charstr[10];

scanf("%s",str);但字符指針一旦指向某個具體對象,就可以用于輸入了,下面的用法是正確的:

chara[10],*str=a;

scanf("%s",str);6.4指針與字符串(3)修改(地址)的方法不同。字符指針的值(地址)可以被反復修改,也就是可以通過修改其值使其可以指向字符串中的任意位置;但字符數組名只能被引用,而不能被修改。例如:

chara[25]=chara[25]="clanguageprogramming!",*str=a;

str=a+2;

puts(str);

str=str+9;

puts(str);

printf("%c",*str);6.4指針與字符串三、字符串數組字符數組是一個一維數組,而字符串數組是一個將字符串作為數組元素的數組,可視其為一個二維字符數組。例如下面定義一個簡單的字符串數組,代碼如下:charcountry[5][20]={"China","Japan","Ruassia","Germany","Switzerland"}

字符串數組變量country被定義為含有5個字符串的數組,每個字符串的長度要小于20(這里要考慮字符串最后的'\0')。6.4指針與字符串

通過觀察上面定義的字符串數組可以發(fā)現(xiàn),像“China”和“Japan”這樣的字符串的長度僅為5,加上字符串結束符其長度也僅為6,而內存中卻要給它們分別分配一個20字節(jié)的空間,這樣就會造成資源浪費。為了解決這個問題,可以使用指針數組,使每個指針指向所需要的字符常量。這種方法雖然需要在數組中保存字符指針,而且也占用空間,但要遠少于字符串數組需要的空間。一維指針數組的定義形式如下:

類型名*數組名[數組長度]6.4指針與字符串實例6-4-2:輸出12個月的月份。本實例定義了一個指針數組,并且為這個指針數組賦初值,將12個月份輸出,具體代碼如下:

#include<stdio.h>voidmain(){inti;char*month[]={"January","February","March","April","May","June","July","August","September","October","November","December"};for(i=0;i<12;i++)printf("%s\n",month[i]);}6.4指針與字符串拓展訓練五:小學六年級英語期末考試,有一題是根據漢語填寫英語,漢語題目是語文、數學、英語、化學、生物、物理,填寫的英語分別為Chinese、Math、English、Chemistry、Biology、Physics,請用字符串數組輸出填寫的英文。6.5指針與函數一、指針作函數的參數指針作為函數的形參時,在形參說明時需要使用格式“類型名*指針名”。*號不能省略,而在函數定義的說明部分,*號的作用是類型說明符。實例6-5-1:指針作為形參的函數調用。#include<stdio.h>voidchangeA(int*);/*函數聲明*/intmain(){inta=10,*pa=&a;printf("調用前:pa=%x,a=%d\n",pa,a);changeA(pa);/*函數調用*/printf("調用后:pa=%x,a=%d\n",pa,a);return0;}

voidchangeA(int*p)/*函數定義*/{intb;*p=*p+*p;/*操作p所指向的變量*/p=&b;/*p指向b*/printf("在函數中:p=%x\n",p);}6.5指針與函數說明:在main函數中調用函數changeA時,將實參pa的值傳遞給形參p,p和pa都指向變量a,*p=*p+*p等價于a=a+a,結果是將a的值修改為20,然后p指向b。分析程序運行結果的第一行和第三行可以知道,在函數內通過p訪問a的操作改變了函數外變量a的值;分析程序運行結果的第二行和第三行可以知道,函數內對p的操作,與函數外的變量pa無關。運行結果中的pa和p的值在不同的C語言編譯器中可能會有所不同。第二行代碼“voidchangeA(int*)”的作用是函數聲明,其中*號不能省略,它的作用是說明changeA函數的形參為int類型的指針變量。指針作為函數參數,在被定義、聲明和調用時,數據類型都必須一致,如果不一致,編譯就會報錯。指針作為函數的形參時,函數中可以修改指針所指向的對象,利用這個特性,一個函數可以獲得多個返回值,只要在定義這個函數時使用多個指針變量作為形參即可。6.5指針與函數實例6-5-2:將輸入的3個數從大到小輸出。本實例使用嵌套函數實現(xiàn)相關功能,在定義的排序函數中嵌套了自定義交換函數,實現(xiàn)了數據按從大到小進行排序的功能,具體代碼如下:#include<stdio.h>voidswap(int*p1,int*p2)/*自定義交換函數*/{inttemp;temp=*p1;*p1=*p2;*p2=temp;}voidexchange(int*pt1,int*pt2,int*pt3)/*3個數由大到小排序*/{if(*pt1<*pt2)swap(pt1,pt2);/*調用swap函數*/if(*pt1<*pt3)swap(pt1,pt3);if(*pt2<*pt3)swap(pt2,pt3);}

voidmain(){inta,b,c,*q1,*q2,*q3;puts("Pleaseinputthreekeynumbersyouwanttorank:");scanf("%d,%d,%d",&a,&b,&c);q1=&a;/*將變量a地址賦給指針變量q1*/q2=&b;q3=&c;exchange(q1,q2,q3);/*調用exchange函數*/printf("\n%d,%d,%d\n",a,b,c);}6.5指針與函數從該實例代碼和運行結果可以看出:(1)程序創(chuàng)建了一個自定義函數swap,用于實現(xiàn)交換兩個變量的值;還創(chuàng)建了一個exchange函數,其作用是將3個數由大到小排序,在exchange函數中還調用了前面自定義的swap函數,這里的swap和exchange函數都是以指針變量作為形式參數的。(2)程序運行時,通過鍵盤輸入3個數并保存在變量a、b、c中,分別將a、b、c的地址賦予q1、q2、q3,調用exchange函數,將指針變量作為實際參數,將實際參數變量的值傳遞給形式參數變量,此時q1和pt1都指向變量a,q2和pt2都指向變量b,q3和pt3都指向變量c,在exchange函數中又調用了swap函數,當執(zhí)行swap(pt1,pt2)時,pt1也指向了變量a,pt2也指向了變量b。6.5指針與函數實例6-5-3:使用指針實現(xiàn)冒泡排序。#include<stdio.h>voidorder(int*p,intn){inti,t,j;for(i=0;i<n-1;i++)for(j=0;j<n-1-i;j++)if(*(p+j)>*(p+j+1))/*判斷相鄰兩個元素的大小*/{t=*(p+j);*(p+j)=*(p+j+1);*(p+j+1)=t;/*借助中間變量t進行值互換*/}printf("排序后的數組:");for(i=0;i<n;i++){if(i%5==0)/*以每行5個元素的形式輸出*/printf("\n");printf("%5d",*(p+i));/*輸出數組中排序后的元素*/}printf("\n");}voidmain(){inta[20],i,n;printf("請輸入數組元素的個數:\n");scanf("%d",&n);/*輸入數組元素的個數*/printf("請輸入各個元素:\n");for(i=0;i<n;i++)scanf("%d",a+i);/*給數組元素賦初值*/order(a,n);}/*調用order函數*6.5指針與函數拓展訓練六:大福源超市的員工重新擺放水果區(qū)的水果,店長要求按照水果名稱的升序進行擺放,水果名稱及其單價如下:蘋果(apple)3.50元、橘子(tangerine)2.50元、柚子(grapefriu)3.00元、橙子(orange)2.99元、菠蘿(pineapple)4.99元、葡萄(grape)5.00元。編寫程序,按照水果英文名稱的首字母升序將水果輸出。6.5指針與函數二、返回指針值的函數一個函數可以返回一個整型值、字符值、實型值等,也可以返回指針型的數據(指針值),即地址,返回指針值的函數簡稱為指針函數。定義指針函數的一般形式為:

類型名*函數名(參數列表)如:

int*max(intn)其中max是函數名,n是函數max的形參,函數名前面的*表示調用該函數后返回一個指向整型數據的指針(地址)。6.5指針與函數實例6-5-4:求長方形的周長。在本實例中輸入長方形的長、寬,計算長方形的周長。具體代碼如下:#include<stdio.h>intper(inta,intb);voidmain(){intiWidth,iLength,iResult;printf("請輸入長方形的長:\n");scanf("%d",&iLength);printf("請輸入長方形的寬:\n");scanf("%d",&iWidth);iResult=per(iWidth,iLength);printf("長方形的周長是:");printf("%d\n",iResult);}intper(inta,intb){

return(a+b)*2;}6.5指針與函數實例6-5-4中自定義了一個per函數,用來求長方形的面積。下面來看一下在實例6-5-4的基礎上如何使用返回值為指針的函數。#include<stdio.h>int*per(inta,intb);intperimeter;voidmain(){intiWidth,iLength;int*iresult;printf("請輸入長方形的長:\n");scanf("%d",&iLength);printf("請輸入長方形的寬:\n");scanf("%d",&iWidth);iresult=per(iWidth,iLength);printf("長方形的周長是:");printf("%d\n",*iresult);}int*per(inta,intb){int*p;p=&perimeter;perimeter=(a+b)*2;returnp;}程序中自定義了一個返回指針值的函數:

int*per(intx,inty)該函數將指向存放著所求長方形周長的變量的指針值予以返回。注意:這個程序本身并不需要寫成這種形式,因為對該問題使用這種方式編寫程序并不簡便。這樣寫只是為了講解如何使用返回值為指針的函數。6.5指針與函數實例6-5-5:求一維數組各元素中的最大值。#include<stdio.h>intmain(){int*p;

int*max(intn);/*聲明指針函數*/p=max(8);/*max函數返回最大值的地址*/

printf("最大值是:%d\n",*p);/*輸出最大值*/return0;}int*max(intn){/*定義指針函數*/staticinta[]={13,24,38,27,11,9,36,18};inti,m=0;for(i=1;i<n;i++)/*找最大值*/if(a[m]<a[i])m=i;/*m為最大值元素的下標*/return&a[m];/*返回最大值元素的地址*/}6.5指針與函數拓展訓練七:師徒二人合作生產一批零件,徒弟生產了9個零件,比師傅少生產21個,計算這批零件一共有多少個?將求得的零件個數利用指針返回。6.5指針與函數三、指向函數的指針函數和數組一樣,經系統(tǒng)編譯后,其目標代碼在內存中連續(xù)存放,其名字本身就是一個地址,是函數的入口地址。C語言中,指針可以指向變量,也可以指向函數。指向函數的指針的定義格式為:類型名(*指針變量名)(參數表);其中,類型名是函數返回值的類型,參數表是函數指針所指向函數的所有形參。例如:int(*pc)(int,int);其中,pc為指向函數的指針,所指函數有兩個整型參數,其返回值為整型,如果目標函數沒有返回值,則定義格式為void(*pc)()。6.5指針與函數三、指向函數的指針定義了指向函數的指針以后,必須將一個函數名(函數的入口地址)賦給函數指針,然后才能用函數指針間接調用該函數。如:int(*pc)(int,int);/*定義指向函數的指針pc,限定pc所指函數有兩個整型參數*/intave(inta,intb);/*聲明有兩個整型參數的函數*/pc=ave;/*指針pc指向函數ave*/指向函數的指針對函數的調用格式如下:(*指針變量名)(實參表);如:(*pc)(a,b);/*調用pc所指函數,a、b為實參*/6.5指針與函數實例6-5-6:指向函數的指針和指向函數的指針數組。#include<stdio.h>intmax(inta,intb)/*定義求最大值函數*/{returna>b?a:b;}intmin(inta,intb)/*定義求最小值函數*/{returna>b?b:a;}

intave(inta,intb)/*定義求平均值函數*/

{return(a+b)/2;}

voidmain()

{inta=10,b=15,c;int(*pc)(int,int);/*定義指向函數的指針pc,限定pc所指函數有兩個整型參數*/int(*p[2])();/*定義指向函數的指針數組p,不限定所指函數的參數*/pc=ave;/*pc指向ave函數*/p[0]=max;/*p[0]指向max函數*/p[1]=min;/*p[1]指向min函數*/c=(*pc)(a,b);/*調用pc所指函數,需要給出實參*/printf("平均值是:%d\n",c);

c=(*p[0])(a,b);/*調用p[0]所指函數,需要給出實參*/printf("最大值是:%d\n",c);

c=(*p[1])(a,b);/*調用p[1]所指函數,需要給出實參*/printf("最小值是:%d\n",c);}6.5指針與函數提示:使用指向函數的指針調用函數與直接調用函數在效果上是相同的,只是多了一種調用函數的手段。指向函數的指針可以作為函數的形參。例如,下面root函數聲明的第三個形參即為指向函數的指針:doubleroot(doublea,doubleb,double(*f)(double))這樣就可以在調用root函數時,把不同函數的入口地址傳遞給形參,從而在被調用的函數中使用實參函數。拓展訓練八:利用指向函數的指針編寫程序,求出兩個數x、y中的最大值。6.6指向指針的指針和指針數組一、指向指針的指針一個指針變量可以指向整型變量、實型變量和字符類型變量,當然也可以指向指針類型變量。當指針變量用于指向指針類型變量時,則稱之為指向指針的指針變量。這種雙重指針下圖所示。整型變量i的地址是&i,將其值傳遞給指針變量p1,則p1指向i;同時,將p1的地址&p1傳遞給p2,則p2指向p1。這里的p2就是前面講到的指向指針變量的指針變量,即指針的指針。6.6指向指針的指針和指針數組指向指針的指針變量定義如下:

類型標識符**指針變量名;例如:

int**p;其含義為定義一個指針變量p,它指向另一個指針變量,該指針變量又指向一個基本整型變量。由于指針運算符*是自右至左結合的,所以上述定義相當于:int*(*p);6.6指向指針的指針和指針數組實例6-6-1:輸出化學元素周期表中的前7個金屬元素。在本實例中,定義了一個指向指針的指針,利用這個指針將指針數組的元素輸出,具體代碼如下:#include<stdio.h>intmain(){inti;char

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論