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è),還剩39頁(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章指針地址和指針的概念

指向變量的指針變量

指針與數(shù)組字符串的指針和指向字符串的指針變量指針數(shù)組指向指針的指針函數(shù)指針返回指針的函數(shù)main()函數(shù)的返回指和參數(shù)8.1.地址和指針的概念內(nèi)存單元的編號(hào)也叫做內(nèi)存地址,通常把這個(gè)地址稱為指針。即變量的指針就是變量的地址。對(duì)于一個(gè)內(nèi)存單元來說,單元的地址即為指針,其中存放的數(shù)據(jù)是該內(nèi)存單元的內(nèi)容。內(nèi)存單元的地址和內(nèi)存單元的內(nèi)容是兩個(gè)不同的概念。指針變量是一個(gè)地址變量,當(dāng)一個(gè)指針變量中存放了一個(gè)地址時(shí),該指針變量就指向該地址的存儲(chǔ)空間。(a)變量的地址裝入指針變量中

(b)指針變量指向變量有了指針變量以后,對(duì)一般變量的訪問既可以通過變量名進(jìn)行,也可以通過指針變量進(jìn)行。通過變量名或其地址(如a或&a)訪問變量的方式叫直接訪問方式;通過指針變量(如p)訪問它指向的變量(如a)的方式叫間接訪問方式。8.2.1指向變量的指針變量的定義指針變量也是一個(gè)變量,所以和其他變量一樣必須先定義后使用。定義指向變量的指針變量的一般格式如下:類型標(biāo)識(shí)符*變量名;例如:int*p1,*p2;float*q;在指針變量定義中,指針變量名前的“*”號(hào)僅是一個(gè)符號(hào),并不是指針運(yùn)算符,表示定義的是指針變量;類型標(biāo)識(shí)符表示該指針變量所指向的變量的數(shù)據(jù)類型,并不是指針變量自身的數(shù)據(jù)類型,所有指針變量都是存放變量地址的。8.2指向變量的指針變量8.2.2指針運(yùn)算符2.取內(nèi)容運(yùn)算符“*”取內(nèi)容運(yùn)算符“*”是單目運(yùn)算符,其結(jié)合性為從右到左,功能是取指針變量所指向的存儲(chǔ)區(qū)域內(nèi)存放的值。取內(nèi)容運(yùn)算符“*”是優(yōu)先級(jí)最高的運(yùn)算符之一。1.取地址運(yùn)算符“&”取地址運(yùn)算符“&”是單目運(yùn)算符,其結(jié)合性為從右到左,功能是取變量的地址。取地址運(yùn)算符“&”是優(yōu)先級(jí)最高的運(yùn)算符之一?!纠?.1】指針變量的應(yīng)用。#include<stdio.h>voidmain(){inta=3,*p;intb=5,*q=&b;intc;printf("a=%d,b=%d\n",a,b);p=&a;*q=9;printf("a=%d,b=%d\n",a,b);printf("*p=%d,*&a=%d\n",*p,*&a);(*p)++;printf("(*p)++=%d\n",a);}程序運(yùn)行結(jié)果:a=3,b=5a=3,b=9*p=3,*&a=3(*p)++=4使用指針運(yùn)算符時(shí)應(yīng)注意以下幾點(diǎn):⑴指針“*”運(yùn)算符和指針定義中的指針標(biāo)識(shí)符“*”不是一回事。在指針變量定義中,“*”是類型標(biāo)識(shí)符,表示定義的變量是指針類型的變量。而表達(dá)式中出現(xiàn)的“*”則是一個(gè)指針運(yùn)算符,表示取指針變量所指向變量的值。⑵對(duì)于語(yǔ)句“*p=&a,(*p)++;”表示使指針變量p所指向的存儲(chǔ)單元的值自增,相當(dāng)于a++。*p兩邊的括號(hào)是必須的,如果沒有括號(hào),成為*p++,而"++"和"*"是優(yōu)先級(jí)相同的運(yùn)算符,按從右到左的結(jié)合方向結(jié)合等價(jià)于*(p++)。p=&x;x=*p;p=&*p;x=*&x;

/*表示取整型變量x的內(nèi)存地址,并賦值給指針變量p*//*表示取指針變量p所指向的變量的值,并賦值給整型變量x*//*按優(yōu)先級(jí)&*p等價(jià)&(*p),*p就是變量x,再執(zhí)行&x,即取變量x的地址,并將變量x的地址賦值給指針變量p。因此,&*p等價(jià)于&x*//*按優(yōu)先級(jí)*&x等價(jià)于*(&x),&x就是取變量x的地址,再執(zhí)行*運(yùn)算相當(dāng)于取變量x的值,并賦值給整型變量x。因此*&x等價(jià)于x*/【例8.2】按從大到小的順序輸出兩個(gè)整型變量的值。#include<stdio.h>voidmain(){inta=5,b=9;intp,*pa,*pb;printf("%d,%d\n",a,b);pa=&a;pb=&b;if(*pa<*pb){p=*pa;*pa=*pb;*pb=p;}printf("%d,%d\n",*pa,*pb);getch();}程序運(yùn)行結(jié)果:5,99,58.2.3指針變量的初始化指針變量初始化的一般格式如下:類型說明符*指針變量名=初始地址例如:intk,*p=&k;floatx,*s=&x;對(duì)于外部或靜態(tài)指針變量在聲明中若不帶初始化項(xiàng),指針變量被初始化為NULL,它的值為整數(shù)0。NULL由stdio.h定義為0,它也等同于‘\0’,意為空指針(定義一個(gè)指針變量后,沒有使其指向一個(gè)確定的地址,這個(gè)變量稱為空指針)。例如:#defineNULL0int*p=NULL;8.2.4指針變量的運(yùn)算指針變量的運(yùn)算是指指針變量所持有的地址為運(yùn)算對(duì)象進(jìn)行的運(yùn)算,所以指針變量的運(yùn)算實(shí)際上就是地址的運(yùn)算。1.單個(gè)指針變量的算術(shù)運(yùn)算單個(gè)指針變量的算術(shù)運(yùn)算,包括+、一、++、--運(yùn)算符。C語(yǔ)言的地址運(yùn)算規(guī)則規(guī)定:一個(gè)地址加上或減去一個(gè)整數(shù)n,其運(yùn)算結(jié)果仍然是一個(gè)地址,它是以運(yùn)算對(duì)象的地址為基點(diǎn)向后或向前偏移n*基類型數(shù)據(jù)所占字節(jié)數(shù)的大小地址。即其運(yùn)算結(jié)果應(yīng)該是該指針變量當(dāng)前指向位置的后方或前方第n*基類型數(shù)據(jù)所占字節(jié)數(shù)的大小地址。例如:inta,b,c,d,&p;p=&b;p++;

/*定義了4個(gè)整型變量,一個(gè)指針變量*//*指針變量p指向b*//*或p=p+1,通過++運(yùn)算,指針變量向后偏移一個(gè)整型變量所占的字節(jié)數(shù),假定本例中開辟的空間是連續(xù)的,則指向了下一個(gè)變量c*/2.兩個(gè)指針變量之間的算數(shù)運(yùn)算兩個(gè)指針變量之間的運(yùn)算只能在同一種指針類型中進(jìn)行,主要包括+、-運(yùn)算符。“-”運(yùn)算所得的差是兩個(gè)指針變量之間相差的元素個(gè)數(shù)。正數(shù)表示被減數(shù)指針變量指在減數(shù)指針變量的后面,負(fù)數(shù)表示被減數(shù)指針變量指在減數(shù)指針變量的前面。對(duì)于兩個(gè)指針變量之間的"+"運(yùn)算,是毫無意義的。floata,b,*p1,*p2,*p3;intn,c[10],*q1,*q2;p1=&a;p2=&b;q1=&c[1];q2=&c[7];n=q2-q1;p3=p1+p2;p3=q1;

/*定義了2個(gè)單精度的變量a,b,三個(gè)指針變量*//*定義了1個(gè)整型變量,1個(gè)整型數(shù)組,2個(gè)整型變量*//*p1和p2指向兩個(gè)不同變量a,b*//*q1和q2指向同一個(gè)數(shù)組的不同數(shù)組元素c[1]和c[7]*//*相差元素的個(gè)數(shù),為6個(gè)整型變量所占字節(jié)數(shù)的大小計(jì)6*4=24*//*毫無意義*//*不正確,指針的類型不同*/3.指針變量的關(guān)系運(yùn)算基于類型相同的兩個(gè)指針變量之間的關(guān)系運(yùn)算,表示它們指向的地址之間的關(guān)系。假如數(shù)據(jù)存放在一段連續(xù)的存儲(chǔ)空間內(nèi),那么指向后面的存儲(chǔ)單元的指針變量的值大于指向前面存儲(chǔ)單元的指針變量的值。指向同一存儲(chǔ)單元的兩個(gè)指針變量的值相等。兩個(gè)指針之間可以進(jìn)行大于、大于等于、小于、小于等于、等于、不等于(>,>=,<,<=,==,!=)的比較運(yùn)算。在程序中,判斷空指針變量可以與整數(shù)比較。設(shè)p為指針變量,若有p==0成立,表示p為空指針,它不指向任何變量;若p!=0成立,表明p不是空指針?!纠?.3】分析下面程序的運(yùn)行結(jié)果。#include"stdio.h"#include"conio.h"voidmain(){inta=3,*p1;charch='A',*p2;floatx,y,*p3,*p4;p1=&a;p2=&ch;p3=&x;p4=p3+1;printf("%d,%c\n",a,ch);*p1=*p1+6;*p2=*p2+5;printf("%d,%c\n",a,ch);if(p3<p4)printf("OK!\n");elseprintf("NOT!\n");}運(yùn)行結(jié)果:3,A9,FOK!8.2.5指針變量作為函數(shù)參數(shù)如果形參作為指針變量,相對(duì)應(yīng)的實(shí)參必須是變量的指針。在這種情況下,數(shù)據(jù)傳送是地址的傳遞方式。

【例8.4】用函數(shù)調(diào)用的方法求一個(gè)整數(shù)m的平方。#include"stdio.h"voidsquare(int*pn){*pn=*pn**pn;}voidmain(){intn;printf("請(qǐng)輸入數(shù)據(jù)n:");scanf("%d",&n);printf("輸入的數(shù)據(jù)是:%d\n",n);square(&n);printf("輸入數(shù)的平方據(jù)是:%d\n",n);}程序的運(yùn)行結(jié)果:請(qǐng)輸入數(shù)據(jù)n:5↙輸入的數(shù)據(jù)是:5輸入數(shù)的平方據(jù)是:25用地址傳遞方式把變量n的地址傳遞給square()函數(shù)。函數(shù)square()用指向int類型的指針pn作為形參,在函數(shù)square()內(nèi)形參pn的值改變,同時(shí)也影響到了main()函數(shù)內(nèi)實(shí)參n的值的改變。#include"stdio.h"voidswap(int*q1,int*q2){intt;t=*q1;*q1=*q2;*q2=t;}voidmain(){inta,b,*pa=&a,*pb=&b;printf("請(qǐng)輸入數(shù)據(jù)a,b:");scanf("%d,%d",&a,&b);printf("比較前的兩個(gè)數(shù)是:%d,%d\n",a,b);if(a<b)swap(pa,pb);printf("比較后的兩個(gè)數(shù)是:%d,%d\n",*pa,*pb);}【例8.5】輸入兩個(gè)整數(shù)a,b,按從大到小的順序輸出。程序的運(yùn)行結(jié)果為:請(qǐng)輸入數(shù)據(jù)a,b:15,20比較前的兩個(gè)數(shù)是:15,20比較后的兩個(gè)數(shù)是:20,15【例8.6】輸入3個(gè)數(shù),輸出其中的最大整數(shù)和最小整數(shù)。#include"stdio.h"voidmax_min(int*p1,int*p2,int*p3){intmax,min;max=min=*p1;if(max<*p2)max=*p2;if(max<*p3)max=*p3;if(min>*p2)min=*p2;if(min>*p3)min=*p3;*p1=max;*p3=min;}voidmain(){inta,b,c;printf("請(qǐng)輸入a,b,c:");scanf("%d,%d,%d",&a,&b,&c);max_min(&a,&b,&c);printf("max=%d,min=%d\n",a,c);}程序運(yùn)行結(jié)果:請(qǐng)輸入a,b,c:2,5,9↙max=9,min=28.2.6程序?qū)嵗纠?.7】調(diào)用自定義的函數(shù)getint讀入一正整數(shù),并將其輸出。在輸入過程中,可用退格鍵,而空格或回車鍵表示結(jié)束輸入。#include"stdio.h"#include"conio.h"voidgetint(int*pintnum){inti,ch,finish=0;intbuf[10],count=10;*pintnum=0;while(!finish){ch=getch();switch(ch){case'':case'\r':finish=1;break;case'\b':if(count>0){printf("\b\b");--count;}break;default:if('0'<=ch&&ch<='9'){printf("%c",ch);buf[count]=ch;--count;}}}for(i=0;i<count;i++)*pintnum=10*(*pintnum)+(buf[i]-'0');}main(){intdata;getint(&data);printf("\n%d",data)}8.3指針與數(shù)組C語(yǔ)言規(guī)定數(shù)組名代表數(shù)組的起始地址,一個(gè)數(shù)組包含若干個(gè)元素,每個(gè)數(shù)組元素都在內(nèi)存中占用存儲(chǔ)空間,都有相應(yīng)的地址,指針變量可以指向數(shù)組或數(shù)組元素。8.3.1

一維數(shù)組和指針8.3指針與數(shù)組1.指針指向一維數(shù)組數(shù)組名代表數(shù)組的起始地址,也是數(shù)組第一個(gè)元素的地址。例如:inta[10];

a代表該數(shù)組的起始地址,是一個(gè)常量,也等價(jià)于&a[0]。a+i代表元素a[i]的地址,即a+i代表元素&a[i]。

對(duì)于數(shù)組元素的訪問,除了前面講述的下標(biāo)表示法之外(例如要訪問第5個(gè)元素,則用a[4]表示),也可以用地址法表示。例如,a[0]等于*a,a[i]等于*(a+i)。等價(jià)于:p=a;例如:inta[10];int*p=a;也可在定義指針變量的同時(shí)賦值。例如:inta[10],*p;p=&a[0];2.指向數(shù)組元素的指針變量的使用【例8.8】輸出數(shù)組a中的全部元素。方法一#include<stdio.h>voidmain(){inta[10]={3,6,1,8,2,7,0,4,2,5},i,*p;p=a;for(i=0;i<10;i++){printf("%3d",*p);p++;}}方法二#include<stdio.h>voidmain(){inta[10]={3,6,1,8,2,7,0,4,2,5},*p;for(p=a;p<a+10;p++){printf("%3d",*p);p++;}}

利用指向數(shù)組元素的指針變量,并對(duì)其進(jìn)行適當(dāng)?shù)募訙p運(yùn)算,即可處理整個(gè)數(shù)組。

例如:inta[10],*p;

則存取數(shù)組a中的第i個(gè)元素,使用指針可以表示如下:*(p+i);用地址法編寫的程序。#include<stdio.h>voidmain(){inta[10]={3,6,1,8,2,7,0,4,2,5},i;for(i=0;i<10;i++)printf("%3d",*(a+i));}對(duì)指針變量進(jìn)行的運(yùn)算大致可分為如下幾種:①指針運(yùn)算符*與++、--的優(yōu)先級(jí)相同,結(jié)合方向?yàn)閺挠业阶?。②p++使指針p指向下一個(gè)元素。p--同理。③p1-p2(pl和p2指向同一數(shù)組),得到pl和p2指向元素的下標(biāo)差值。④p+j(p指向數(shù)組的某一元素),得到在當(dāng)前地址基礎(chǔ)上向后偏移j個(gè)元素的地址。p-j同理。⑤*p++等價(jià)于先得到p所指向變量的值(即*p),然后使p=p+l,即使p指向下一個(gè)元素。*p--同理。⑥*++p等價(jià)于先執(zhí)行p=p+l,再取*p的值。*--p同理。⑦++(*p),先取*p的值加1存人p所指向地址,再取*p的值。--(*p)同理。對(duì)指針與數(shù)組元素的關(guān)系(設(shè)inta[10],*p=a;)歸納如下:①&a[j],a+j,p+j等價(jià),代表a數(shù)組第j個(gè)元素的地址。②a[j],*(a+j),p[j],*(p+j)等價(jià),代表a數(shù)組第j個(gè)元素的值。③*(p++)等價(jià)于a[j++]、*(p--)等價(jià)于a[j--]、*(++p)等價(jià)于a[++j]、*(--p)等價(jià)于a[--j]?!纠?.9】分析下面程序的運(yùn)行結(jié)果。#include<stdio.h>voidmain(){inta[]={5,15,25,35,45,55,65,75,85,95},m,*p;p=a;m=*p++;/*e1行*/printf("m=%d\n",m);m=*++p;/*e2行*/printf("m=%d\n",m);m=++(*p);/*e3行*/printf("m=%d\n",m);m=(*p)++;/*e4行*/printf("m=%d\n",m);}執(zhí)行el行時(shí),先取出p所指向的元素的值,即a[0]的值5,賦值給m后,再執(zhí)行++運(yùn)算,使p指向下一個(gè)元素a[1]。執(zhí)行e2行時(shí),p先執(zhí)行++運(yùn)算,使p指向下一個(gè)元素a[2],取出p所指向的元素的值,即a[2]的值25,再賦值給m。執(zhí)行e3行時(shí),先取出p所指向的元素的值,即a[2]的值25,再執(zhí)行++運(yùn)算將a[2]加1,即a[2]為26后賦值給m,p仍然指向a[2]。執(zhí)行e4行時(shí),先取出p所指向的元素的值,即a[2]的值26,賦值給m后,再執(zhí)行++運(yùn)算,使p所指向的元素的值a[2]加1,即a[2]為27,p仍然指向a[2]不變。使用指針變量是應(yīng)該注意以下幾問題:①不要使用沒有賦值的指針變量,使用指針之前一定要對(duì)它正確的賦值。②使用指針變量訪問數(shù)組元素時(shí),要隨時(shí)檢查指針的變化范圍和指針當(dāng)前的值,使指針的指向不能超過數(shù)組的上下界。【例8.10】輸入幾個(gè)學(xué)生的成績(jī)球平均成績(jī)。#include"stdio.h"voidmain(){inta[10],*p=a,j;for(j=0;j<10;j++)scanf("&d",p++);for(j=0;j<10;j++)printf("%3d",*p++);printf("\n");}#include"stdio.h"voidmain(){inta[10],*p=a,j;for(j=0;j<10;j++)scanf("&d",p++);p=a;for(j=0;j<10;j++)printf("%3d",*p++);printf("\n");}③無論傳遞數(shù)組的首地址的函數(shù)參數(shù)用數(shù)組名還是指針,其實(shí)質(zhì)都是指針,在函數(shù)被調(diào)用時(shí),該指針通過參數(shù)傳遞均指向數(shù)組。方法一:實(shí)參用指針變量,形參用數(shù)組名。#include"stdio.h"#defineN5floataver(floatp[])/*定義aver()函數(shù)用于計(jì)算平均成績(jī),形參用數(shù)組名*/{inti;floatav,s=0;for(i=0;i<N;i++)s+=p[i];/*利用下標(biāo)法取數(shù)組元素的值*/av=s/N;return(av);}voidmain(){floatscore[N],av,*p=score;inti;printf("請(qǐng)輸入5個(gè)學(xué)生的成績(jī)!");for(i=0;i<N;i++)scanf("&f",&score[i]);av=aver(p);/*調(diào)用aver()函數(shù)時(shí),實(shí)參用指針變量*/printf("這5個(gè)學(xué)生的平均成績(jī)是%5.2f",av);}方法二:實(shí)參用數(shù)組名,形參用指針變量。#include"stdio.h"#defineN5floataver(float*pa)/*定義aver()函數(shù)用于計(jì)算平均成績(jī),形參用指針變量*/{inti;floatav,s=0;for(i=0;i<N;i++)s+=*pa++;/*利用指針變量取數(shù)組元素的值*/av=s/N;return(av);}voidmain(){floatscore[N],av;inti;printf("請(qǐng)輸入5個(gè)學(xué)生的成績(jī)!");for(i=0;i<N;i++)scanf("&f",&score[i]);av=aver(score);/*調(diào)用aver()函數(shù)時(shí),實(shí)參用數(shù)組名*/printf("這5個(gè)學(xué)生的平均成績(jī)是%5.2f",av);}方法三:實(shí)參用指針變量,形參也用指針變量。#include"stdio.h"#defineN5floataver(float*pa)/*定義aver()函數(shù)用于計(jì)算平均成績(jī),形參用指針變量*/{inti;floatav,s=0;for(i=0;i<N;i++)s+=*pa++;/*利用指針變量取數(shù)組元素的值*/av=s/N;return(av);}voidmain(){floatscore[N],av,*p=score;inti;printf("!");for(i=0;i<N;i++)scanf("&f",&score[i]);av=aver(p);/*調(diào)用aver()函數(shù)時(shí),實(shí)參用指針變量*/printf("%5.2f",av);}【例8.11】輸入n個(gè)數(shù),對(duì)其中的正數(shù)統(tǒng)計(jì)個(gè)數(shù)并求和,程序最后輸出原始數(shù)據(jù)和統(tǒng)計(jì)結(jié)果。#defineN5voidmain(){inta[N],*p;intcount=0,sum=0;printf("%d!",N);for(p=a;p<a+N;p++)/*使指針指向下一個(gè)元素*/{scanf("%d",p);if(*p>0){sum+=*p;count++;}}p=a;/*使指針指向數(shù)組的首地址*/while(p<a+N)printf("%-3d",*p++);/*利用指針指向打印數(shù)組的元素*/printf("\n");printf("count=%d\n",count);printf("sum=%d\n",sum);}1.二維數(shù)組地址的表示方法8.3.2二維數(shù)組和指針例如:inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};2.二維數(shù)組的指針變量二維數(shù)組指針變量說明的一般形式為:類型標(biāo)識(shí)符(*指針變量名)[長(zhǎng)度];其中:“類型說明符”為所指向數(shù)組的數(shù)據(jù)類型?!?”表示其后的變量是指針類型?!伴L(zhǎng)度”表示二維數(shù)組分解為多個(gè)一維數(shù)組時(shí),一維數(shù)組的長(zhǎng)度,也就是二維數(shù)組的列數(shù)。應(yīng)注意“(*指針變量名)“兩邊的括號(hào)不可少,缺少括號(hào)則表示是指針數(shù)組,意義就完全不同了?!纠?.12】用指向數(shù)組元素的指針變量輸出數(shù)組元素的值,并統(tǒng)計(jì)其中的正數(shù)。

#include"stdio.h"voidmain(){inta[][4]={{1,-2,3,4},{11,-22,33,44},{-55,66,0,-89}};intcount=0,*p;for(p=a[0];p<a[0]+12;p++){if((p-a[0])%4==0)printf("\n");printf("%4d",*p);if(*p>0)count++;}printf("\ncount=%d\n",count);}程序運(yùn)行結(jié)果

1-23411-223344-55660-88count=7【例8.13】查看某個(gè)學(xué)生某一門課程的成績(jī)。#include"stdio.h"#defineN3/*N表示學(xué)生數(shù)*/#defineM4/*M表示課程數(shù)*/voidmain(){intscore[N][M]={{67,80,74,58},{77,80,84,90},{87,81,75,69}};inti,j;printf("請(qǐng)輸入待查學(xué)生的學(xué)號(hào)%d和課程號(hào)%d");scanf("%d,%d",&i,&j);printf("第%d個(gè)學(xué)生的第%d課程的成績(jī)是%d\n",i-1,j-1,*(*(score+i-1)+j-1));}程序的運(yùn)行結(jié)果:請(qǐng)輸入待查學(xué)生的學(xué)號(hào)和課程號(hào):2,1↙第2個(gè)學(xué)生的第1課程的成績(jī)是778.3.3程序?qū)嵗?include<stdio.h>voidsort(inta[],intn){inti,j,temp;for(i=0;i<n;i++){for(j=n-1;j>i;j--)if(a[j-1]>a[j]){temp=a[j-1];a[j-1]=a[j];a[j]=temp;}}}

voidprint(inta[],intn){inti;for(i=0;i<n;i++)printf("%d",a[i]);printf("\n");}main(){inti,n,a[100];scanf("%d",&n);for(i=0;i<n;i++)scanf("%d",&a[i]);sort(a,n);print(a,n);}【例8.14】用冒泡排序法對(duì)數(shù)組進(jìn)行排序。8.4字符串的指針和指向字符串的指針變量C語(yǔ)言中沒有專門針對(duì)字符串變量的運(yùn)算,對(duì)字符串的操作要通過字符數(shù)組和指針來完成。字符串在內(nèi)存中的起始地址稱為字符串的指針,可以定義一個(gè)字符指針變量指向一個(gè)字符串。8.4.1字符串的指針1.字符數(shù)組把字符串的各字符(包括結(jié)束標(biāo)志‘\0’)依次保存在字符數(shù)組中,利用下標(biāo)變量或數(shù)組名對(duì)數(shù)組進(jìn)行操作。輸出時(shí)用“%s”格式進(jìn)行整體輸出。2.字符指針也可以直接定義指向字符串的指針變量,利用該指針變量對(duì)字符串進(jìn)行操作。【例8.15】字符數(shù)組應(yīng)用舉例。#include"stdio.h"voidmain(){charstr[]="Cprogram.";printf("%s\n",str);}程序運(yùn)行結(jié)果:Cprogram.【例8.16】字符指針應(yīng)用舉例。#include"stdio.h"voidmain(){char*ps="Cprogram.";printf("%s\n",ps);}8.4字符串的指針和指向字符串的指針變量#include"stdio.h"voidmain(){charst[50],*ps;inti;printf("請(qǐng)輸入一個(gè)字符串:");ps=st;scanf("%s",ps);for(i=0;ps[i]!='\0';i++)if(ps[i]=='k')break;if(ps[i]=='\0')printf("thereisno'k'inthestring.\n");elseprintf("thereisa'k'inthestring.\n");}【例8.17】在字符串中查找有無某字符。

程序的運(yùn)行結(jié)果:請(qǐng)輸入一個(gè)字符串:efgkabc↙thereisno'k'inthestring.請(qǐng)輸入一個(gè)字符串:abcxyz↙thereisno'k'inthestring.在使用時(shí)應(yīng)注意以下幾個(gè)問題:①字符串指針變量本身是一個(gè)變量,用于存放字符串的首地址。而字符串本身是存放在以該首地址為首的一塊連續(xù)的內(nèi)存空間中,并以'\0'作為字符串的結(jié)束標(biāo)志。字符數(shù)組是由若干個(gè)數(shù)組元素組成的,它可用來存放整個(gè)字符串。②對(duì)字符數(shù)組作初始化賦值,必須采用外部類型或靜態(tài)類型,而對(duì)字符串指針變量則無此限制。staticcharst[]={"CLanguage"};char*ps="CLanguage";③對(duì)字符串指針方式char*ps=“CLanguage”;可以寫為:char*ps;*ps="CLanguage";而對(duì)數(shù)組方式:staticcharst[]={"CLanguage"};不能寫成:staticcharst[20];或st[]={"CLanguage"};【例8.18】對(duì)字符數(shù)據(jù)使用冒泡排序法進(jìn)行排序,用字符數(shù)組和字符指針實(shí)現(xiàn)。#include<stdio.h>#include<string.h>voidmain(){inti,j,n;chart;staticchars[50];char*item=s;/*定義字符指針item,并把字符數(shù)組的首地址賦給item*/printf("請(qǐng)輸入一個(gè)字符串:");gets(item);n=strlen(s);/*求字符串的長(zhǎng)度*/for(i=1;i<n;i++)for(j=n-1;j>=i;j--){if(item[j-1]>item[j]){t=item[j-1];item[j-1]=item[j];item[j]=t;}}item=s;/*指針復(fù)位*/printf("\n排序后的字符串為:%S",item);}運(yùn)行結(jié)果:請(qǐng)輸入一個(gè)字符串:Cprogram排序后的字符串為:Cagmoprr8.4.2字符串作為函數(shù)參數(shù)將一個(gè)字符串從一個(gè)函數(shù)傳遞到另一個(gè)函數(shù),一方面可以用字符數(shù)組名做參數(shù),另一方面可以用指向字符串的指針變量做參數(shù),這樣,在被調(diào)函數(shù)中若改變了字符串的內(nèi)容,則主調(diào)函數(shù)中相應(yīng)的字符串的內(nèi)容也隨之改變?!纠?.19】編寫程序,把一個(gè)字符串的內(nèi)容復(fù)制到另一個(gè)宇符串中,要求不能使用strcpy()函數(shù)。#include<stdio.h>voidcpystr(char*ps,char*pd)/*形參pss指向源字符串,而pds指向目標(biāo)字符串*/{while((*pd=*ps)!='\0')/*將ps指向的字符串賦值到pd指向的存儲(chǔ)單元中并判斷是否結(jié)束*/{pd++;/*pd值加1,指向下一個(gè)字符*/ps++;/*ps值加1,指向下一個(gè)字符*/}}voidmain(){char*pa="CHINA",b[10],*pb;pb=b;cpystr(pa,pb);/*以指針變量pa、pb為實(shí)參,調(diào)用cpystr()函數(shù)*/printf("stringa=%s\nstringb=%s\n",pa,pb);}程序的運(yùn)行結(jié)果:

stringa=CHINAstringb=CHINA【例7.20】編寫程序,將輸入字符串中的大寫字母轉(zhuǎn)換為小寫字母。#include<stdio.h>#include<string.h>voidchan(char*p){inti,n;n=strlen(p);for(i=0;i<=n;i++)if(*(p+i)>64&&*(p+i)<92)*(p+i)=*(p+i)+32;}voidmain(){charstr[]="AbcDeF";puts(str);chan(str);puts(str);}程序的運(yùn)行結(jié)果:AbcDeFabcdef8.5指針數(shù)組

指針數(shù)組是一個(gè)數(shù)組,該數(shù)組是指針變量的集合,即它的每一個(gè)元素都是一個(gè)指針變量,這些指針變量具有相同的數(shù)據(jù)類型。指針數(shù)組的定義格式為:類型標(biāo)識(shí)*指針數(shù)組名[數(shù)組長(zhǎng)度];例如:int*a[10];

對(duì)指向字符串的指針數(shù)組在說明賦初值時(shí),是把存放字符串的首地址賦給指針數(shù)組的對(duì)應(yīng)元素。例如:char*a[5]={"BASIC","FORTRAN","FOXBASE","PASCAL","COBOL"};定義了a是指針數(shù)組,它有5個(gè)元素分別存放了字符串"BASIC","FORTRAN","FOXBASE","PASCAL","COBOL"的起始地址?!纠?.21】利用指針數(shù)組輸出另一個(gè)一維數(shù)組中的各元素#include<stdio.h>voidmain(){inti;inta[5]={2,4,6,8,10};int*p[5];for(i=0;i<5;i++)p[i]=a+i;for(i=0;i<5;i++)printf("%d",*p[i]);}程序的運(yùn)行結(jié)果:246810【例8.22】用0~6分別代表星期日至星期六,當(dāng)輸人其中的任意一個(gè)數(shù)字時(shí),請(qǐng)輸出對(duì)應(yīng)的星期名。#include<stdio.h>voidmain(){char*weekname[7]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};intweek;printf("請(qǐng)輸入0~6的數(shù)字:");scanf("%d",&week);if(week>=0&&week<7)printf("weekNO:%d-->%s",week,weekname[week]);elseprintf("inputerror!!\n");}程序運(yùn)行結(jié)果:請(qǐng)輸入0~6的數(shù)字:5↙weekNO:5-->Friday8.6指向指針的指針程序運(yùn)行結(jié)果:x=10

指向指針的指針變量中存放的是另一個(gè)指針變量的地址,則稱這個(gè)指針變量為指向指針的指針變量。指向指針的指針變量的一般格式為:類型標(biāo)識(shí)符**變量名;例如:int**pp;

表示pp是一個(gè)指針變量,它指向另一個(gè)指針變量,而這個(gè)指針變量指向一個(gè)整型量?!纠?.23】指向指針的指針演示。#include<stdio.h>voidmain(){intx,*p,**pp;x=10;p=&x;pp=&p;printf("x=%d\n",**pp);}【例8.24】通過指針變量輸出指針數(shù)組中數(shù)組元素的地址和數(shù)組元素所指向的數(shù)組。

#include<stdio.h>voidmain(){char*p[4]={"BASIC","DBASE","C","FORTRAN"};char**q;inti;for(i=0;i<4;i++){q=p+i;printf("%o",*q);printf("%s\n",*q);}}程序運(yùn)行結(jié)果:634BASIC642DBASE640C650FORTRAN8.6.2指向指針的指針的應(yīng)用現(xiàn)有5個(gè)國(guó)家的國(guó)名:"CHINA","AMERICA","AUSTRALIA","FRANCE","GERMAN",現(xiàn)要對(duì)這些國(guó)名按字母順序排列后輸出。思考:排序后排序前GERMAN\0GERMAN\0FRANCE\0FRANCE\0CHIAN\0AUSTRALIA\0AUSTRALIA\0AMERICA\0AMERICA\0nameCHINA\0name二維字符數(shù)組來存放字符串每個(gè)字符串不論其實(shí)際長(zhǎng)度是多少均需占據(jù)10個(gè)字節(jié),存儲(chǔ)空間占據(jù)較多,在排序時(shí)字符串的存儲(chǔ)位置作了交換,因此程序執(zhí)行效率較低。

把所有的字符串存放在一個(gè)數(shù)組中,把這些字符數(shù)組的首地址放在一個(gè)指針數(shù)組中,當(dāng)需要交換兩個(gè)字符串時(shí),只需要交換指針數(shù)組相應(yīng)兩元素的內(nèi)容(地址)即可,而不必交換字符串本身,【例8.25】用指針數(shù)組處理字符串。voidsort(char*name[],intn){char*temp;inti,j;for(i=0;i<n-1;i++)for(j=n-1;j>i;j--)if(strcmp(name[j-1],name[j])>0){temp=name[j-1];name[j-1]=name[j];name[j]=temp;}}voidprint(char*name[],intn){inti,j;for(i=0;i<n;i++)printf("%s\n",name[i]);}main(){char*progname[]={"CHINA","AMERICA","AUSTRALIA","FRANCE","GERMAN"};sort(progname,5);print(progname,5);}指針可以指向一個(gè)變量,同樣也可以指向一個(gè)函數(shù)。一個(gè)函數(shù)在編譯時(shí),其代碼在內(nèi)存中占用一段連續(xù)的內(nèi)存單元,這片連續(xù)的內(nèi)存單元有一個(gè)人口地址,這個(gè)地址是執(zhí)行該函數(shù)的起始地址,也稱為該函數(shù)的指針??梢杂靡粋€(gè)指針變量指向一個(gè)函數(shù),然后通過該指針變量調(diào)用此函數(shù)。8.7.1函數(shù)的指針和指向函數(shù)的指針變量8.7函數(shù)的指針

一個(gè)函數(shù)在編譯時(shí)被分配給一個(gè)入口地址,這個(gè)函數(shù)的入口地址就是函數(shù)的指針。C語(yǔ)言規(guī)定函數(shù)名代表函數(shù)的入口地址。

在C語(yǔ)言中規(guī)定,一個(gè)函數(shù)總是占用一段連續(xù)的內(nèi)存區(qū),而函數(shù)名就是該函數(shù)所占內(nèi)存區(qū)的首地址。

可以把函數(shù)的這個(gè)首地址(或稱入口地址)賦予一個(gè)指針變量,使該指針變量指向該函數(shù),然后通過指針變量就可以找到并調(diào)用這個(gè)函數(shù)。把這種指向函數(shù)的指針變量稱為指向函數(shù)的指針變量。使用指向函數(shù)的指針變量有以下3個(gè)步驟:⑴定義指向函數(shù)的指針變量類型說明符(*指針變量)();例如:int(*pf)();

表示pf是一個(gè)指向函數(shù)入口的指針變量,該函數(shù)的返回值(函數(shù)值)是整型。⑵將定義后的指針變量指向函數(shù)例如:

int(*p)();…p=fun;…intfun(intx,inty){return(x+y);}⑶用指向函數(shù)的指針變量調(diào)用函數(shù)調(diào)用函數(shù)的格式為:(*指針變量)(實(shí)參表)在上述程序段中,通過指向函數(shù)的指針變量fun()函數(shù)的格式為“s=(*p)(a,b);”【例8.26】演示函數(shù)指針的使用方法。#include<stdio.h>intmax(inta,intb)/*定義max()函數(shù)用于求兩個(gè)數(shù)的較大數(shù)*/{if(a>b)return(a);elsereturn(b);}voidmain(){int(*pmax)(int,int);intx,y,z;pmax=max;printf("請(qǐng)輸入兩個(gè)數(shù):");scanf("%d,%d",&x,&y);z=(*pmax)(x,y);/*通過函數(shù)指針調(diào)用max()*/printf("max=%d\n",z);}程序的運(yùn)行結(jié)果:請(qǐng)輸入兩個(gè)數(shù):15,30↙max=30指向函數(shù)的指針變量的性質(zhì)與普通指針變量相同,唯一的區(qū)別是:普通指針變量指向的是內(nèi)存的數(shù)據(jù)存儲(chǔ)區(qū);而指向函數(shù)的指針變量指向的是內(nèi)存的程序代碼區(qū)。8.7.2函數(shù)的指針作為函數(shù)參數(shù)

當(dāng)函數(shù)在兩個(gè)函數(shù)之間傳遞時(shí),調(diào)用函數(shù)的實(shí)參應(yīng)該是被調(diào)傳遞函數(shù)的函數(shù)名,而被調(diào)函數(shù)的形參應(yīng)該是接收函數(shù)地址的指向函數(shù)的指針變量?!纠?.27】任意輸入兩個(gè)整數(shù),求它們的和、差。#include<stdio.h>intadd(intx,inty)/*定義add()函數(shù)用于計(jì)算兩個(gè)數(shù)的和*/{return(x+y);}intsub(intx,inty)/*定義sub()函數(shù)用于計(jì)算兩個(gè)數(shù)的差*/{return(x-y);}intfun(int(*p)(int,int),intx,inty)/*定義fun()函數(shù)用于調(diào)用相應(yīng)的函數(shù)*/{intz;z=(*p)(x,y);return(z);}voidmain(){inta,b;printf("請(qǐng)輸入兩個(gè)數(shù):");scanf("%d,%d",&a,&b);printf("%d+%d=%d\n",a,b,fun(add,a,b));printf("%d-%d=%d\n",a,b,fun(sub,a,b));}程序的運(yùn)行結(jié)果:請(qǐng)輸入兩個(gè)數(shù):126↙12+6=1812-6=68.7.3函數(shù)指針的應(yīng)用【例8.28】設(shè)有一個(gè)函數(shù)general,調(diào)用它時(shí),因?yàn)閰?shù)的不同實(shí)現(xiàn)不同的功能,輸入a,b兩個(gè)數(shù),第一次調(diào)用general時(shí),找出a和b中大者,第二次調(diào)用general時(shí)找出其中小者,第三次調(diào)用general時(shí)求a,b之和。#include<stdio.h>intmax(intx,inty){return(x>y)?x:y;}intmin(intx,inty){return(x<y)?x:y;}intadd(intx,inty){returnx+y;}voidgeneral(intx,inty,int(*fun)()){intresult;result=(*fun)(x,y);printf("%d\n",result);}main(){inta,b;printf("Entera,andb:");scanf("%d%d",&a,&b);printf("max=");general(a,b,max);printf("min=");general(a,b,min);printf("sum=");general(a,b,add);}運(yùn)行結(jié)果如下:Enteraandb:-38↙max=8min=-3sum=5【例8.29】指向函數(shù)的指針數(shù)組的應(yīng)用。#include"stdio.h"voidfun1(int);voidfun2(int);voidfun3(int);voidmain(){void(*f[3])(int)={fun1,fun2,fun3};intchoice;printf("Enteranumberbetween0and2,3toend:");scanf("%d",&choice);while(choice>=0&&choice<3){(*f[choice])(choice);printf("Enteranumberbetween0and2,3toend:");scanf("%d",&choice);}printf("Youentered3toend\n");}voidfun1(inta){printf("Youentered%dsofun1wascalled\n\n",a);}voidfun2(intb){printf("Youentered%dsofun2wascalled\n\n",b);}voidfun3(intc){printf("Youentered%dsofun3wascalled\n\n",c);}運(yùn)行結(jié)果如下:Enteranumberbetween0and2,3toend:0Youentered0sofun1wascal

溫馨提示

  • 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)論