高級語言程序設計(CC++版) 課件 第7章 指針_第1頁
高級語言程序設計(CC++版) 課件 第7章 指針_第2頁
高級語言程序設計(CC++版) 課件 第7章 指針_第3頁
高級語言程序設計(CC++版) 課件 第7章 指針_第4頁
高級語言程序設計(CC++版) 課件 第7章 指針_第5頁
已閱讀5頁,還剩43頁未讀 繼續免費閱讀

下載本文檔

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

文檔簡介

第7章

指針目錄定義與引用指針指針與一維數組指針與字符串指針數組與多重數組指針與函數動態內存分配216:12什么是指針所謂指針,就是內存地址;所謂指針變量,也就是其值為內存地址的變量。不同類型的變量占用不同長度的存儲空間,而不同類型的指針變量占用相同長度的存儲單元。指針可賦予不同的地址,通過指針可以間接操作其指向的變量。在C/C++語言中,指針變量存儲的內容的是其所指向對象的首地址,指向的對象可以是變量、數組、函數等占據存儲空間的實體。316:121.定義與引用指針程序運行時,每個變量都被存放在從某個內存地址開始的若干字節中。所謂“指針”,也稱作“指針變量”,其存儲內容是它所指向對象的首地址。指針變量的定義方法與普通變量基本相同,唯一的區別是必須在變量前加上一個“*”,表示該變量為指針變量。定義指針變量的一般格式為:類型*指針變量名;例如:inta=1; //①:定義一個整型變量a,賦初值為1int*p; //②:定義一個整型指針變量pp=&a; //③:p指向整型變量a;

②③int*p=&a;*p=3; //④:將p所指向的變量賦值為3,即將a賦值為3返回416:12例7.1:用指針方法編寫一個程序,輸入3個整數,將它們按由小到大的順序輸出。

輸入:輸入以空格分隔的3個整數。

輸出:將三個整數按從小到大順序輸出。#include<iostream>usingnamespacestd;voidswap(int*pa,int*pb){ inttemp; temp=*pa; *pa=*pb; *pb=temp;}intmain(){ inta,b,c,temp;

cin>>a>>b>>c; if(a>b)swap(&a,&b); if(a>c)swap(&a,&c); if(b>c)swap(&b,&c); cout<<a<<“”<<b<<“”<<c; return0;}516:122.

指針與一維數組(2.1指針指向數組元素)一個數組的名字實際上就是一個指針,該指針指向這個數組存放的起始地址。如果定義如下數組:intarray[10];那么標識符“array”的類型就是int*,可以用array給一個int*類型的指針變量賦值。不過,數組名array代表數組的首地址,其值是編譯時已確定的常量,不允許對array賦值。返回616:12例7.2:編寫一個使用指針的函數,交換數組a和數組b中的對應元素。

輸入:輸入包括三行,第一行為一個正整數n,第二行為數組a的n個元素,第三行為數組b的n個元素。

輸出:將數組a和數組b中對應的n個元素交換后,輸出兩行,第一行為數組a的n個元素(以空格分隔),第二行為數組b的n個元素。#include<iostream>usingnamespacestd;constintN=10;voidexchange(int*a,int*b,intn){ inttmp; for(inti=0;i<n;i++){ tmp=a[i];a[i]=b[i];b[i]=tmp; }}intmain(){ intx[N],y[N]; intn; cin>>n;716:12例7.2:編寫一個使用指針的函數,交換數組a和數組b中的對應元素。

輸入:輸入包括三行,第一行為一個正整數n,第二行為數組a的n個元素,第三行為數組b的n個元素。

輸出:將數組a和數組b中對應的n個元素交換后,輸出兩行,第一行為數組a的n個元素(以空格分隔),第二行為數組b的n個元素。 for(inti=0;i<n;i++) cin>>x[i]; for(inti=0;i<n;i++) cin>>y[i]; exchange(x,y,n); for(inti=0;i<n;i++) cout<<x[i]<<“”; cout<<endl; for(inti=0;i<n;i++) cout<<y[i]<<“”; cout<<endl;}816:122.2指針的運算指針方式引用數組元素時,常使用指針的算術運算操作。指針可進行以下算術運算操作:(1)同類型的指針之間可以比較大??;(2)同類型的指針可以進行相減;(3)指針變量可以加減整型變量或常量;(4)指針變量可以自增、自減。如果p1、p2是兩個同類型“T*”的指針,那么當“地址p1<地址p2”時表達式“p1<p2”為真,反之為假。p1>p2、p1==p2含義類推。如果p1和p2是兩個同類型“T*”的指針,那么表達式“p2–p1”表示在地址p1和p2之間能夠存放多少個T類型的變量。即p2–p1=(地址p2-地址p1)/sizeof(T)。如果p是一個“T*”類型的指針,n是一個整型變量或常量,那么表達式“p+n”是一個類型為T*的指針,該指針指向的地址是:p+n*sizeof(T);“p-n”,“p++”,“p--”類推。916:12例7.3:編寫一個使用指針的程序,輸入一個字符串,找出其中的大寫字母,小寫字母,空格,數字,及其他字符的個數。

輸入:輸入一個字符串。

輸出:輸出該字符串中大寫字母,小寫字母,空格,數字,及其他字符的個數。#include<iostream>usingnamespacestd;intmain(){ inta=0,b=0,c=0,d=0,e=0; char*p,s[100]; cin.getline(s,100);

p=s; while(*p!=0){ if(*p>='A'&&*p<='Z')a++; elseif(*p>='a'&&*p<='z')b++; elseif(*p=='')c++; elseif(*p>='0'&&*p<='9')d++; elsee++; p++; } cout<<a<<""<<b<<""<<c<<""<<d<<""<<e; return0;}1016:122.3指針變量作為函數參數數組、動態分配的內存等均是系列數據的集合,無法將其通過一個基本數據類型參數全部傳入函數內部。此時可以將該系列數據的起始地址作為實參,將該實參傳遞給函數定義中的指針變量形參,然后在函數內部通過指針運算符與指針變量訪問該系列數據。對于整數、小數、字符等基本類型數據的操作有時也必須要借助指針,一個典型的例子就是交換兩個變量的值。該例使用指針變量作為函數形參,以接收發生函數調用時從函數外部傳入的地址實參,從而可在函數內部以指針方式間接訪問函數外部的數據,這些數據不會隨著函數調用的結束而被銷毀。1116:12

≡例7.4:編寫一個使用指針作為形參的函數,實現數組元素的逆置。

輸入:輸入兩行,第一行為一個正整數n,第二行為a數組的n個元素,以空格分隔。

輸出:將a數據元素逆置后輸出,元素間以空格分隔。#include<iostream>usingnamespacestd;constintN=10;voidinverse(int*x,intn);intmain(){ intn,a[N]; cin>>n; for(inti=0;i<n;i++)cin>>a[i]; inverse(a,n); for(inti=0;i<n;i++)cout<<a[i]<<""; return0;}voidinverse(int*x,intn){ int*p,*i,*j; intt; intm=(n-1)/2; i=x;j=x+n-1;p=x+m; for(;i<=p;i++,j--) t=*i,*i=*j,*j=t;}1216:123.指針與字符串字符串常量的類型是char*,字符數組名的類型當然也是char*。因此可以用一個字符串或一個字符數組名,給一個char*類型的指針變量賦值。返回1316:12#include<stdio.h>intmain(){ charstring[]="IloveChina!"; //定義字符數組sting printf("%s\n",string); //用%s格式聲明輸出string,可以輸出整個字符串

printf("%c\n",string[7]); //用%c格式輸出一個字符數組元素

return0;}#include<stdio.h>intmain(){ char*string="IloveChina!";

//定義字符指針變量string并初始化

printf("%s\n",string);

//輸出字符串

return0;}例7.5:編寫函數實現兩個字符串的比較。函數原型為:intstrcmp(char*p1,char*p2)

設置p1指向字符串s1,p2指向字符串s2。要求:當s1=s2時返回值為0;當s1不等于s2時返回它們兩者的第一個不同字符的ASCII碼差值(如”boy”與”bad”,第二個字母不同,’o’與’a’之差為79-65=14);如果s1>s2則輸出正值,如果s1<s2則輸出負值。#include<iostream>usingnamespacestd;intstrcmp(char*p1,char*p2);intmain(){ intm; chars1[100],s2[100],*p1,*p2; scanf(“%s”,str1); scanf(“%s”,str2); p1=&s1[0]; p2=&s2[0]; m=strcmp(p1,p2); cout<<m; return0;}intstrcmp(char*p1,char*p2){ inti=0; while(*(p1+i)==*(p2+i)) i++; if(*(p1+i)==0&&*(p2+i)==0)return0;

return*(p1+i)-*(p2+i);}1416:12例7.6:使用指針實現字符串復制函數voidstrcpy(char*s1,char*s2)。

輸入:輸入包括兩行,分別為字符串s1和s2。

輸出:將s1賦值為s2后,分兩行輸出s1和s2。#include<iostream>usingnamespacestd;voidstrcpy(char*s1,char*s2){ while(*s2!='\0'){ *s1=*s2; s1++; s2++; } *s1='\0';}intmain(){ chars1[100],s2[100]; cin.getline(s1,100); cin.getline(s2,100); strcpy(s1,s2); cout<<s1<<endl; cout<<s2<<endl; return0;}1516:12例7.7:字符串連接。用指針方式實現字符串連接函數char*StrCat(char*dest,char*src)。

輸入:輸入包括兩行,分別為字符串s1和s2。

輸出:把字符串s2復制到字符串s1后面(刪除s1原來末尾的“\0”),分兩行輸出s1和s2。#include<iostream>usingnamespacestd;char*StrCat(char*dest,char*src){

char*pdest=dest;while(*dest){dest++;}

while(*src){*dest=*src;dest++;src++;}*dest='\0';returnpdest;}

1616:12例7.7:字符串連接。用指針方式實現字符串連接函數char*StrCat(char*dest,char*src)。

輸入:輸入包括兩行,分別為字符串s1和s2。

輸出:把字符串s2復制到字符串s1后面(刪除s1原來末尾的“\0”),分兩行輸出s1和s2。

intmain(){chars1[200],s2[100];//增大s1的大小以容納連接后的字符串cin.getline(s1,100); cin.getline(s2,100);StrCat(s1,s2);cout<<s1<<endl;cout<<s2<<endl;return0;}1716:12例7.8:設計函數voidinsert(char*s1,char*s2,char*s,intn),用指針實現在字符串s1中的指定位置n處插入字符串s2得到字符串s。

輸入:輸入包括三行,前兩行分別為字符串s1和s2,第三行為一非負整數n。

輸出:s1在位置n處插入s2后的字符串s。#include<iostream>usingnamespacestd;voidinsert(char*s1,char*s2,char*s,intn){ intj=0; for(inti=0;i<n;i++)*s++=*s1++; while(*s2!='\0')*s++=*s2++; while(*s1!='\0')*s++=*s1++; *s='\0';}intmain(){ chars1[100],s2[100],s[200]; cin.getline(s1,100); cin.getline(s2,100); intn; cin>>n; insert(s1,s2,s,n); cout<<s<<endl; return0;}1816:12例7.9:每到月末,小明就會統計本月支出賬單,請編程幫助他完成任務。

輸入:第一行是整數n(n<100)。然后是n行的賬單信息,每一行由物品的名字name和對應的花費c組成,長度不超過200。中間會有一個或多個空格,而每一行的開頭和結尾沒有空格。0.0<c<1000.0。

輸出:輸出總的花費,小數點后保留一位數字。#include<iostream>usingnamespacestd;intmain(){ inti,n; doublef,sum=0; stringstr; char*p; cin>>n; getchar(); //吸收整數后面的回車 for(i=0;i<n;i++){ getline(cin,str); p=&str[str.find_last_of("")]; //從后向前查找空格 p++; //指向空格后的數字 sscanf(p,"%lf",&f); //將字符串p轉換為實數

//f=atof(p); sum=sum+f; } cout<<sum<<endl; return0;}19輸入樣例:3Apple2.3Buyclothesforgirlfriends260.5Gotocinema30輸出樣例:292.816:12doubleatof(char*p){ doublesum=0; while(*p!='\0'&&*p!='.'){ sum=sum*10+*p-'0'; p++; } if(*p=='.'){ p++; intnum=10; while(*p!='\0'){ sum=sum+(*p-'0')*1.0/num; num=num*10; p++; } } returnsum;}sscanf(p,“%lf”,&f); //從字符串p中進行格式化輸入sprintf(str,“%d”,n);

//把格式化的數據輸出到字符串str中。

2016:124.指針數組與多重數組(4.1指向指針的指針)若一個指針變量存放的是另一個指針變量的地址,則稱其為指向指針的指針變量。定義指針的指針的一般格式為:類型**指針變量名;例如:int**p; 語句“int**p;”定義了一個指針變量p,p的類型是“int**”。在此情況下,通常稱p為“指針的指針”,因為p指向的是類型為“int*”的指針。同理,“int***p;”…,無論中間多少個“*”都是合法的定義。注意,不論p是幾級指針變量,在devc++中均占用4個字節內存空間。返回2116:124.2指針數組一個數組的各個元素均為指針類型數據,則稱該數組為指針數組。也就是說,指針數組中的每一個元素都是指針變量。定義指針數組的一般格式為:類型*數組名[常量表達式];例如:char*s[10];因為運算符[]的優先級高于運算符*,所以上述定義也可寫成“char*(s[10]);”,即s先和[10]結合,形成s[10]形式,該形式為一個數組格式,共有10個元素;然后再和s前面的*結合,*表示指針類型,即每個數組元素均為一個指向字符數據的指針變量。2216:12例7.10:編寫程序,用指針數組在主函數中輸入n(n<10)個等長(長度<10)的字符串。用另一函數對它們排序,然后在主函數中輸出n個已排好序的字符串。

輸入:第一行為1個正整數n(n<10),然后是n行,每行一個字符串。

輸出:n行排序后的字符串。#include<iostream>#include<cstring>usingnamespacestd;voidsort(char*s[],intn){ char*temp; inti,j; for(i=0;i<n-1;i++) for(j=0;j<n-1-i;j++) if(strcmp(*(s+j),*(s+j+1))>0)temp=*(s+j),*(s+j)=*(s+j+1),*(s+j+1)=temp;}intmain(){ intn; cin>>n; charstr[10][10],*p[10]; for(inti=0;i<n;i++)p[i]=str[i]; //將第i個字符串的首地址賦給指針數組p的第i個元素 for(inti=0;i<n;i++)scanf("%s",p[i]); sort(p,n); for(inti=0;i<n;i++)printf("%s\n",p[i]); return0;}2316:124.3帶參數的main函數指針數組的一個重要應用是用作main函數的形參,此時main()函數中允許帶2個參數,一個為整型參數argc,另一個是指向字符類型的指針數組argv[]。定義帶參數的main函數頭的一般格式為:intmain(intargc,char*argv[])其中argc和argv是main函數的形參,它們是程序的命令行參數:argc代表參數個數,argv代表參數向量。這兩個參數可以用任何合法的標識符命名,但是習慣采用argc和argv。在調用帶參數的main()函數時加上參數即可,就如同使用DOS命令一樣。main函數由操作系統調用,在操作命令狀態下,實參由執行文件時的命令給出。若在源文件file1.cpp中定義帶參數的main函數如下:#include<iostream>usingnamespacestd;intmain(intargc,char*argv[]){ for(inti=0;i<argc;i++) cout<<*(argv+i)<<endl; return0;}將file1.cpp生成可執行文件后,若在命令狀態下輸入如下操作命令:file1chinazz則運行結果如下:file1chinazz2416:12下面程序的功能是:計算從命令行中輸入的第2個參數開始的所有參數中是回文字符串的參數個數。(順讀和倒讀都一樣的字符串稱為“回文”,如“level”就是回文)請填空。#include<stdio.h>

【1】

intsumhw(char**p,intn);charjughw(char*str);intmain(intargc,char*argv[]){ ints; if(argc<2)printf("請輸入有效參數\n"); else{ s=sumhw(

【2】

,argc-1); printf("共有%d個回文串\n",s); } return0;}intsumhw(char**p,intn){ charflag; inti,sum=0; for(i=0;i<n;i++) {flag=jughw(

【3】

); if(

【4】

)sum++;} returnsum;}charjughw(char*str){ char*p1,*p2; intn; n=strlen(str); p1=str; p2=

【5】

; while(

【6】

){ if(*p1!=*p2)break; else{p1++;

【7】

;} } if(

【8】

)return('N'); elsereturn('Y');}25#include<string.h>argv+1*(p+i)flag==’Y’str+n-1p1<p2p2--p1<p24.4指向數組的指針指向數組的指針是一個指針,該指針指向一個數組。定義指向數組的指針的一般格式為:類型(*數組名)[常量表達式];例如:int(*a)[10];因為*a處于小括號內,所以a先和*結合,形成*a形式,即a為一個指針;然后再和后面的[10]結合,即a為一個指向一維數組的指針變量,該一維數組的長度為10。2616:12例7.11:編寫一個包含指向數組的指針參數的函數,將3*3矩陣轉置。

輸入:輸入一個3*3矩陣。

輸出:將該矩陣轉置后輸出。#include<iostream>usingnamespacestd;voidtrans(int(*matrix)[3]);intmain(){ inta[3][3]; for(inti=0;i<3;++i) for(intj=0;j<3;++j) cin>>a[i][j]; trans(a); for(inti=0;i<3;++i){ for(intj=0;j<3;++j) cout<<a[i][j]<<""; cout<<endl; } return0;}voidtrans(int(*matrix)[3]){ inttemp; inti,j; for(i=1;i<3;i++) for(j=0;j<i;j++){ temp=*(*(matrix+j)+i); *(*(matrix+j)+i)=*(*(matrix+i)+j); *(*(matrix+i)+j)=temp; }}2716:12例7.12:有一個班級,共n名學生,各學m門課程,請找出存在不及格課程的學生,并輸出其全部成績。

輸入:第一行為兩個正整數n(n<10)和m(n<10)。然后是n行,第i行為第i名學生的m門課程的成績,各門課程成績用空格隔開。

輸出:存在不及格課程的學生的m門課程成績,每名學生占一行,成績間用空格分隔。#include<iostream>usingnamespacestd;constintN=10,M=10;voidsearch(float(*p)[M],intn,intm){ //p是指向包含4個float型元素的一維數組的指針 inti,j,flag;

for(i=0;i<n;i++){

flag=0;

for(j=0;j<m;j++)if(*(*(p+i)+j)<60){flag=1;break;} //*(*(p+i)+j)就是score[i][j] if(flag==1){ cout<<i+1<<":"; for(j=0;j<m;j++) cout<<*(*(p+i)+j)<<""; cout<<endl; } }}intmain(){ intn,m;floatscore[N][M]; cin>>n>>m;

for(inti=0;i<n;++i) for(intj=0;j<m;++j) cin>>score[i][j]; search(score,n,m); //調用search函數 return0;}2816:125.指針與函數(5.1返回指針的函數)在C/C++語言中允許一個函數的返回值是一個指針(即地址),這種返回指針的函數稱為指針型函數。定義指針型函數的一般格式為:

類型*函數名(形參表)

{

……

/*函數體*/

}其中函數名之前加“*”號表明該函數是一個指針型函數,即函數的返回值是一個指針,類型表示該指針所指向的數據類型。返回2916:12例7.13:有m個學生,每個學生有n門課程的成績(0<m,n<10)。要求在用戶輸入學生序號以后,能輸出該學生的全部成績。用返回指針的函數來實現。

輸入:第一行輸入三個正整數m,n,k;然后m行,第i行為學生序號為i的n門課程成績(以空格分隔)。

輸出:輸出序號為k的學生的n門課成績。#include<iostream>usingnamespacestd;constintM=10,N=10;float*search(float(*p)[N],intn); //函數聲明intmain(){ intm,n,k; floatscore[M][N]; cin>>m>>n>>k; for(inti=0;i<m;++i) for(intj=0;j<n;++j) cin>>score[i][j]; float*p; p=search(score,k); //調用search函數,返回score[k-1][0]的地址 for(inti=0;i<n;++i) cout<<*(p+i)<<""; //輸出score[k-1][0]~score[k-1][n-1]的值 cout<<endl; return0;}float*search(float(*p)[N],intk){return*(p+k-1);}3016:125.2指向函數的指針指向函數的指針是一個指針變量,該指針指向一個函數。C/C++程序在編譯時會將每個函數的源碼轉換為可執行代碼,并為每個函數分配一段存儲空間。因此每一個函數均有一個入口地址,當調用該函數時程序便轉入該函數的入口地址開始執行。函數擁有地址屬性,因此可定義一個指針指向某一函數。定義指向函數的指針變量的一般格式為:類型(*指針變量名)();說明:(1)定義指向函數的指針變量,并不意味著這個指針變量可以指向任何函數,它只能指向在定義函數指針時規定形式的函數。(2)將指針指向某函數后,既可通過函數名調用該函數,也可通過指向該函數的指針調用該函數。(3)用函數指針變量調用函數時,只需將“(*指針變量名)”代替函數名,然后在“(*指針變量名)”之后的小括弧中根據需要寫上實參。(4)在一個程序中,一個指向函數的指針變量可以先后指向不同的函數,在給函數指針變量賦值時僅需給出函數名而不必給出參數。(5)對于指向函數的指針變量,“++”、“--”、“+n”之類的指針運算不再有意義。(6)用函數名調用函數只能調用指定的一個函數,而通過函數指針調用函數比較靈活,可根據需要先后指向不同的函數并加以調用,但這些函數必須與該指針變量具有相同的形式。返回3116:12例7.14:使用指向函數的指針,實現求兩個正數中的最大值與最小值。

輸入:輸入2個整數。

輸出:最大值和最小值。#include<iostream>usingnamespacestd;intmax(inta,intb){returna>=b?a:b;}intmin(inta,intb){returna<b?a:b;}intmain(){ inta,b; cin>>a>>b; int(*p)(int,int); //定義一個指向函數的指針 p=max; //將函數max的地址賦給函數指針p cout<<(*p)(a,b)<<endl; //通過函數指針p調用函數max p=min; //將函數max的地址賦給函數指針p cout<<(*p)(a,b)<<endl; //通過函數指針p調用函數min return0;}3216:126.動態內存分配與指向它的指針變量全局變量是分配在內存中的靜態存儲區的,非靜態的局部變量(包括形參)是分配在內存中的動態存儲區的,這個存儲區是一個稱為棧(stack)的區域。除此以外,C語言還允許建立內存動態分配區域,以存放一些臨時用的數據,這些數據不必在程序的聲明部分定義,也不必等到函數結束時才釋放,而是需要時隨時開辟,不需要時隨時釋放。這些數據臨時存放在一個特別的自由存儲區,稱為堆(heap)區??梢愿鶕枰?,向系統申請所需大小的空間。由于未在聲明部分定義它們為變量或數組,因此不能通過變量名或數組名去引用這些數據,只能通過指針來引用。33返回怎樣建立內存的動態分配malloc函數開辟動態存儲區函數原型為:作用是在內存的動態存儲區中分配一個長度為size的連續空間。形參size的類型定為無符號整型(不允許為負數)。此函數的值(即“返回值”)是所分配區域的第一個字節的地址,或者說,此函數是一個指針型函數,返回的指針指向該分配域的第一個字節。指針的基類型為void,即不指向任何類型的數據,只提供一個純地址。如果此函數未能成功地執行(例如內存空間不足),則返回空指針(NULL)。34void*malloc(unsignedintsize);malloc(100); //開辟100字節的臨時分配域,函數值為其第1個字節的地址怎樣建立內存的動態分配用calloc函數開辟動態存儲區函數原型為作用是在內存的動態存儲區中分配n個長度為size的連續空間,這個空間一般比較大,足以保存一個數組。用calloc函數可以為一維數組開辟動態存儲空間,n為數組元素個數,每個元素長度為size。這就是動態數組。函數返回指向所分配域的第一個字節的指針;如果分配不成功,返回NULL。35p=calloc(50,4); //開辟50×4個字節的臨時分配域,把首地址賦給指針變量pvoid*calloc(unsignedn,unsignedsize);怎樣建立內存的動態分配用realloc函數重新分配動態存儲區函數原型為如果已經通過malloc函數或calloc函數獲得了動態空間,想改變其大小,可以用realloc函數重新分配。用realloc函數將p所指向的動態空間的大小改變為size。p的值不變。如果重分配不成功,返回NULL。36realloc(p,50); //將p所指向的已分配的動態空間改為50字節void*realloc(void*p,unsignedintsize);怎樣建立內存的動態分配用free函數釋放動態存儲區函數原型為作用是釋放指針變量p所指向的動態空間,使這部分空間能重新被其他變量使用。p應是最近一次調用calloc或malloc函數時得到的函數返回值。

free函數無返回值。37free(p);

//釋放指針變量p所指向的已分配的動態空間voidfree(void*p);注意:以上函數的聲明在stdlib.h頭文件中,在用到這些函數時應當用“#include<stdlib.h>”指令把stdlib.h頭文件包含到程序文件中。void指針類型C99允許使用基類型為void的指針類型??梢远x一個基類型為void的指針變量(即void*型變量),它不指向任何類型的數據。在將它的值賦給另一指針變量時由系統對它進行類型轉換,使之適合于被賦值的變量的類型。int*pt;pt=(int*)malloc(100);

//mcaloc(100)是void*型,把它轉換為int*型38注意不要把“指向void類型”理解為能指向“任何的類型”的數據,而應理解為“指向空類型”或“不指向確定的類型”的數據。6.動態內存分配(6.1分配單個元素空間)數組的長度是預先定義好的,在整個程序中固定不變。C/C++中不允許定義元素個數不確定的數組。例如:intn;inta[n]; //此定義不允許在實際的程序設計中,常遇到暫時無法確定所需內存空間大小的情形。如果定義一個盡可能大的數組,又會造成空間浪費。為此,C++提供了一種“動態內存分配”的機制,使得程序可以在運行期間,根據實際需要,要求系統臨時分配一片內存空間用于存放數據。此種內存分配是在程序運行中進行的,而不是在編譯時就確定的,故稱為“動態內存分配”。在C++中通過“new”運算符來實現動態內存分配。new運算符的一般使用格式為:p=newT;其中,T是任意類型名,p是類型為T*的指針。執行該語句后,系統會動態分配出一片大小為sizeof(T)字節的內存空間,并且將該內存空間的起始地址賦值給P。例如:int*p;p=newint; //①*p=5;語句①動態分配了一片4字節大小的內存空間,整型指針p指向這片空間的起始地址。返回3916:126.2分配多個元素空間new運算符還可以用來動態分配一個任意大小的數組:p=newT[n];T是任意類型名,p是類型為T*的指針,n代表“元素個數”,它可以是任何值為正整數的表達式,表達式中可以包含變量、函數調用。該語句成功執行后,系統動態分配n*sizeof(T)個字節的連續內存空間,并將這片連續內存空間的起始地址賦給p。如果要求分配的空間太大,系統無法滿足,那么動態內存分配就會失敗。因此,通常在進行較大的動態內存分配時,要判斷該內存分配是否成功。判斷的方法如下:int*p=newint[400]; //int*p=(int*)malloc(100*sizeof(int));if(p==NULL)printf(“內存分配失敗”);elseprintf(“內存分配成功”);4016:126.3釋放空間使用完系統動態分配的內存空間后,程序應及時釋放該空間,以便其他程序能夠動態申請使用。C++提供“delete”運算符釋放動態分配的內存空間。delete運算符的基本用法是:delete指針;該指針必須已指向動態分配的內存空間,否則運行時很可能會出錯。例如:int*p=newint;*p=5;deletep;deletep; //本句會導致程序異常以上第一條delete語句正確地釋放了動態分配的4個字節內存空間。第二條delete語句會導致程序出錯,因為p所指向的空間已經釋放。4116:12如果使用new運算符動態分配了一個數組,那么釋放該數組時應以如下形式使用delete運算符:delete[]指針;例如:int*p=newint[20];p[0]=1;delete[]p;同樣要求被delete的指針p必須是已指向動態分配的內存空間的指針,否則會報錯。如果動態分配了一個數組,但是卻用“delete指針”的方式釋放,則程序編譯時不會報錯,程序運行時也不會發現異常,但實際上該動態分配的內存空間沒有被完全釋放。使用new運算符動態分配的內存空間,一定要使用delete運算符及時予以釋放。否則,即便程序運行已經結束,系統也不會收回該內存空間。若可用內存被大量消耗,則會導致操作系統運行速度變得越來越慢,甚至無法再啟動新的程序運行。4216:12例7.15:有n個整數,使前面各數順序向后移動k個位置,移出的數再從開頭移入。

輸入:輸入分2行,第一行是兩個整數n,k,第二行是n個整數,用空格隔開。

輸出:輸出占一行,為移動之后的n個數組元素,由空格分隔。#include<iostream>usingnamespacestd;voidringShift(int*a,intn,intk){ int*b=newint[k]; for(inti=0;i<k;i++) b[i]=a[n-k+i]; for(inti=n-1;i-k>=0;i--) a[i]=a[i-k]; for(inti=0;i<k;i++) a[i]=b[i]; delete[]b;}intmain(){ intn,k; cin>>n>>k; int*a=newint[n]; for(inti=0;i<n;i++)

cin>>a[i];

ringShift(a,n,k); for(inti=0;i<n;i++)

cout<<a[i]<<""; delete[]a; return0;}4316:12例7.16:數組a中有m個按升序序排列的元素,數組b中有n個降序排列的元素,編程將所有元素按降序存入數組c中。

輸入:輸入有兩行,第一行首先是一個正整數m,然后是m個整數;第二行首先是一個正整數n,然后是n個整數,m,n均小于等于1000000。

輸出:輸出合并后的m+n個整數,數據之間用空格隔開。輸出占一行。#include<iostream>usingnamespacestd;intmain(){ intm,n,i,j,k; cin>>m; int*a=newint[m]; for(i=0;i<m;i++)

cin>>a[i]; cin>>n; int*b=newint[n]; for(i=0;i<n;i++)

cin>>b[i]; i=m-1;j=0;k=0; int*c=newint[m+n]; while(i>=0&&j<n){ if(a[i]>b[j])c[k++]=a[i--]; elsec[k++]

溫馨提示

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

評論

0/150

提交評論