C++ 程序設(shè)計課件:第五章 數(shù)組與指針_第1頁
C++ 程序設(shè)計課件:第五章 數(shù)組與指針_第2頁
C++ 程序設(shè)計課件:第五章 數(shù)組與指針_第3頁
C++ 程序設(shè)計課件:第五章 數(shù)組與指針_第4頁
C++ 程序設(shè)計課件:第五章 數(shù)組與指針_第5頁
已閱讀5頁,還剩84頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、本章將深入學(xué)習(xí)數(shù)組包括多維數(shù)組的知識和應(yīng)用,以及它們與指針的關(guān)系。 C+語言擁有在運行時獲得變量地址和操縱地址的能力,這種可用來操縱地址的變量類型就是指針。指針可以用于數(shù)組,用于內(nèi)存訪問,還可作為函數(shù)的參數(shù)。,第五章 數(shù)組與指針,第五章 數(shù)組與指針,5.1 數(shù)組,5.5 數(shù)組與指針,5.4 this指針,5.3 指針與地址,5.2 多維數(shù)組,5.7 多級指針與多維數(shù)組(選讀),5.6 字符串,5.1 數(shù)組,C+的數(shù)據(jù)類型: 基本數(shù)據(jù)類型亦稱內(nèi)置數(shù)據(jù)類型。C+為它們提供了內(nèi)置的支持(協(xié)助函數(shù)helper function),以完成各種允許的運算。也就是說基本數(shù)據(jù)類型也是一個類:有數(shù)據(jù)有操作,兩者

2、是封裝起來的。,在C+的標(biāo)準(zhǔn)庫中支持基本類抽象的組合,如字符串類,復(fù)數(shù)類等標(biāo)準(zhǔn)庫類類型。,在內(nèi)置數(shù)據(jù)類型和標(biāo)準(zhǔn)庫類類型之間是復(fù)合類型(Compound type),特別是指針和數(shù)組類型。,5.1 數(shù)組,5.1.1 數(shù)組、數(shù)組元素及其存儲方式,5.1.2 數(shù)組名作為函數(shù)參數(shù),5.1.3 數(shù)組的應(yīng)用回溯算法(選讀),5.1.1 數(shù)組與數(shù)組元素及其存儲方式,數(shù)組的引入: 數(shù)組(array)是一種順序容器(sequence container),是由單一類型元素組成的一個有序集合: int fibon10=0,1,1,2,3,5,8,13,21,34;,fibon0,fibon1,fibon2,fib

3、on3,fibon8,fibon9,圖5.1 數(shù)組在內(nèi)存中的存儲,數(shù)組名為fibon,這是一個包含10個元素的整型一維(dimension)數(shù)組,其第一個元素為fibon0,存放0,最后一個元素為fibon9,存放34。,數(shù)組元素的訪問方式: 通過下標(biāo)操作符(subscript),按元素在數(shù)組中的位置進行訪問,稱為索引訪問(indexing)或下標(biāo)訪問(subscripting)。參見圖5.1 。,注意: 1: 數(shù)組是一種組合類型,是不能作為一個整體進行訪問和處理的,只能按元素進行個別的訪問和處理。 2: C+數(shù)組第一個元素的下標(biāo)為0,而不是1,且下標(biāo)表達方式是固定的。 3:數(shù)組元素在內(nèi)存中是

4、從低地址開始順序排列,各元素的存儲單元占用內(nèi)存大小相同,各元素的存儲單元之間沒有空隙,可以從數(shù)組第一個元素存儲單元的起始地址計算出任意一個元素存儲單元的起始地址。,5.1.1 數(shù)組與數(shù)組元素及其存儲方式,【例 5.1】找出整型數(shù)組各元素中的最大數(shù)和最小數(shù)。數(shù)組中的數(shù)由隨機數(shù)函數(shù) rand()產(chǎn)生。,5.1.1 數(shù)組與數(shù)組元素及其存儲方式,結(jié)構(gòu)數(shù)組定義: struct keyword char word16; /關(guān)鍵字 int count; /該關(guān)鍵字將在源程序中出現(xiàn)的次數(shù) ; 初始化: 結(jié)構(gòu)數(shù)組初始化時可以用括號來區(qū)分每一個結(jié)構(gòu),例如: keyword keytab=auto, 0,break

5、, 0,case, 0, ; 當(dāng)提供了數(shù)組中所有結(jié)構(gòu)元素的值時,不必用這種括號的形式。 keyword keytab=auto, 0,break, 0,case, 0,char, 0, unsigned, 0,volatile, 0,while, 0,;,5.1.1 數(shù)組與數(shù)組元素及其存儲方式,對象數(shù)組定義: CGoods goods3; 該商品類對象數(shù)組包含3個商品對象數(shù)組元素,系統(tǒng)調(diào)用3次默認(rèn)的構(gòu)造函數(shù)來建立這3個商品對象數(shù)組元素。 初始化: 應(yīng)該完整書寫各個元素的構(gòu)造函數(shù)及成員數(shù)據(jù)初值: CGoods goods3= CGoods(夏利2000,30,98000.0), /調(diào)用三參數(shù)構(gòu)造

6、函數(shù),初始化goods0 CGoods(桑塔納2000,164000.0), /調(diào)用兩參數(shù)構(gòu)造函數(shù),初始化goods1 CGoods() /調(diào)用默認(rèn)的構(gòu)造函數(shù),初始化goods2 ;,5.1.2 數(shù)組名作為函數(shù)參數(shù),數(shù)組作為參數(shù): 數(shù)組可以作為函數(shù)的參數(shù)。在函數(shù)調(diào)用時傳遞實參數(shù)組的首地址,所以在被調(diào)函數(shù)中對形參數(shù)組的處理實際就是對調(diào)用函數(shù)的實參數(shù)組的處理。,C+只傳遞數(shù)組首地址,而對數(shù)組邊界不加檢查。這帶來的好處是,函數(shù)對長度不等的同類數(shù)組都通用。如要指定長度可以設(shè)定另一個參數(shù)來傳遞數(shù)組元素的個數(shù)。,【例5.2】字符數(shù)組與字符數(shù)組相連接,5.1.3 數(shù)組的應(yīng)用回溯算法(選讀),回溯法: 回溯法

7、的基本思想是,通過對問題的分析找出解決問題的線索,先在一個局部上找出滿足問題條件的局部的解,然后逐步由局部解向整個問題的解的方向試探,若試探成功就得到問題的解,試探失敗逐步向后退,改變局部解再向前試探。回溯法能避免枚舉法的許多不必要的搜索,使問題比較快地得到解決?;厮莘☉?yīng)用廣泛,八皇后問題、迷宮問題、四色地圖等等都可以用回溯法求解。 【例5.3】八皇后問題:在88的國際象棋棋盤上安放八個皇后,為避免她們之間相互攻擊,要求沒有任何兩個皇后在棋盤的同一行、同一列及在同一對角線上。圖6.4是八皇后問題的一個解。八皇后在棋盤上可能有的布局?jǐn)?shù)是:C86464!(8!56!)=4426165368種,用回

8、溯法解決八皇后問題顯然是合適的。,5.2 多維數(shù)組,5.2.1 多維數(shù)組,5.2.2 多維數(shù)組作為函數(shù)參數(shù),C+中數(shù)組可以嵌套,就是多維數(shù)組。,二維數(shù)組: 一維數(shù)組可對應(yīng)數(shù)學(xué)中的向量,而二維數(shù)組可對應(yīng)矩陣,可用一個二維數(shù)組存儲矩陣。,5.2.1 多維數(shù)組存儲與訪問方式,二維數(shù)組的橫向稱為行,縱向稱為列,上面這個數(shù)組為三行六列。定義二維數(shù)組的通用格式為: 存儲類型 類型 數(shù)組名常量行表達式 常量列表達式; 行與列用常量表達式表示。,5.2.1 多維數(shù)組存儲與訪問方式,二維數(shù)組分析: 上面的數(shù)組可定義為: int mat36; 第一行第一列的元素為mat00,第三行第六列元素為 mat25, 下標(biāo)

9、仍是從0開始。 計算機內(nèi)存是一維編址的,多維數(shù)組必須要轉(zhuǎn)化為一維方式存儲,越右的下標(biāo)變化越快,二維數(shù)組則按行排列,先排第一行,再排第二行,直到所有行排完: mat00 mat01 mat02 mat03 mat04 mat05 mat10 mat11 mat12 mat13 mat14 mat15 mat20 mat21 mat22 mat23 mat24 mat25 即所謂按行排列。 有了確定的關(guān)系后可以算出多維數(shù)組任一元素在內(nèi)存的位置,設(shè)有a數(shù)組m行n列,每個元素占b個字節(jié),aij 的首地址為: 數(shù)組的首地址+(i*n+j)*b;,5.2.1 多維數(shù)組存儲與訪問方式,圖5.3 6*3*4的

10、三維數(shù)組,多維數(shù)組分析: C/C+ 中的多維數(shù)組基本的定義是以數(shù)組作為元素構(gòu)成的數(shù)組,二維數(shù)組的數(shù)組元素是一維數(shù)組,三維數(shù)組的數(shù)組元素是一個二維數(shù)組,依此類推。也就是說,多維數(shù)組用的是一個嵌套的定義。,圖5.3表示一個三維數(shù)組可定義為: int a3d634; a3d是由6個二維數(shù)組構(gòu)成的數(shù)組,其中第一個二維數(shù)組用a3d 0 表示,即圖6.5立方體最上面的3*4大小的一片,也就是一個3*4的二維數(shù)組。 而a3d02則是a3d0 的第3個元素,一個一維數(shù)組,立方體最上最右的一條,(陰影所示)即一個4元素的一維數(shù)組。,5.2.1 多維數(shù)組存儲與訪問方式,多維數(shù)組的數(shù)組名: 代表數(shù)組中第一維(最高維

11、)第一個元素(0號元素)在內(nèi)存中的首地址,如三維數(shù)組的數(shù)組名代表的是組成三維數(shù)組的第一個二維數(shù)組的存儲首地址。 當(dāng)數(shù)組作為函數(shù)的參數(shù)進行傳遞時,多維數(shù)組同樣是作為第一維第一個數(shù)組的首地址傳遞給函數(shù),所以物理上是傳地址。在函數(shù)中對形參的數(shù)組元素的修改實際上是對作為實參的原數(shù)組的元素進行修改。,5.2.1 多維數(shù)組存儲與訪問方式,初始化: 對于二維數(shù)組,可用嵌套一維數(shù)組初始化進行: int matrix36=1,3,5,7,9,11,2,4,6,8,10,12,3,5,7,11,13,17; 也可以按數(shù)組元素存儲次序列出各元素的值: int matrix36=1,3,5,7,9,11,2,4,6,

12、8,10,12,3,5,7,11,13,17; 還可以對部分元素賦初值,沒有明確初值的元素清0: int matrix36=1,3,2,4,3,5,7; 其結(jié)果等效于: int matrix36=1,3,0,0,0,0,2,4,0,0,0,0,3,5,7,0,0,0; 最后還可由初始化數(shù)據(jù)來確定數(shù)組最高維,如 int matrix6=1,3,5,7,9,11,2,4,6,8,10,12,3,5,7,11,13,17; 結(jié)果定義的matrix是三行六列的數(shù)組。也可以 int matrix6=1,3,2,4,3,5,7; 同樣也是三行六列。注意這里只能最高維省略。,5.2.1 多維數(shù)組存儲與訪問方

13、式,圖5.4 極點與鞍點示意圖,【例5.4】已知矩陣 int mat88,找出其中的極點與鞍點。如某元素在所在行相鄰點中與所在列相鄰點中均為最大或最小,則為極點;如某元素在所在行(或列)相鄰點中為最大,同時該元素在所在列(或行)相鄰點中為最小,則為鞍點。,5.2.2 多維數(shù)組作為函數(shù)參數(shù),多維數(shù)組作為參數(shù): 在作為函數(shù)的形式參數(shù)時,可以省略最高維(第一維) 。因為編譯器只要根據(jù)后面每一維(從第二維開始)的大小,就可計算數(shù)組每一個元素的存儲位置。 基于同樣的理由,也只能省略最高維。進一步考慮,對多維數(shù)組,編譯器不檢查邊界,其實只是不檢查最高維(第一維)的邊界,較低各維的大小是在控制之中的。 復(fù)合

14、類型只能對各元素逐個操作,不能整體操作。,5.2.2 多維數(shù)組作為函數(shù)參數(shù),【例5.5】矩陣轉(zhuǎn)置與矩陣相乘。 下標(biāo)作為參數(shù)傳遞。,缺陷與改進: 多維數(shù)組作為函數(shù)參數(shù),最高維可以不寫,但較低維必須明確標(biāo)出。這限定了二維數(shù)組的構(gòu)造,所以用二維數(shù)組進行矩陣運算很難表示成通用的算法。 既然二維數(shù)組使用一維數(shù)組方式存儲,則用一維數(shù)組加上行列信息傳遞,可不受數(shù)組構(gòu)造的限制。,5.3 指針與地址,5.3.1指針的概念,5.3.2 指針變量的賦值、初始化與簡單應(yīng)用,5.3.1 指針的概念,指針與間接訪問: 按變量的地址直接存取變量的方法稱為“直接訪問”方式。存貯變量的內(nèi)存空間的首地址稱為該變量的地址。 如果將

15、一個變量的地址放在另一個變量中,則存放地址的變量稱為指針(Pointer)型變量。這樣存取變量,也可以間接的由指針變量取得該變量的地址進行,稱為“間接訪問”方式。 由于指針變量中的值是另一個變量的地址,習(xí)慣上形象地稱為指針變量指向該變量。指針變量中的值也簡稱為指針,所以指針就是地址。,5.3.1 指針的概念,指針類型的區(qū)分: 指針類型可以按它指向的變量的類型區(qū)分?;绢愋秃头腔绢愋投加袑?yīng)的指針類型,包括類(class),甚至還有指針類型(指向指針的指針,二級指針)。,理由: 指針中只放變量首地址是不夠的,還要知道占多少內(nèi)存?數(shù)據(jù)又是怎樣組織的?整型數(shù)占4個字節(jié),浮點數(shù)占4個字節(jié),字符型占1

16、個字節(jié),寬字符占2個字節(jié);并且它們有各自不同的存儲組織方式。,5.3.1 指針的概念,指針類型變量定義: 存貯類型 類型 *變量名,*變量名; 這里*是一個定義變量為指針的說明符,而不是指針變量的一部分。 必須指出的是定義時每一個指針變量都需要一個指針變量說明符。例如: int *lp1,*lp2; 如果寫成 int *lp1,lp2; 則編譯器認(rèn)為lp2是整型變量,只有l(wèi)p1是指向整型變量的指針型變量。,5.3.2 指針變量的賦值、初始化與簡單應(yīng)用,指針變量的值 : 對指針決不可以任意賦一個內(nèi)存地址,只能取一個已經(jīng)分配了內(nèi)存的變量的地址賦給指針變量。 理由:指針變量中存放的是在內(nèi)存中可尋址的

17、變量或?qū)ο蟮氖椎刂?,而變量或?qū)ο蟮膬?nèi)存地址是由系統(tǒng)來分配的。程序員不能代替系統(tǒng)給變量分配內(nèi)存,當(dāng)然也就不能給指針變量隨意賦一個地址值。,5.3.2 指針變量的賦值、初始化與簡單應(yīng)用,與指針相關(guān)的運算符: “ 把指針變量P的初始置為0 xaf80,我們并不知道那個內(nèi)存單元放的是什么數(shù)據(jù),這在一般程序中是非常危險的。,訪問對象或結(jié)構(gòu)成員: 如果通過指向?qū)ο蠡蚪Y(jié)構(gòu)變量的指針變量來訪問其公有成員時,則只要在指針變量名后加箭頭號(箭頭操作符“-” ),再加公有成員名就可以了。,【例5.7】通過結(jié)構(gòu)指針來訪問結(jié)構(gòu)成員。,*C語言的指針容易失控,在C+中增加了引用類型,它具有指針的主要功能,但限制了靈活性,

18、使用更加安全。建議在函數(shù)參數(shù)傳遞中,能用“引用”時絕不用“指針”。,5.3.2 指針變量的賦值、初始化與簡單應(yīng)用,指針常量: 指針常量是固定指向一個對象的指針,即指針本身是常量: char ch=a,ch1=x; char * const ptr= /錯誤 ptr本身在初始化時所指向的地址是不可改變的,但它指向的目標(biāo)ch的值是可以改變的。,5.3.2 指針變量的賦值、初始化與簡單應(yīng)用,常量指針: 常量指針是指向“常量”的指針,即指針本身可以改指向別的對象,但不能通過該指針修改對象,該對象可以通過其他方式修改,常用于函數(shù)的參數(shù),以免誤改了實參。類似于在“運算符重載”一節(jié)中引用參數(shù)前加const。

19、 char ch=a,ch1=x; const char * ptr1= /正確,5.4 this 指針,問: 當(dāng)在對象的外部訪問該對象的公有成員時,必須指明是哪一個對象。但是當(dāng)我們用對象的成員函數(shù)來訪問本對象的成員時,在成員函數(shù)中只要給出成員名就可以實現(xiàn)對該對象成員的訪問。再進一步可用同一個類創(chuàng)建很多個對象,但它們共用同一份成員函數(shù)的代碼。既然是同一份代碼,那么成員函數(shù)又怎么知道是取哪一個對象的成員數(shù)據(jù)呢?,答: 當(dāng)調(diào)用一個成員函數(shù)時,系統(tǒng)自動產(chǎn)生一個隱藏的指針,這個指針稱為this指針,它始終指向產(chǎn)生這個調(diào)用的對象,并將該指針作為一個參數(shù)自動傳遞給該成員函數(shù)。這就是說,成員操作符總是要使用

20、的,只不過在對象內(nèi)是隱式的,而在對象外是顯式的。即在對象內(nèi)省略了this指針。,5.4 this 指針,this指針的實現(xiàn): 1改變類成員函數(shù)的定義,用附加參數(shù)this指針來定義每個成員函數(shù)。如: void Cgoods:RegisterGoods(Cgoods*this,char*nam, int amount,float price) strcpy(this-Name,name);this-Amount=amount; this-price=price; ,2每個類成員函數(shù)的調(diào)用,加上一個附加的實參被調(diào)用對象的地址。如: Car1.RegisterGoods ( String , numb

21、er , pr ); 改變?yōu)椋?RegisterGoods ( ,5.4 this 指針,this指針的使用: 通常this指針不必寫成顯式的,但是有時必須寫成顯式的,如在對復(fù)數(shù)類的賦值號重載中需要返回當(dāng)前調(diào)用的對象時: Complex ,靜態(tài)成員函數(shù)沒有this指針。因為普通成員函數(shù)雖然在物理上只有一份代碼,但在邏輯上都認(rèn)為一個對象有一份代碼,所以有this指針,而靜態(tài)成員函數(shù)在邏輯上也只有一份代碼,不屬于具體的對象,當(dāng)然沒有this指針,用指針表達聚合,在C+中表達聚合還沒有一個好辦法,一般可以采用指針。如課題組問題:教師建立一個數(shù)組;而課題組中有一個指針數(shù)組,數(shù)組元素指針指向參加本課題組

22、的教師。,5.5 數(shù)組與指針,5.5.1 數(shù)組名、指針和指針運算,5.5.2 指針作為函數(shù)參數(shù),5.5.1 數(shù)組名、指針和指針運算,數(shù)組名和指針的關(guān)系:,數(shù)組名被看作該數(shù)組的第一個元素在內(nèi)存中的首地址(僅在sizeof操作中例外,該操作給出數(shù)組所占內(nèi)存大?。?數(shù)組名在表達式中被自動轉(zhuǎn)換為一個指向數(shù)組第一個元素的指針常量。數(shù)組名中所放的地址是不可改變的,所以稱指針常量(即隱含說明“元素類型* const數(shù)組名”)。,數(shù)組名是指針,非常方便,但是卻丟失了數(shù)組另一個要素:數(shù)組的大小,即數(shù)組元素的數(shù)量。編譯器按數(shù)組定義時的大小分配內(nèi)存,但運行時(run time)對數(shù)組的邊界不加檢測。這會帶來無法預(yù)

23、知的嚴(yán)重錯誤。數(shù)組名指向的目標(biāo)是數(shù)組元素,而不是數(shù)組整體。,5.5.1 數(shù)組名、指針和指針運算,用指針訪問數(shù)組: C+提供根據(jù)數(shù)組的存儲地址訪問數(shù)組元素的方法。圖5.1中fibon是數(shù)組第一個元素的地址,所以*fibon是數(shù)組的第一個元素fibon0,而fibon+1是數(shù)組第二個元素的地址,*(fibon+1)是第二個元素fibon1本身。指針加1,則地址移動一個數(shù)組元素所占字節(jié)數(shù)。,數(shù)組實際訪問方式: C+語言的下標(biāo)運算符 是以指針作為操作數(shù)的,fiboni被編譯系統(tǒng)解釋為*(fibon+i),即表示為fibon所指(固定不可變)元素向后第i個元素。無論以下標(biāo)方式或指針方式存取數(shù)組元素時,系

24、統(tǒng)都是轉(zhuǎn)換為指針方法實現(xiàn)。,5.5.1 數(shù)組名、指針和指針運算,指針的算術(shù)運算和關(guān)系運算:,1. 指針變量與整型量的加減表示移動指針,以指向當(dāng)前目標(biāo)前面或后面的若干個位置的目標(biāo)。指針與整型量i的加減等于指針值(地址)與i*sizeof(目標(biāo)類型)積的加減,得出新的地址。,*運算結(jié)果并不表明那兒有一個指針?biāo)?guī)定的數(shù)據(jù)類型的變量,這稱作不對數(shù)組邊界做檢查。所以指針必須小心使用。,2. 只有當(dāng)兩個同類型的指針變量指向同一個數(shù)組時才可以進行減法運算,結(jié)果表示由第一個指針?biāo)冈氐降诙€指針?biāo)冈刂g的元素數(shù)量。這里數(shù)量算頭不算尾。,*兩個指針相加是毫無意義的。建立兩個指針間的指針,不能寫p=(p1+

25、p2)/2,必須寫p=p1+(p2-p1)/2。,5.5.1 數(shù)組名、指針和指針運算,3當(dāng)且僅當(dāng)兩個同類型指針變量指向同一數(shù)組中的元素時,可以用關(guān)系運算符,=,!=等進行比較,比較規(guī)則是指向后面元素的指針大,指向同一元素的相等。,指針同樣可以進行”+”,”-“運算,運算結(jié)果也是指向后一個或前一個數(shù)組元素。,*但是有”+”和”-”的表達式往往容易出錯,必須小心使用,如: y=*pfib+; 由于后”+”的優(yōu)先級高于”*”,所以該表達式等效于y=*(pfib+),又因是后”+”,所以y中取值為*pfib,而pfib增1后指向下一個元素。這條語句在C+中是常用的。千萬不可誤解為將pfib所指目標(biāo)增1

26、。,【例5.8】指針與數(shù)組相關(guān)的運算,演示怎樣訪問數(shù)祖,5.5.2 指針作為函數(shù)參數(shù),引用調(diào)用與指針傳值調(diào)用: C+中函數(shù)的參數(shù)的基本使用方法是傳值。為了彌補單純傳值的不足,以引用作為函數(shù)的參數(shù),從邏輯上講引用是別名,在函數(shù)中對參數(shù)的操作,就是對實參的操作,而在物理上是傳實參的地址。,將指針用作函數(shù)的參數(shù)時,傳的仍然是值,指針的值,這個值就是指針?biāo)赶虻淖兞炕驅(qū)ο蟮膬?nèi)存首地址,在物理上傳的是指針的值,在邏輯上講是把另一個變量的地址傳過去了,可以看作傳地址。 建議在函數(shù)參數(shù)傳遞中,能用“引用”時絕不用“指針”。,【例5.9】用指針代替引用實現(xiàn)兩數(shù)據(jù)的交換,5.5.2 指針作為函數(shù)參數(shù),指針作為返

27、回值: 函數(shù)的返回值也可以是指針。如希望返回多個值,可以用引用參數(shù)或指針參數(shù)來等效實現(xiàn),如果我們希望返回一個數(shù)組,并且這個數(shù)組生命期不在該函數(shù)中消亡,我們可以返回一個指向該數(shù)組的指針。,指針變量可以代替數(shù)組作為函數(shù)的參數(shù),而且更常見。在下一節(jié)C風(fēng)格字符串的庫函數(shù)中,總是用指向字符的指針取代字符數(shù)組作為形式參數(shù)。但是實參必須是字符數(shù)組名(字符串)或已指向字符串的指針。,5.6 字符串,5.6.1 C風(fēng)格字符串(選讀),5.6.2 標(biāo)準(zhǔn)的C+string類,5.6.3 自定義字符串類,5.6.1 C風(fēng)格字符串(選讀),回憶字符串: 字符串是用字符型數(shù)組存儲的,字符串要求其尾部以0作為結(jié)束標(biāo)志。如:

28、 char string =”C+ programming language”; 用sizeof 來測string長度為25個字節(jié),而實際串本身長度(含空格)為24個字節(jié),多出來的一個就是串結(jié)束符0(含0)。,指針與字符串: char *pstr=”C+ is a object_oriented language”; 這里絕不是建立了一個字符串*pstr,并用賦值號后的字符串常量給它賦初值。而是編譯器將字符串常量”C+ is a object language”的第一個字符的存儲地址賦給字符指針作初值。字符串常量是放在字符串常量區(qū)中,它不屬于指針pstr,反過來是pstr依附于它。,5.6.1

29、 C風(fēng)格字符串(選讀),用指針輸出字符串: C+不對數(shù)組的邊界進行檢測,但字符串有一個結(jié)束符0(全0),在程序運行時是可以知道實際串長度的。 設(shè)有定義int a10,如有語句: coutaendl; 則打印出a數(shù)組在內(nèi)存中的首地址,一個16進制的數(shù)。,如有語句: coutstring,pstrendl; 則輸出”C+ programming language ,C+ is a object_oriented language”;,5.6.1 C風(fēng)格字符串(選讀),字符串復(fù)制函數(shù) char *strcpy(char *s,const char ct)。返回值是指向復(fù)制后字符串中首字符的指針。 【

30、例5.10】字符串復(fù)制函數(shù) strcpy(),,字符串處理函數(shù): C+標(biāo)準(zhǔn)庫有很多字符串處理函數(shù),在頭文件中。,另一個復(fù)制函數(shù)可指定拷多少字符: char *strncpy(char *s,const char *ct,size_t n)。 字符串常用size_t代替整型,其說明方法如下: typedef int size_t; 用易讀性更好的數(shù)組長度size_t來代替通用的int。,5.6.1 C風(fēng)格字符串(選讀),2. 串連接函數(shù)char *strcat(char *s,const char *ct)。 將串ct復(fù)制到串s的后面,形成一個長串。例如: char str130=“張成”; c

31、har str220=“是電子系的學(xué)生”; strcat(str1,str2); 結(jié)果是str1中放的是“張成是電子系的學(xué)生”。,關(guān)鍵字typedef: typedef提供了產(chǎn)生新的類型標(biāo)識符的功能: typedef 類型 標(biāo)識符1,標(biāo)識符2; 其中可以是標(biāo)準(zhǔn)的類型名或是用戶自定義的類型名,還可以是已定義的新類型標(biāo)識符(如size_t)。,5.6.1 C風(fēng)格字符串(選讀),3. 字符串比較函數(shù)int strcmp(const char *cs,const char ct)。 兩字符串比較是按字典排序方法進行。兩個字符串從第一個字符比較起,如果相同,則比較第二個字符,依此類推,直到不同。哪個字符

32、串對應(yīng)的字符的ASCII碼值大,串就大。如果兩串直到結(jié)束符都相同,則一樣大。 若兩個字符串相等,則返回0;串cs 大,則返回正整數(shù);串ct大,則返回負(fù)整數(shù)。該函數(shù)也可很簡潔地表達如下: int strcmp(const char *cs,const char *ct) int k; while(k= *cs - * ct)= 0 ,4. 求字符串長度函數(shù)int strlen(const char *s)。 這里求出的串長度不包含串結(jié)束符在內(nèi)。而sizeof運算符包 括 結(jié)束符,還包括沒有使用的單元。,5.6.1 C風(fēng)格字符串(選讀),void指針及應(yīng)用: 稱無類型或泛型指針。任何類型的指針都可

33、以賦給void類型的指針變量,例如: int val=5; int *pi= 【例5.11】將字符指針強制轉(zhuǎn)換為泛型指針輸出字符串地址。,5.6.2 標(biāo)準(zhǔn)的C+string類,建議使用C+的string類,它重載了運算符,連接、索引和復(fù)制等操作不必使用函數(shù),使運算更加方便,而且不易出錯。string類包含在名字空間std中的頭文件。 #include using namespace std;,5.6.2 標(biāo)準(zhǔn)的C+string類,string類的使用方法: (1) string類有三個構(gòu)造函數(shù): string str; /調(diào)用默認(rèn)的構(gòu)造函數(shù),建立空串 string str(OK); /調(diào)用采用

34、C字符串初始化的構(gòu)造函數(shù) string str(str1); /調(diào)用復(fù)制構(gòu)造函數(shù),str是str1的副本 (2) string類字符元素的訪問比C字符串有所增強: stri /返回str中索引i處字符的引用,不查是否出界 str.at(i) /返回str中索引i處字符的引用,查是否出界,5.6.2 標(biāo)準(zhǔn)的C+string類,(3) string類重載了一些運算符,特別注意當(dāng)目標(biāo)串較小,無法容納新的字符串,系統(tǒng)會自動分配更多的空間給目標(biāo)串,不必顧慮出界: str1=str2; /str1成為str2的副本 str1+=str2; /str2的字符數(shù)據(jù)連接到str1的尾部 str1+str2; /

35、返回一個字符串,它將str2連接到str1的尾部 str1=str2; str1!=str2; /比較串是否相等,返回布爾值 str1str2; str1=str2; /基于字典序的比較,返回布爾值,5.6.2 標(biāo)準(zhǔn)的C+string類,(4) string類的輸入輸出。輸出與C風(fēng)格字符串同樣方便,使用插入運算符,代碼讀取的是以空白字符結(jié)束的字符串,輸入完整的字符串可用非成員函數(shù)getline,注意格式: getline(cin,str); /串以n結(jié)束 getline(cin,str,ch); /串以ch結(jié)束,5.6.2 標(biāo)準(zhǔn)的C+string類,(5) string類有一些常用的成員函數(shù)可

36、進行字符串處理: str.substr(pos,length1); /返回對象的一個子串,從pos位置起,長length1個字符 str.empty(); /查是否空串 str.insert(pos,str2); /將str2插入str的pos位置處 str.erase(pos,length1); /在str位置pos處起,刪除長度為length1的字串 str.find(str1); /返回str1首次在str中出現(xiàn)時的索引 str.find(str1,pos); /返回從pos處起str1首次在str中出現(xiàn)時的索引 str.length(str); /返回串長度,5.6.2 標(biāo)準(zhǔn)的C+st

37、ring類,(6) C字符串到string類對象是由構(gòu)造函數(shù)隱式自動進行,而string類對象到C字符串的轉(zhuǎn)換必須執(zhí)行顯示的類型轉(zhuǎn)換,應(yīng)調(diào)用成員函數(shù) str.c_str(); /將string類轉(zhuǎn)換為C風(fēng)格字符串,返回char* 在教材第4章習(xí)題4.9將人民幣類轉(zhuǎn)換為浮點數(shù),那是由轉(zhuǎn)換函數(shù)顯式完成的,反之由浮點數(shù)轉(zhuǎn)換為人民幣類由對應(yīng)的構(gòu)造函數(shù)隱式自動完成。這是一個規(guī)則。 (7) string類重載了插入和提取運算符,當(dāng)先輸入數(shù)值,后輸入串,不必先吸收回車,不會產(chǎn)生C風(fēng)格字符串那樣的空串問題(參見例9.3)。,5.6.2 標(biāo)準(zhǔn)的C+string類,【例5.12】判斷字符串是否為回文。 回文是指順

38、讀和反讀都一樣的串,這里不分大小寫,并濾去所有非字母字符,如: Madam,Im Adam. Golf,No Sir,prefer prison flog! 都是回文。,string類的優(yōu)點: string類有自己的構(gòu)造函數(shù)和析構(gòu)函數(shù),如果它作為類或結(jié)構(gòu)的成員,要記住它是成員對象,當(dāng)整個類對象建立和撤銷時,會自動調(diào)用作為成員對象的string字符串的構(gòu)造和析構(gòu)函數(shù)。,5.6.3 自定義字符串類,自定義字符串類:,class mystring char str21; int maxsize; int last; public: mystring() last=-1; maxsize=21; st

39、r0=0; mystring(char *s);mystring() void show() /如需重載,則請參見9.3節(jié),暫時未學(xué)到,替代方法是改用show()函數(shù) coutstrt; bool operator(mystring ,5.6.3 自定義字符串類,mystring: mystring(char *s)/當(dāng)C字符串過長,初始化時采用截尾處理 last=-1; maxsize=21; do last+; strlast=slast; while(slast!=0 ,5.6.3 自定義字符串類,bool mystring:operator(mystring ,可以用mystring代

40、替標(biāo)準(zhǔn)字符串類string,但注意串長限制在20個字符或10個漢字。在類定義中運算符和函數(shù)的重載是面向?qū)ο蟪绦蛟O(shè)計實現(xiàn)通用性的非常得力的工具。,5.7 多級指針與多維數(shù)組 (選讀),多級指針的概念: 多級指針可對應(yīng)于多維數(shù)組,這種指針變量中存的是另一個指針變量的地址,其說明如下: int val=10; int *ptr= /是多少級指針就有多少*號 這里val值為10,*ptr值也為10,*pptr的值和*ppptr的值均為10。(注意:這段文字中的*號是運算符,稱間接引用運算符。與定義中的*號意義不同,定義中的是指針說明符。),【例5.13】多級指針,5.7 多級指針與多維數(shù)組 (選讀),

41、指針兩要素: 指向數(shù)組(元素)類型的指針,與一維數(shù)組名是等效的: int a10, *pa =a; 則寫pa0 ,就是a0; *pa,即a0; *(pa+1) 和pa1 ,都代表a1。 指針有兩要素:地址和所指向目標(biāo)的數(shù)據(jù)類型。a 與pa 兩者都是一樣的,所以pa 可以替代a。,5.7 多級指針與多維數(shù)組 (選讀),指向一維數(shù)組的指針的定義如下: 數(shù)據(jù)類型 (* 指針變量名)n; 這里數(shù)組元素的個數(shù)n不可省略。因是指向指針的指針,稱二級指針。,二維數(shù)組與指針: 二維數(shù)組是數(shù)組元素為一維數(shù)組的數(shù)組,所以等效的指針類型應(yīng)該是指向一維數(shù)組的指針類型。如有: int x2d34=1,2,3,4,5,6

42、,7,8,9,10,11,12; int (*pt)4=x2d; 則指針pt 和x2d 是等效的。它們表示的首地址一樣,所指目標(biāo)類型也一樣,pt 可以代替x2d,就象pa代替a一樣。,指向行方向,x2d00,x2d12,x2d02,x2d03,x2d10,x2d11,x2d20,x2d01,x2d23,x2d21,x2d0,x2d+1(或pt+1),x2d22,x2d1,x2d2,x2d13,x2d(或pt),指向列方向,x2d+2(或pt+2),圖5.8 二維數(shù)組剖析,x2d指向的是一個由指針組成的數(shù)組,包括x2d0,x2d1和x2d2 。由此可見,存儲二維數(shù)組還必須保存一些訪問數(shù)組元素的輔

43、助信息,如:x2d0,x2d1和x2d2。 在這里x2d即 int main() int arrSIZE, i,high,low; for (i=0;ihigh) high=arri; if(arrilow) low=arri; couthighest value is highendl; coutlowest value is lowendl; return 0;,【例5.2】字符數(shù)組與字符數(shù)組相連接,void strcat(char s,char ct) int i=0,j=0; while (si!=0) i+; while (ctj!=0) si+=ctj+; si=0; void m

44、ain (void) char a40=李明; char b20=是東南大學(xué)學(xué)生; strcat(a,b); coutaendl;/打印字符數(shù)組a ,【例5.3】八皇后問題(選讀),首先要求沒有任何兩個皇后在棋盤的同一行,則可每一行安置一個皇后,第i 個皇后被安置在第i行上。可用數(shù)組queen8 中的每一個數(shù)組元素記錄一個皇后所在位置的列號,在安置的過程中只需考慮每兩個皇后不在同一列和同一對角線的問題。很明顯第i行皇后和第j行皇后在同一列的充要條件是: queeniqueenj 第i行皇后和第j行皇后在同一對角線的充要條件是: queeni-queenji-j 初始時將每一行的皇后都放在第0列

45、(即下標(biāo)為0的列), 以第0行皇后開始向下試探。設(shè)前 i-1 行的皇后已經(jīng)安排得互不攻擊,安排第i行的皇后,使之與前 i-1 行皇后也互不攻擊,可從第i行皇后的當(dāng)前位置開始向棋盤的右部搜索:,【例5.3】八皇后問題(選讀),1. 若queeni 8,說明在前 i-1 行皇后的當(dāng)前布局下,第i行皇后已經(jīng)無法安置。為此將第i行的皇后回歸到該行的開始列,回溯一行,考慮第i-1行皇后與前面的i-2個皇后都互不攻擊的下一位置。如果已回溯到i小于零的行,程序結(jié)束。 3. 若當(dāng)前安排好的皇后是在最后一行, 說明已找到八個皇后互不攻擊的一種布局,將這種布局輸出。然后將最后一個皇后右移一列,重新進行這個過程,以

46、便找出下一種布局。,【例5.3】八皇后問題(選讀),圖 5.2 八皇后問題的一個解,int total = 0; /方案計數(shù) int main() int queen8; int i, j, k; for (i=0;i8;i+) queeni = 0; /八皇后全放在第0列 for (i=1;) /首先安放第0行皇后 if(queeni8) /皇后還可調(diào)整 k=0; /檢查與第k個皇后是否互相攻擊 while(ki ,i+; /無沖突,安置下一行皇后 if(i8) continue; for(j=0;j8;j+) coutqueenj;/已完成,輸出結(jié)果 cout” ”; total+; /方

47、案數(shù)加1 if(total%5=0) coutendl; queen7+; /將第7個皇后右移一列,前7個不動 i=7; /此處是制造機會,如不成功則回溯,關(guān)鍵一步 else /當(dāng)前行皇后無法安置,回溯 queeni=0; /當(dāng)前行皇后回歸0列 i-; /回溯到前一行皇后 if(i0) /回溯到數(shù)組0行之前,結(jié)束 cout 總數(shù):totalendl; return 0; else queeni+; /前一行皇后右移一列,【例5.4】矩陣極點與鞍點,#include #include using namespace std; int mat88=0,3,5,7,11,,25,19,16,14;

48、int maxmin(int a,int b,int c) /判斷相鄰3元素中間元素是否最大或最小 if(ab /b為最大返回1 ,最小返-1,其他為0,int main (void) int i,j,k,l; for(i=1;i=6;i+) for(j=1;j=6;j+) k=maxmin(matij-1,matij,matij+1); if(k=0) continue; l=maxmin(mati-1j,matij,mati+1j); if(l=0) continue; if(k=1 ,【例5.4】矩陣極點與鞍點,【例5.5】矩陣轉(zhuǎn)置與矩陣相乘,void inverse(int 36, i

49、nt 63); /轉(zhuǎn)置矩陣 void multi(int 63, int 34, int 64); /矩陣乘法 void output(int 64); /矩陣輸出 Int main() int middle63, result64; int matrix136=8,10,12,23,1,3,5,7,9,2,4,6, 34,45,56,2,4,6; int matrix234=3,2,1,0,-1,-2,9,8,7,6,5,4; inverse(matrix1,middle); multi(middle,matrix2,result); output(result); return 0;,【例

50、5.5】矩陣轉(zhuǎn)置與矩陣相乘,void inverse(int matrix136,int middle63) /轉(zhuǎn)置矩陣 int i,j; for (i=0;i3;i+) for (j=0;j6;j+) middleji=matrix1ij; return; void multi(int middle63,int matrix234,int result64) int i,j,k; /矩陣乘法 for (i=0;i6;i+) for (j=0;j4;j+) resultij = 0; for (k=0;k3;k+) resultij+=middleik*matrix2kj; return; ,【例5.5】矩陣轉(zhuǎn)置與矩陣相乘,void output(int result64) /矩陣輸出 cout resultn; int I,j; for (i=0;i6;i+) for (j=0;j4;j+) cout setw(4)resultij ; coutn; return; ,【例5.6】指針變量的賦值,20,age2,18,age1,#include using namespace std; int main() int age1=18,age2=20,*p_age; p_age=,【例5.7】 指針變量簡單應(yīng)用,【例5.7】通

溫馨提示

  • 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)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論