C++程序設(shè)計基礎(chǔ)教程 第2版 課件第6章 指針_第1頁
C++程序設(shè)計基礎(chǔ)教程 第2版 課件第6章 指針_第2頁
C++程序設(shè)計基礎(chǔ)教程 第2版 課件第6章 指針_第3頁
C++程序設(shè)計基礎(chǔ)教程 第2版 課件第6章 指針_第4頁
C++程序設(shè)計基礎(chǔ)教程 第2版 課件第6章 指針_第5頁
已閱讀5頁,還剩90頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第6章

指針6指針6.1指針的定義與初始化6.2指針的使用6.3指針與數(shù)組6.4指針與字符串6.5指針與函數(shù)6.6引用6.7應(yīng)用實例6.1指針的定義與初始化6.1.1指針的定義回顧:變量名和變量值變量名:代表內(nèi)存中的一塊可用空間,具體的地址由編譯器來記住,用戶只要通過變量名就可以對這塊空間進行讀寫。變量值:在這塊空間中存放的內(nèi)容。合法標識符指針的目標變量的數(shù)據(jù)類型指針變量的定義一般形式:

數(shù)據(jù)類型*指針名;例int*p1,*p2;float*q;staticchar*name;表示定義指針變量不是‘*’運算符說明1、int*p1,*p2;

與int*p1,p2;的區(qū)別;2、指針變量名是p1,p2,不是*p1,*p2;3、指針變量只能指向定義時所規(guī)定類型的變量;4、指針變量定義后,變量值不確定,應(yīng)用前必須先賦值;&與*運算符兩者關(guān)系:互為逆運算&含義:取變量的地址單目運算符優(yōu)先級:2結(jié)合性:自右向左*含義:

取指針所指向變量的內(nèi)容單目運算符優(yōu)先級:2結(jié)合性:自右向左…...…...200020082012整型變量i10變量i_pointer20042000指針變量200010i_pointer*i_pointer&i_pointeriinti=10;int*i_pointer=&i;變量與指針

指針變量與其所指向的變量之間的關(guān)系3變量i2000i_pointer*i_pointeri*i_pointer&ii_pointeri=3;*i_pointer=33變量i2000i_pointer*i_pointeri*i_pointer&ii_pointeri=3;*i_pointer=3inti=3;int*i_pointer;i_pointer=&i;

一般的C++編譯系統(tǒng)為每一個指針變量分配4個字節(jié)的存儲單元,用來存放變量的地址。在定義指針變量時要注意:(1)不能用一個整數(shù)給一個指針變量賦初值。(2)在定義指針變量時必須指定基類型。6.1.2指針的初始化一般形式:

數(shù)據(jù)類型*指針名=初始地址值;賦給指針變量,不是賦給目標變量例inti;int*p=&i;變量必須已說明過類型應(yīng)一致例

int*p=&i;

inti;例inti;int*p=&i;int*q=p;用已初始化指針變量作初值例main(){inti=10;int*p;

*p=i;cout<<*p;}危險!例

main(){inti=10,k;int*p;

p=&k;*p=i;cout<<*p;}指針變量必須先賦值,再使用…...…...2000200420062005整型變量i10指針變量p200120022003隨機對指針變量進行賦值時,必須滿足如下三個方面:賦給指針變量的必須是一個地址值;該地址必須是合法的,即系統(tǒng)已經(jīng)分配給用戶使用的空間地址;目標變量的類型與指針變量定義時的類型必須相符;用數(shù)組名或字符串對指針進行初始化:(1)利用數(shù)組名進行初始化

inta[5],*p=a;(2)利用字符串進行初始化

char*p="C++Language";6.2指針的使用6.2.1指針運算符&含義:取變量的地址單目運算符優(yōu)先級:2結(jié)合性:自右向左*含義:

取指針所指向變量的內(nèi)容單目運算符優(yōu)先級:2結(jié)合性:自右向左【例6-1】指針運算符的使用#include<iostream>usingnamespacestd;intmain(){ inta=3,b=13; int*p; p=&a; cout<<"---------初始情況-----"<<endl;cout<<"變量a的地址:"<<&a<<endl; cout<<"變量p的地址:"<<&p<<endl; cout<<"變量p里存的內(nèi)容:"<<p<<endl; cout<<"p所指向的目標變量的值:"<<*p<<endl; cout<<"-------目標變量修改后的情況-----"<<endl; a=4; cout<<"a值改變后的輸出:"<<a<<""<<*p<<endl; *p=5; cout<<"*p值改變后的輸出:"<<a<<""<<*p<<endl;cout<<"--------指針修改后的情況---------"<<endl; p=&b; cout<<"變量b的地址:"<<&b<<endl; cout<<"變量p的地址:"<<&p<<endl; cout<<"變量p里存的內(nèi)容:"<<p<<endl; cout<<"p所指向的目標變量的值:"<<*p<<endl;return0;}運行結(jié)果:6.2.2指針變量的運算(1)賦值運算對指針變量進行賦值時,需要符合下面三個方面的要求:將一個地址賦給指針變量;該地址必須是合法的,也就是系統(tǒng)允許分配給用戶使用的空間地址;指針變量只能接受與它所指向的目標變量類型一致的變量地址。例如:

inta,*p;floatf;charc;p=&a;//賦值正確,把整型變量a的地址賦予整型指針變量pap=&f;//賦值錯誤,類型不匹配

p=&c;//賦值錯誤,類型不匹配

p=&b;//賦值錯誤,變量b沒有提前定義,該地址不合法將數(shù)組或字符串的首地址賦給指向同類型的指針變量例如:把數(shù)組的首地址賦給指向同類型的指針變量inta[5],*p;p=a;也可寫為:p=&a[0];例如:把字符串的首地址賦給指向字符類型的指針變量char*p;p="C++Language";由于指針變量也是一種變量,所以可以把一個指針變量的值賦給指向相同類型變量的另一個指針變量。例如:

inta,*p1=&a,*p2;p2=p1;指針變量還可以賦0值,這種指針稱為空指針。例如:

#defineNULL0int*p=NULL;對指針變量賦0值和不賦值實質(zhì)上是不同的(2)部分算術(shù)和關(guān)系運算①算術(shù)運算指針變量可以與整數(shù)n進行加減運算意義:指針當(dāng)前指向的位置向前或向后移動n個位置。例如:inta[5],*p;p=a;p=p+3;②兩指針變量相減兩指針變量相減返回的值是兩個指針所指數(shù)組元素之間相差的元素個數(shù)。pf2-pf1的結(jié)果為(0xff1018-0xff1008)/4=4,表示pf1和pf2之間相差4個元素③兩指針變量進行關(guān)系運算兩個指針變量進行關(guān)系運算,實際上是對其存儲的地址值進行比較。當(dāng)兩指針指向同一數(shù)組時,該運算進行的是所指數(shù)組元素位置之間的比較。6.3指針與數(shù)組6.3.1指針與一維數(shù)組一維數(shù)組名是數(shù)組中第一個元素的首地址,故可以將其賦給指向同類型的指針,例如:

inta[5],*pp=a;數(shù)組元素的訪問方式:①以下標的形式訪問:

a[i],i=0,1,2,3,4或p[i],i=0,1,2,3,4②以指針的形式訪問:

*(a+i),i=0,1,2,3,4或*(p+i),i=0,1,2,3,4a[i]

p[i]

*(p+i)

*(a+i)【例6-3】利用指針操作數(shù)組里的元素。#include<iostream>usingnamespacestd;intmain(){ inti,temp; inta[10]={0}; int*p=a,*q=&a[9];

cout<<"p-q="<<p-q<<endl;

//利用指針p對數(shù)組賦值0-9 for(i=0;p<=q;p++) *p=i++;p=a;//使p指針重新指向數(shù)組的第一個元素//利用下標的形式輸出數(shù)組內(nèi)容,驗證賦值是否成功cout<<"賦值后的數(shù)組輸出:"<<endl;for(i=0;i<10;i++)

cout<<p[i]<<"";cout<<endl;/*利用指針p和指針q實現(xiàn)逆序存放:每次a[i]與a[9-i]內(nèi)容交換(i=0,1,2,3,4)*/ while(p<q)

{ temp=*p; *p=*q; *q=temp; p++; q--;

}在做什么? //輸出數(shù)組內(nèi)容,驗證交換是否成功 cout<<"對稱元素內(nèi)容交換后的數(shù)組輸出:"<<endl; for(i=0;i<10;i++) cout<<*(a+i)<<""; cout<<endl; return0;}運行結(jié)果:6.3.2指針與二維數(shù)組(1)指向數(shù)組元素的指針二維數(shù)組在內(nèi)存中的存放是按照一維線性排列的,每個數(shù)組元素按其類型占有幾個連續(xù)的內(nèi)存單元,因此可以將某個數(shù)組元素的地址賦給類型相符的指針,從而利用指針的運算來間接訪問該數(shù)組里的所有元素。例如:inta[3][4];int*p=&a[1][2];

可以通過指針p向上或向下移動來訪問數(shù)組中的每個元素。如語句:while(p>=&a[0][0])cout<<*(p--);

或:

while(p<=&a[2][3])cout<<*(p++);(2)指向一維數(shù)組的指針編譯器總是將二維數(shù)組看成是一個一維數(shù)組,而一維數(shù)組的每一個元素又都是一個數(shù)組。以inta[3][4];為例,二維數(shù)組名a是第一行所占空間的首地址(常量),設(shè)為0x00ff00。當(dāng)a+1時,新地址是0x00ff10,即a+1=0x00ff10。如圖所示。

當(dāng)用二維數(shù)組名對指針進行賦值時,指向基本數(shù)據(jù)類型(如整型、浮點型、字符型)的指針變量就不再合適,而是要用一種新的指針變量。它指向一個一維數(shù)組,即目標變量是一個一維數(shù)組空間,因此稱為“指向一維數(shù)組的指針”,簡稱數(shù)組指針。定義數(shù)組指針的語法為:

數(shù)據(jù)類型(*指針變量名)[數(shù)組長度];其中,數(shù)組長度決定了該指針所指向的數(shù)組包含的元素個數(shù),數(shù)據(jù)類型決定了該數(shù)組里存儲的數(shù)據(jù)。例如:

inta[3][4];int(*p)[4]=a;注意:因為二維數(shù)組為int型,所以數(shù)組指針所指向的空間里的元素也應(yīng)該是int型。定義數(shù)組指針時,方括號中的元素個數(shù)必須與二維數(shù)組的第二維大小相同。p與a的區(qū)別:a是一個指針常量,而p是一個指針變量。訪問二維數(shù)組的方式也分為兩種:①以下標的形式訪問:

a[i][j],i=0,1,2;j=0,1,2,3

或p[i][j],i=0,1,2;j=0,1,2,3②以指針的形式訪問:*(*(a+i)+j),i=0,1,2;j=0,1,2,3

或*(*(p+i)+j),i=0,1,2;j=0,1,2,3二維數(shù)組中存在兩種地址:每一行的地址,如a+i,i=0,1,2或p+i,i=0,1,2,這種稱為行指針;某個元素的地址,如a[i]+j,i=0,1,2;j=0,1,2,3或*(p+i)+j,i=0,1,2;j=0,1,2,3,這種稱為列指針?!纠?-4】利用指針實現(xiàn)3×3矩陣的轉(zhuǎn)置。#include<iostream>#include<iomanip>usingnamespacestd;intmain(){ inta[3][3];inti,j,t; int(*p)[3]; p=a; cout<<"請輸入一個3×3的矩陣:"<<endl;for(i=0;i<3;i++) for(j=0;j<3;j++) cin>>*(*(a+i)+j);for(i=0;i<3;i++) for(j=i;j<3;j++) { t=*(*(p+i)+j); *(*(p+i)+j)=*(*(p+j)+i); *(*(p+j)+i)=t; } cout<<"轉(zhuǎn)置后的矩陣:"<<endl; for(i=0;i<3;i++) { for(j=0;j<3;j++) cout<<setw(5)<<p[i][j]<<""; cout<<endl; } return0;}運行結(jié)果:6.4指針與字符串可以通過數(shù)組或指針兩種方式來建立一個字符串。例如:

chars1[]="Hello";char*s2="Hello";說明兩者如果均作為指針來用,則都可以進行加法運算。如:

for(i=0;i<3;i++)cout<<*(s1+i);

for(i=0;i<3;i++)cout<<*(s2+i);輸出結(jié)果都為:Hel思考:下列語句中是否可以將s2換成s1?為什么?

while(*(s2)!='\0')cout<<*(s2++);下列語句中是否可以將s1換成s2?為什么?

s1[1]=‘a(chǎn)’;【例6-5】寫出下列程序的輸出結(jié)果。#include<iostream>usingnamespacestd;intmain(){char*string=”IloveChina!”;cout<<string<<endl;cout<<string+7<<endl;return0;}【例6-6】從鍵盤輸入兩個字符串s1和s2,假設(shè)兩個字符串中只包含數(shù)字和英文字母,如果s1包含了s2中的每一個字符(不需要按照s2里的順序連續(xù)包含),就輸出“Yes”;如果沒有全部包含,就輸出“No”,并輸出缺少的字符個數(shù)。要求:函數(shù)完成查找工作,結(jié)論在主函數(shù)內(nèi)輸出。intjudge(char*s,char*b){ inti,j; intn=0; i=0; while(*(b+i))//依次取子串中的每一個字符 {j=0; while(*(s+j))//依次取源串中的每一個字符

{if(*(b+i)==*(s+j)) { *(s+j)='*'; break; }

j++; } if(*(s+j)=='\0')n++;//累計出現(xiàn)的字符個數(shù) i++; } returnn;}intmain(){ chars1[500],s2[500]; intp; cout<<"請輸入源串和子串:"<<endl; cin>>s1>>s2; p=judge(s1,s2); if(p==0)cout<<"Yes"<<endl; elsecout<<"No"<<p<<endl;

return0;}運行結(jié)果:請輸入源串和子串:pRYYGrYB225YrR8RrYNo36.5指針與函數(shù)6.5.1指針作為函數(shù)參數(shù)實參為指針變量實參為數(shù)組元素的地址實參為一維數(shù)組名實參為二維數(shù)據(jù)名【例6-7】設(shè)有4個學(xué)生,5門課。編程實現(xiàn):(1)輸出某一門課的平均分;(2)根據(jù)學(xué)號輸出某個學(xué)生的全部成績及平均成績;#include<iostream>#include<iomanip>#definerow5#definecol7usingnamespacestd;voidinput(int(*p)[col],intstu,intcour);//輸入學(xué)生學(xué)號和各科成績voidavgstud(int*p,intcour);//計算某個學(xué)生的平均分voidavgcour(int(*p)[col],intstu,intcour);//計算每門課的平均分voidoutput(int(*p)[col],intn);//輸出某個學(xué)生的各科成績和平均分intmain(){ inti,cour,num; intscore[row][col]={0};input(score,row-1,col-1); for(i=0;i<row-1;i++) avgstud(score[i],col-2); avgcour(score,row-1,col-2);cout<<"請輸入需要查詢第幾科目:"; cin>>cour; cout<<"該科目的平均分為:"<<score[row-1][cour]<<endl; cout<<"請輸入需要查詢的學(xué)生學(xué)號"; cin>>num; output(score,num); return0;}voidinput(int(*p)[col],intstu,intcour){ inti,j; cout<<"請輸入學(xué)生的學(xué)號和各科成績:"<<endl;for(i=0;i<stu;i++) { cout<<"第"<<i+1<<"個學(xué)生:"; for(j=0;j<cour;j++) cin>>*(*(p+i)+j); }}voidavgstud(int*p,intcour){ floatsum=0.0; inti; for(i=1;i<=cour;i++) sum+=*(p+i); *(p+i)=sum/cour;}voidavgcour(int(*p)[col],intstu,intcour){ intsum; inti,j; for(j=1;j<=cour;j++) { sum=0; for(i=0;i<stu;i++) sum+=p[i][j]; p[i][j]=sum/stu; } }voidoutput(int(*p)[col],intn){inti,j;cout<<"學(xué)號為"<<n<<"的學(xué)生情況:”<<endl;for(i=0;i<row;i++) if(p[i][0]==n) { for(j=1;j<col;j++) cout<<p[i][j]<<setw(7); }cout<<endl;}運行結(jié)果:【例6-8】編寫函數(shù)實現(xiàn)三個數(shù)據(jù)按由小到大的順序輸出,要求利用指針進行參數(shù)傳遞。#include<iostream>usingnamespacestd;voidcmp(int*,int*);intmain(){ inta,b,c; int*p=&a,*q=&b,*r=&c; cout<<"請輸入三個數(shù)據(jù):"<<endl; cin>>a>>b>>c; cmp(p,q); //比較大小,將小的排在前面

cmp(p,r); cmp(q,r); cout<<"則它們由小到大的排列順序為:"<<endl; cout<<a<<""<<b<<""<<c<<endl; return0;}voidcmp(int*x,int*y){ int*z; if(*x>*y) { z=x;x=y;y=z; }}為什么?如果希望函數(shù)cmp在比較大小后能夠?qū)?shù)據(jù)進行內(nèi)容的交換,需要用到指針的“間接訪問”功能。如將上例中的cmp()函數(shù)修改為:voidcmp(int*x,int*y){ intz; if(*x>*y) { z=*x;*x=*y;*y=z;}}6.5.2指針作為函數(shù)返回值

函數(shù)的返回值除了可以是普通類型的變量(如整型、浮點型、字符型),也可以返回一個數(shù)據(jù)結(jié)構(gòu),這就需要由指針來實現(xiàn)。當(dāng)指針作為函數(shù)返回值時,需要注意兩點:接收函數(shù)返回值的指針變量必須與返回值類型相符;返回的地址必須是一個合法地址,即實際存在的空間首地址?!纠?-9】編制具有如下原型的函數(shù):char*findFirst(char*sourceStr,char*subStr);

該函數(shù)所實現(xiàn)的功能為:返回源串sourceStr中第一次出現(xiàn)subStr子字符串的頭字符位置(地址值)。如果源串sourceStr的長度小于subStr子字符串的長度,或者源串sourceStr中根本就不出現(xiàn)subStr子字符串的話,返回空指針值NULL。而后編制主函數(shù),任意輸入兩個字符串,將它們用作實參來調(diào)用這個函數(shù),以驗證其正確性。要求實現(xiàn)程序中不可使用string頭文件內(nèi)有關(guān)尋找子串的標準庫函數(shù)。intmain(){charstr[30],substr[20];char*p;p=str;cout<<"請輸入源串和子串:"<<endl;cin>>str>>substr;p=findFirst(str,substr);if(p)

cout<<"子串首次出現(xiàn)是從第"<<p-str+1<<"個字符開始"<<endl;else

cout<<"沒有查找到!"<<endl;

return0;}char*findFirst(char*sourceStr,char*subStr){char*p1=sourceStr,*p2=subStr;intlen1=0,len2=0;

inti;//記錄每趟掃描,源串的開始位置

intj;

len1=strlen(sourceStr);

len2=strlen(subStr);

for(i=0;i<len1-len2;i++)

{for(j=0;j<len2;j++)//子串每次從頭開始掃描

if(*(p1+i+j)!=*(p2+j))break;

if(j==len2)returnp1+i; } returnNULL;}運行結(jié)果:6.6引用

引用就是給變量取一個別名,因此引用是變量的同義詞,是變量本身,而不是重新建立了一個副本,所以對引用的任何操作實際上就是對其所代表的變量的改動。6.6.1引用的定義當(dāng)建立引用時,需要用一個變量的名字對它初始化。引用運算符“&”用來定義一個引用。定義的語法為:數(shù)據(jù)類型&引用名=變量名;例如,對一個整型變量的引用:

inti;int&ri=i;說明引用類型與它所引用的變量的類型相同。如引用ri類型為int型。一旦說明引用ri是變量i的別名,那么在其作用域范圍內(nèi),引用ri不允許再與其他任何變量建立別名關(guān)系。6.6.2引用的使用引用的用法主要有三種:①單獨使用(一般稱為“獨立引用”);②作為函數(shù)參數(shù)使用;③作為函數(shù)返回值使用。從功能上來說,引用型變量是被引用變量的“別名”,這兩個變量只是名稱不同,變量的地址是同一個。由于引用傳遞的是對象本身的地址,所以不存在分配、釋放臨時變量的問題,效率較高,因此它主要用在給函數(shù)傳遞大型的對象以及從函數(shù)中返回左值。(1)獨立引用定義獨立引用時需要注意以下規(guī)則:①引用型變量在定義時必須初始化。②被引用的對象必須已經(jīng)分配了空間,即不能為空。【例6-10】引用變量的單獨使用#include<iostream>usingnamespacestd;intmain(){inta;int&b=a;//b和a實際上是同一變量

cout<<"被引用變量a的地址"<<&b<<endl;cout<<"引用型變量b的地址"<<&a<<endl;b=100;cout<<"b賦值為100后,a="<<a<<endl; a=10;cout<<"a賦值為10后,b="<<b<<endl;return0;}運行結(jié)果:(2)作為函數(shù)參數(shù)使用

引用參數(shù)是其對應(yīng)實參變量的“替身”,這意味著:被調(diào)函數(shù)中對引用參數(shù)值的使用與更改就是對相應(yīng)實參變量值的直接使用與更改,從而可實現(xiàn)調(diào)用函數(shù)與被調(diào)函數(shù)間數(shù)據(jù)的“雙向傳值”。(3)作為函數(shù)返回值使用

若函數(shù)的返回值為引用,則返回的不僅是一個值,還可以將函數(shù)調(diào)用結(jié)果當(dāng)作“變量”來進行使用,即作為“左值”的存儲空間進行運算。通過例題6-11對上述兩種情況進行分析。#include<iostream>usingnamespacestd;intk=56;//全局變量voidf1(int,int&);int&f2(int&,int&);intmain(){ intx=1,y=2,z=3,w=0; f1(x,y); cout<<"main1:x,y=>"<<x<<","<<y<<endl; cout<<"main1:z,k,w=>"<<z<<","<<k<<","<<w<<endl; w=f2(z,k)++; cout<<"main2:z,k,w=>"<<z<<","<<k<<","<<w<<endl; w=f2(z,k)++; cout<<"main3:z,k,w=>"<<z<<","<<k<<","<<w<<endl; return0;}voidf1(inta,int&b){ cout<<"I

溫馨提示

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

評論

0/150

提交評論