計算概論B-馬思偉 Lecture 17 數(shù)組 指針與函數(shù)_第1頁
計算概論B-馬思偉 Lecture 17 數(shù)組 指針與函數(shù)_第2頁
計算概論B-馬思偉 Lecture 17 數(shù)組 指針與函數(shù)_第3頁
計算概論B-馬思偉 Lecture 17 數(shù)組 指針與函數(shù)_第4頁
計算概論B-馬思偉 Lecture 17 數(shù)組 指針與函數(shù)_第5頁
已閱讀5頁,還剩54頁未讀, 繼續(xù)免費閱讀

付費下載

下載本文檔

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

文檔簡介

計算概論

(IntroductiontoComputing)

主講人:馬思偉北京大學數(shù)字媒體研究所/第十七講數(shù)組、指針與函數(shù)提綱復習—指針與數(shù)組、字符串數(shù)組、指針與函數(shù)傳值調用與傳地址調用返回指針值的函數(shù)動態(tài)數(shù)組的引入靜態(tài)數(shù)組—亦即一般數(shù)組的定義數(shù)據(jù)類型數(shù)組變量名[數(shù)組大小];inta[10];charc[10];……數(shù)組大小固定為常量,需要預知數(shù)組大小!如果數(shù)組大小不定怎么辦?動態(tài)數(shù)組!動態(tài)數(shù)組申請空間頭文件賦值訪問空間回收動態(tài)數(shù)組–申請空間用前面講過用如下方法可以定義一個數(shù)組:charname[20];//定義一個類型為char長度為20的數(shù)組。在申請動態(tài)數(shù)組之前,先定義指向動態(tài)數(shù)組的指針。例如:char*name;然后,用malloc()函數(shù)申請動態(tài)數(shù)組:

name=(char*)malloc(20);動態(tài)數(shù)組–頭文件使用前要在文件的開始包含<malloc.h>文件。例如:

#include<malloc.h> voidmain(){ double*pd; pd=(double*)malloc(sizeof(double)*50);

…… }動態(tài)數(shù)組–賦值

int*p; p=(int*)malloc(sizeof(int)*100);//一百個數(shù)組元素,每個元素類型為int *p=1;//將數(shù)組的第1個元素賦值為1 *(p+1)=2;//將數(shù)組的第2個元素賦值為2 *(p+2)=3;//將數(shù)組的第3個元素賦值為3123456789101000100410081012101610201024102810321036pP+1動態(tài)數(shù)組–賦值與靜態(tài)數(shù)組相同,動態(tài)數(shù)組的元素下標也是從0開始的。所以對上面pi所指的數(shù)組可以用如下的循環(huán)將全部元素賦初值為0:

intj; for(j=0;j<100;j++)*(pi+j)=0;動態(tài)數(shù)組–例在使用動態(tài)數(shù)組的元素時,可以把每個數(shù)組元素看作一個指針,例如:

char*pc;//定義字符指針pc pc=(char*)malloc(sizeof(char)*2);//兩個數(shù)組元素,每個元素類型為char *pc=‘a’;//將數(shù)組的第1個元素賦值為’a’ *(pc+1)=‘b’;//將數(shù)組的第2個元素賦值為’b’ charx,y;//定義字符型變量x和y x=*pc; //將pc中第一個元素的內容賦值給x;此時x的值為’a’ y=*(pc+1);//將pc中第二個元素的內容賦值給y;此時y的值為’b’動態(tài)數(shù)組–空間回收靜態(tài)數(shù)組是數(shù)組變量定義時分配空間的,它的空間在該變量失效時由系統(tǒng)自動回收。動態(tài)數(shù)組是用malloc()函數(shù)動態(tài)申請的,需要在程序中調用free()函數(shù)主動釋放。如:

char*pc;//定義字符指針pc pc=(int*)malloc(sizeof(char)*2);//兩個數(shù)組元素,每個元素類型為char

…… free(pc);動態(tài)數(shù)組–注意事項強制類型轉換malloc返回一個void*類型的地址,必須通過強制類型轉換,才能賦值給特定的指針變量,如

int*pint=(int*)malloc(….);使用sizeof()最好使用“sizeof(類型名)*動態(tài)數(shù)組長度”形式確定分配內存的大小,如

int*pint=(int*)malloc(sizeof(int)*….);分配的內存不再使用時一定要釋放free(pint);動態(tài)數(shù)組–注意事項分配失敗處理malloc分配內存不能分配時,返回一個NULL值,可以根據(jù)返回值判斷內存分配是否成功int*pint=(int*)malloc(1<<31);

if(pint==NULL)printf(“Cannotallocsomanymemory!”);else{printf(“Alotofmemoryareallocated!”);free(pint);}動態(tài)數(shù)組–注意事項正確釋放內存空間intints[20];int*pint=ints;free(pint);

pint=NULL;free(pint);pint=(int*)malloc(sizeof(int)*10);if(pint!=NULL){ free(pint);

free(pint);}動態(tài)數(shù)組示例字符串復制:申請空間存放字符串#include<stdio.h>#include<malloc.h>#include<string.h>intmain(){ charstr[12]=“Iamhappy”;char*pstr=(char*)malloc(20);strcpy(pstr,str);printf(“%s”,pstr);

free(pstr);return0;}動態(tài)數(shù)組示例字符串輸入指針變量指向數(shù)組元素,指針變量等同于數(shù)組變量指針變量指向動態(tài)分配內存空間,指針變量也相當于數(shù)組,可按數(shù)組方式訪問內存#include<stdio.h>#include<malloc.h>intmain(){intmaxInt,i,*pint;scanf(“%d”,&maxInt);pint=(int*)malloc(sizeof(int)*maxInt);for(i=0;i<maxInt;i++)scanf(“%d”,pint+i);for(i=0;i<maxInt;i++)printf(“%d”,pint[i]);free(pint);return0;}復習--數(shù)組與指針指向數(shù)組元素的指針例:

inta[10];//定義一個包含10個整型數(shù)據(jù)的數(shù)組

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

p=&a[0];//注意不是*p=&a[0]

p=&a[0]與p=a等價:“p=a”表示把a數(shù)組的首元素地址賦給指針變量p,數(shù)組名a不代表整個數(shù)組,不是把數(shù)組a各元素的值賦給p,也可在定義時寫作:

int*p=a;

printf(“%d”,*p);輸出顯示??如何用指針訪問數(shù)組中的其他元素?

p=&a[i];*p=….;12345678910a[0]a[9]&a[0]1000100410081012101610201024102810321036p復習--數(shù)組與指針通過指針引用數(shù)組元素地址偏移,取得相應元素的地址p+i和a+i就是a[i]的地址p+1=1004不是1001!p+1所代表的地址實際上是p+1*d,d表示一個數(shù)組元素所占的字節(jié)數(shù)累加地址,p++取地址(指針)內容,獲得相應的數(shù)組元素*p,*(p+i),*(a+i)表示p+i,a+i所指向的數(shù)組元素即a[i],[]可視為變址運算符,即按a+i計算地址,然后找出此地址單元的值指向數(shù)組的指針變量也可以帶下標,p[i]與*(p+i)等價

p[i]*(p+i)a[0]a[9]a[i]12345678910&a[0]1000100410081012101610201024102810321036p&a[1]p+1&a[i]p+iaa+1a+ip[0]p[1]p[i]復習--數(shù)組與指針通過指針引用數(shù)組元素方法1:下標法,即a[i]方法2:地址法,即*(a+i),相應于計算a+i*d地址方法3:指針法,*p,p[i],

*(p+i)voidmain(){……for(i=0;i<10;i++)printf(“%d“,a[i]);

….}voidmain(){……for(i=0;i<10;i++)printf(“%d“,*(a+i));

….}voidmain(){……

int*p;for(p=a;p<(a+10);p++)printf(“%d“,*p);

….}復習--數(shù)組與指針關于指針地址運算p++,指向下一元素地址,不是下一內存單元地址*p++的運算順序與*(p++)等價,是先*(p),然后p++,printf(“%d”,*p++);*(p++)與*(++p)不同,前者先取*p,然后p加1,后者p先加1,再取*pprintf(“%d”,*p++);printf(“%d”,*(++p));

輸出???++(*p)表示p所指向的元素值加1printf(“%d”,++(*p));如果p指向數(shù)組a中第i個元素,*(p++)與a[i++]等價,*(++p)與a[++i]等價其他*(p--),*(--p),(*p)--

12345678910a[0]a[9]pa[i]復習--數(shù)組與指針關于地址運算兩個指針變量相加無意義floatscores[10];float*pscore1=scores;float*pscore2=scores+1;pscore1+pscore2;錯!兩個指針變量相減是其間的元素數(shù)目(pscore2-pscore1)==1;同類型指針變量可比較大小(地址值的大小)(pscore2>pscore1);(pscore2<pscore1);pscore2==scores;復習--數(shù)組與指針二維數(shù)組val[0],val,val[0],val,&val[0][0]都表示二維數(shù)組的起始地址val[0][i]=*(&val[0][0]+i)復習--數(shù)組與指針指向多維數(shù)組元素的指針變量指針變量指向數(shù)組元素例:用指針變量輸出二維數(shù)組元素的值

#include<stdio.h>#defineNUMROWS3#defineNUMCOLS4voidmain(){intval[NUMROWS][NUMCOLS]={8,16,9,52,3,15,27,6,14,25,2,10};int*p;for(p=val[0];p<val[0]+12;p++){if((p-val[0])%4==0)printf(“\n”);printf(“%4d”,*p);}printf(“\n”);}復習--字符串與指針字符指針與字符串字符指針賦值

char*str=“Beijing”;//字符串常量編譯后即分配空間存儲printf(“%s”,str);

char*str;str=“Beijing”;//字符串常量編譯后即分配空間存儲printf(“%s”,str);

或char*str;chars[15]=“BeijingChina”;str=s;復習--字符串變量輸入字符串變量初始化定義時初始化chars[12]=“Iamhappy”;char*str=“Iamhappy”;使用scanf(),gets()輸入charname[12];char*str;scanf(“%s”,name);scanf(“%s”,str);

str=name;scanf(“%s”,str);gets(name);str=(char*)malloc(12);scanf(“%s”,str);字符串變量輸出使用printf(),puts()輸出printf(“%s”,s);printf(“%s”,str);puts(name);字符串變量輸出例#inlcude<stdio.h>intmain(){chars[12]=“Iamhappy”;char*str;str=s;*str=‘U’;printf(“%s\n”,str);str=s+5;printf(“%s\n”,str);return0;}字符串操作字符串復制使用指針操作#inlcude<stdio.h>#inlcude<stdio.h>intmain(){chars[12]=“Iamhappy”;chart[20];char*ps=s,*pt=t;for(;*ps!=‘\0’;ps++,pt++)*pt=*ps;*pt=‘\0’;printf(“%s\n%s”,s,t);return0;}IamhappyIamhappyst字符串操作用指針處理voidmain(){char*a=“IloveChina”;a=a+7;printf(“%s”,a)}字符串應用求字符串中大寫字母的個數(shù)#include<stdio.h>intmain(){

charstr[256],*ps;intcount;scanf(“%s”,str);for(ps=str;*ps!=‘\0’;ps++)if(*ps>=’A’&&*ps<=‘Z’)count++;printf(“%shas%duppercases\n“,ps,count);return0;}字符串應用比較兩個字符串的大小,輸入兩個字符串,輸出兩個字符串比較的結果#include<stdio.h>intmain(){ chars1[256],s2[256];char*ps1=s1,ps2=s2;intcmp;scanf(“%s”,str);for(;*ps1=*ps2&&*ps1!=‘\0’&&*p2!=‘\0’;ps1++,ps2++)cmp=(*ps1-*ps2);printf(“%scmp%sis%d\n“,ps1,ps2,cmp);return0;}復習--字符串處理函數(shù)strcat(

char*dst,char*src):連接字符串strcpy(char*dst,char*src):復制字符串strcmp(char*str1,char*str2):比較字符串strlen(char*str):求字符串長度strlwr(char*str):把字符串中字符都變小寫strupr(char*str):把字符串中字符都變大寫#inlcude<string.h>數(shù)組、指針與函數(shù)傳值調用與傳地址調用傳值/傳地址調用概念數(shù)組元素傳值調用數(shù)組名傳地址調用指針傳地址調用指針傳值調用指針與數(shù)組參數(shù)傳遞返回指針值的函數(shù)函數(shù)說明和函數(shù)定義intmultiple(intx,inty);

//函數(shù)說明voidmain(){ inta=0,b=0; scanf(“%d%d”,&a,&b); printf(“%d\n”,multiple(a,b));//函數(shù)調用}intmultiple(intx,inty){

//函數(shù)定義

returnx*y;}函數(shù)被調用之前必須先說明或定義形參和實參形參定義函數(shù)時函數(shù)名后面括號中的變量名實參調用函數(shù)時函數(shù)名后面括號中的參數(shù),可以是常量、變量、表達式 intmax(intx,inty);//x,

y為形參 voidmain()

{inta,b,c;scanf(“%d,%d”,&a,&b);c=max(a,b);//a,

b為實參}形參與實參在函數(shù)調用前不占內存,只在發(fā)生函數(shù)調用時才給形參分配內存單元 intmax(inta,intb);//a,

b為形參

voidmain()

{

inta,b,c;

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

c=max(a,b);//a,

b為實參

}intmax(inta,intb){

if

(a>b)

return

a;

else

return

b;}形參、實參a,

b同名,但它們是不同函數(shù)中的局部變量,在內存中分別存放于不同的內存單元形參/實參與參數(shù)傳遞通過函數(shù)調用傳遞實參,A程序可以向B程序傳遞某些數(shù)值,也可以向B程序傳遞內存地址傳值調用與傳地址調用傳值調用時,相當于給形參進行變量賦值實參的數(shù)據(jù)voidmain(){

inta=20,b=45;printf(“%d

%d”,

a,

b); if(a<b)swap(a,b);

printf(“%d

%d”,

a,

b);}voidswap(intx,inty){ inttmp; tmp=x; x=y; y=tmp;}仍輸出“2045!”a,b的值沒有交換!傳地址調用當形參/實參為指針或數(shù)組時,參數(shù)間傳遞的數(shù)據(jù)存放的內存單元地址信息被調用函數(shù)對形參的數(shù)據(jù)處理結果,在主調用函數(shù)即為實參的處理結果例:指針為形參,實參為變量地址voidswap(int*a,int*b){ inttmp=0; tmp=*a; *a=*b; *b=tmp;}voidmain(){ inta=0,b=0; a=20; b=45; if(a<b)swap(&a,&b); printf(“a=%db=%d”,a,b);}傳地址調用4520xy2045ab傳地址調用字符串連接函數(shù)strcat()參數(shù)dst,src均為字符指針主函數(shù)進行指針傳遞調用連接后的字符串保存在dst中,可以顯示輸出

char*strcat(char*dst,char*src){char*p=dst;while(*p)p++;while(*p++=*src++);returndst;}voidmain(){ char*s1=“Beijing”;char*s2=“China”; strcat(s1,s2);printf(“%s”,s1);}數(shù)組參數(shù)傳遞數(shù)組元素作為函數(shù)實參,與變量用法相同,為傳值調用例1.傳遞數(shù)組元素兩個數(shù)組a,b,各有10個元素,逐個元素進行比較,如果a中元素大于b中相應元素的數(shù)目多于b中元素大于a中相應元素的數(shù)目,則認為a數(shù)組大于b數(shù)組。給定a,b判斷二者間的關系voidmain(){ inta[10],b[10]; inti,m=0,n=0,k=0; for(i=0;i<10;i++) scanf(“%d%d”,&a[i],&b[i]); for(i=0;i<10;i++) { if(larger(a[i],b[i])==1)) n++; elseif(larger(a[i],b[i]==0)) m++; elsek++; } if(n>k)printf(“aislargerthanb”); elseif(n<k)printf(“bislargerthana”); elseprintf(“aandbisequal”);}intlarger(intx,inty){if(x>y)return1;elseif(x<y)return-1;elsereturn0;}數(shù)組參數(shù)傳遞數(shù)組名可以作為實參傳遞,傳遞的是數(shù)組首元素的地址,相應的形式參數(shù)應當為數(shù)組名或指針變量例,有一個一維數(shù)組,內放10個學生成績,求平均成績voidmain{ floataverage(floatarray[],intn); floatscore[10]; floataver; …..

aver=average(score,10); printf(“averagescoreis%f”,aver);}floataverage(floatarray[],intn){ …..}數(shù)組參數(shù)傳遞數(shù)組名作為參數(shù)傳遞應在主調用函數(shù)和被調用函數(shù)中分別定義數(shù)組實參數(shù)組與形參數(shù)組類型應一致(類型不一樣會如何?)形參數(shù)組的大小不起任何作用,可以不指定,也可以根據(jù)需要傳送一個數(shù)組大小,例 floataverage(floatarray[],intn);數(shù)組名作為實參傳遞傳遞的是數(shù)組首元素的地址,實參數(shù)組和形參數(shù)組共用同一段內存

數(shù)組參數(shù)傳遞intswap1(intx,inty){ inttmp=0; tmp=x; x=y; y=tmp;return0;}voidmain(){inta[2]={7,8};swap1(a[0],a[1]);printf(“%d%d”,a[0],a[1]);swap2(a);printf(“%d%d”,a[0],a[1]);……}理解傳地址調用函數(shù)swap1傳遞數(shù)組的元素數(shù)據(jù)函數(shù)swap2傳遞數(shù)組起始地址:形參、實參均為數(shù)組intswap2(inta[]){ inttmp=0; tmp=a[0]; a[0]=a[1]; a[1]=tmp;

return0;}傳地址調用的三種形式方法一:指針/指針(含對變量取地址傳遞)主調用函數(shù)的實參及被調用函數(shù)的形參都是指針方法二:數(shù)組/數(shù)組主調用函數(shù)的實參及被調用函數(shù)的形參都是數(shù)組方法三:數(shù)組/指針及指針/數(shù)組主調用函數(shù)的實參及被調用函數(shù)的形參為指針或數(shù)組傳地址調用方法一:指針/指針voidswap(int*a,int*b){ inttmp=0; tmp=*a; *a=*b; *b=tmp;}voidmain(){ inta=0,b=0; int

*p1=&a; int*p2=&b; *p1=20;*p2=45; if(a<b)swap(p1,p2); printf(“a=%db=%d”,a,b);}傳地址調用方法一:指針/指針(對變量取地址傳遞)voidswap(int*a,int*b){ inttmp=0; tmp=*a; *a=*b; *b=tmp;}voidmain(){ inta=0,b=0; a=20; b=45; if(a<b)swap(&a,&b); printf(“a=%db=%d”,a,b);}傳地址調用的三種形式方法一:指針/指針(含對變量取地址傳遞)主調用函數(shù)的實參及被調用函數(shù)的形參都是指針方法二:數(shù)組/數(shù)組主調用函數(shù)的實參及被調用函數(shù)的形參都是數(shù)組方法三:數(shù)組/指針及指針/數(shù)組主調用函數(shù)的實參及被調用函數(shù)的形參為指針或數(shù)組數(shù)組參數(shù)傳遞intswap1(intx,inty){ inttmp=0; tmp=x; x=y; y=tmp;return0;}voidmain(){

inta[2]={7,8};swap1(a[0],a[1]);printf(“%d%d”,a[0],a[1]);swap2(a);printf(“%d%d”,a[0],a[1]);……}intswap2(inta[]){ inttmp=0; tmp=a[0]; a[0]=a[1]; a[1]=tmp;

return0;}方法二:數(shù)組/數(shù)組主調用函數(shù)的實參及被調用函數(shù)的形參都是數(shù)組傳地址調用的三種形式方法一:指針/指針(含對變量取地址傳遞)主調用函數(shù)的實參及被調用函數(shù)的形參都是指針方法二:數(shù)組/數(shù)組主調用函數(shù)的實參及被調用函數(shù)的形參都是數(shù)組方法三:數(shù)組/指針及指針/數(shù)組主調用函數(shù)的實參及被調用函數(shù)的形參為指針或數(shù)組數(shù)組與指針數(shù)組與指針做函數(shù)參數(shù)傳遞傳地址調用形參類型實參類型數(shù)組名指針變量數(shù)組名√√指針變量√√voidf(intx[],intn){….

}voidmain{inta[10];

f(a,10)….}voidf(intx[],intn){….

}voidmain{inta[10],*p=a;

f(p,10)….}voidf(int*x,intn){…

}voidmain{inta[10];

f(a,10)….}voidf(int*x,intn){….

}voidmain{inta[10],*p=a;

f(p,10)….}傳地址調用要注意的問題

空間分配靜態(tài)數(shù)組voidmain(){

int

a[10]={0};

int*b;

outputarray(a,10);

outputarray(b,10);}voidoutputarray(intarray[],intn){ inti;for(i=0;i<n;i++)printf(“%d”,array[i]);}傳地址調用要注意的問題

空間分配動態(tài)數(shù)組,先分配空間voidmain(){

int

*a;

int*b;a=(int*)malloc(sizeof(int)*10);

outputarray(a,10);

outputarray(b,10);}voidoutputarray(intarray[],intn){ inti;for(i=0;i<n;i++)printf(“%d”,array[i]);}函數(shù)的返回值函數(shù)執(zhí)行完以后可以向調用它的程序返回一個值,表明函數(shù)運行的狀況。很多函數(shù)的功能就是對參數(shù)進行某種運算,之后通過函數(shù)返回值給出運算結果。函數(shù)的返回值可以有不同的類型,返回值類型在函數(shù)定義時說明。

返回指針值的函數(shù)返回指針值的函數(shù)定義方法類型名*函數(shù)名(參數(shù)列表);

例:int*a

(intx,inty);返回指針值的函數(shù)例1:用指針返回數(shù)據(jù)strchr()函數(shù):在一個字符串中查找指定字符,找到則輸出char*strchr(char*string,charc){while(*string!=c

溫馨提示

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

最新文檔

評論

0/150

提交評論