課件播客語(yǔ)言入門_第1頁(yè)
課件播客語(yǔ)言入門_第2頁(yè)
課件播客語(yǔ)言入門_第3頁(yè)
課件播客語(yǔ)言入門_第4頁(yè)
課件播客語(yǔ)言入門_第5頁(yè)
已閱讀5頁(yè),還剩197頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、傳智播客C語(yǔ)言入門教程(7)講師:尹成 博客 /yincheng01微博 /yincheng8848 網(wǎng)址 C語(yǔ)言C+語(yǔ)言 傳智播客 高薪就業(yè) 2. 鏈表講解 3.棧,隊(duì)列,鏈表綜合學(xué)習(xí) 4.C語(yǔ)言實(shí)戰(zhàn) 5.C語(yǔ)言面試傳智播客C語(yǔ)言入門教程(7)大綱 1.編譯及預(yù)處理C語(yǔ)言課程概述6.傳智播客C/C+學(xué)院課程介紹 7.1編譯與預(yù)處理如果一個(gè)源程序由多個(gè)諸如A.c,B.h等的源文件組成,使用的編譯鏈接器是如何根據(jù)這些文件生成可執(zhí)行文件的?編譯鏈接的機(jī)理到底是什么,這是本章要學(xué)習(xí)的內(nèi)容。對(duì)C語(yǔ)言來(lái)說(shuō),除了掌握必要的語(yǔ)法機(jī)制外,學(xué)好預(yù)處理命令也是寫出高質(zhì)量代碼的前提。 7.1.1宏定義及編譯預(yù)處理定

2、義4宏宏替換預(yù)處理預(yù)處理是指在進(jìn)行編譯之前所作的處理,由預(yù)處理程序負(fù)責(zé)完成 用一個(gè)標(biāo)識(shí)符來(lái)表示一個(gè)字符串,稱為“宏”,被定義為“宏”的標(biāo)識(shí)符稱為“宏名”。 在編譯預(yù)處理時(shí),對(duì)程序中所有出現(xiàn)的“宏名”,都用宏定義中的字符串去代換,這稱為“宏代換”或“宏展開”; 7.1.2HelloWorld案例拓展很多示例代碼,實(shí)際上,哪怕是像Hello,World這樣簡(jiǎn)單的示例程序,都要經(jīng)過(guò)編輯、預(yù)處理、編譯、鏈接4個(gè)步驟,才能變成可執(zhí)行程序,鼠標(biāo)雙擊就彈出命令窗口,顯示“Hello,World”。這也是一般C語(yǔ)言程序的編譯流程,如所示。 7.1.3編輯編輯可能就是通常所說(shuō)的“寫代碼”,用集成開發(fā)工具也好,用

3、記事本也好,按C語(yǔ)言的語(yǔ)法規(guī)則組織一系列的源文件,主要有兩種形式,一種是.c文件,另一種是.h文件,也稱頭文件。 7.1.4預(yù)處理前面接觸到的“#include”和“#define”都屬于編譯預(yù)處理,C語(yǔ)言允許在程序中用預(yù)處理指令寫一些命令行。預(yù)處理器在編譯器之前根據(jù)指令更改程序文本。編譯器看到的是預(yù)處理器修改過(guò)的代碼文本,C語(yǔ)言的編譯預(yù)處理功能主要包括宏定義、文件包含和條件編譯3種。預(yù)處理器對(duì)宏進(jìn)行替換,并將所包含的頭文件整體插入源文件中,為后面要進(jìn)行的編譯做好準(zhǔn)備。 7.1.5編譯編譯器處理的對(duì)象是由單個(gè)c文件和其中遞歸包含的頭文件組成的編譯單元,一般來(lái)說(shuō),頭文件是不直接參加編譯的。編譯器

4、會(huì)將每個(gè)編譯單元翻譯成同名的二進(jìn)制代碼文件,在DOS和Windows環(huán)境下,二進(jìn)制代碼文件的后綴名為.obj,在Unix環(huán)境下,其后綴名為.o,此時(shí),二進(jìn)制代碼文件是零散的,還不是可執(zhí)行二進(jìn)制文件。錯(cuò)誤檢查大多是在編譯階段進(jìn)行的,編譯器主要進(jìn)行語(yǔ)法分析,詞法分析,產(chǎn)生目標(biāo)代碼并進(jìn)行代碼優(yōu)化等處理。為全局變量和靜態(tài)變量等分配內(nèi)存,并檢查函數(shù)是否已定義,如沒有定義,是否有函數(shù)聲明。函數(shù)聲明通知編譯器:該函數(shù)在本文件晚些時(shí)候定義,或者是在其他文件中定義。 7.1.6鏈接鏈接器將編譯得到的零散的二進(jìn)制代碼文件組合成二進(jìn)制可執(zhí)行文件,主要完成下述兩個(gè)工作,一是解析其他文件中函數(shù)引用或其他引用,二是解析庫(kù)

5、函數(shù)。舉例來(lái)說(shuō),某個(gè)程序由兩個(gè)c文件組成,分別為A.c、B.c,兩個(gè)c文件和其中遞歸包含的頭文件組成的兩個(gè)編譯單元,經(jīng)過(guò)預(yù)處理和編譯生成二進(jìn)制代碼文件A.obj和B.obj,假設(shè)A.c中調(diào)用了函數(shù)C,可函數(shù)C定義在B.c中,A.obj中實(shí)際上僅僅包括著對(duì)C函數(shù)的引用,其二進(jìn)制定義代碼需要從B.obj中提取,插入到A.obj的調(diào)用處,這個(gè)過(guò)程稱為函數(shù)解析(resolve),由鏈接器完成。不僅僅是函數(shù),變量(諸如有外部鏈接性的全局變量)也牽扯到解析的問題。當(dāng)B.c沒有定義函數(shù)C時(shí),編譯時(shí)不會(huì)產(chǎn)生錯(cuò)誤,但鏈接時(shí)卻會(huì)提示,有未解析的對(duì)象,據(jù)此可分析出問題出在編譯階段還是鏈接階段。 7.1.7程序錯(cuò)誤興

6、致勃勃地寫完程序,編譯鏈接,一大堆的錯(cuò)誤提示,不要沮喪,再優(yōu)秀的程序員也會(huì)犯錯(cuò),有人說(shuō),程序編寫的過(guò)程大部分的時(shí)間都是用在錯(cuò)誤調(diào)試上。有時(shí)為了排除一個(gè)小問題,可能會(huì)幾天幾夜地跟蹤代碼,正因?yàn)槿绱?,有人把問題找到并解決的剎那稱為“痛苦的幸福”。繼續(xù)說(shuō)明程序錯(cuò)誤前,有個(gè)觀點(diǎn)要說(shuō)明:沒有完美的程序,不存在沒有缺陷的程序,如果一個(gè)程序運(yùn)行很完美,那是因?yàn)樗娜毕莸浆F(xiàn)在還沒有被發(fā)現(xiàn)。同樣,軟件測(cè)試是為了發(fā)現(xiàn)程序中可能存在的問題,而不是證明程序沒有錯(cuò)誤。 7.1.8錯(cuò)誤分類錯(cuò)誤可分兩大類,一是程序書寫形式在某些方面不合C語(yǔ)言要求,稱為語(yǔ)法錯(cuò)誤,這種錯(cuò)誤將會(huì)由編譯器指明,是種比較容易修改的錯(cuò)誤,二是程序書寫

7、本身沒錯(cuò),編譯鏈接能夠完成,但輸出結(jié)果與預(yù)期不符,或著執(zhí)行著便崩潰掉,稱為邏輯錯(cuò)誤。細(xì)分下去,語(yǔ)法錯(cuò)誤又可分為編譯錯(cuò)誤和鏈接錯(cuò)誤,很明顯,編譯錯(cuò)誤就是在程序編譯階段出的錯(cuò)誤,而鏈接錯(cuò)誤就是在程序鏈接階段出的問題。 7.1.9編譯錯(cuò)誤如果文件中出現(xiàn)編譯錯(cuò)誤,編譯器將給出錯(cuò)誤信息,并指明錯(cuò)誤所在的行,提示用戶修改代碼,編譯錯(cuò)誤主要有兩類:(1)語(yǔ)法問題,缺少符號(hào),如缺分號(hào),缺括號(hào)等,符號(hào)拼寫不正確,一般來(lái)說(shuō),編譯器都會(huì)指明錯(cuò)誤所在行,但由于代碼是彼此聯(lián)系的,有時(shí)編譯器給出的信息未必正確。一般來(lái)說(shuō),源程序中出錯(cuò)位置要么就是編譯器提示位置,要么在提示位置之前,甚至是在前面很遠(yuǎn)的地方。另一個(gè)問題是有時(shí)一

8、個(gè)實(shí)際錯(cuò)誤會(huì)讓編譯器給出很多出錯(cuò)提示,所以,面對(duì)成百上千個(gè)錯(cuò)誤提示時(shí),不要害怕,沒準(zhǔn)修改一處代碼,所有的問題都解決了。(2)上下文關(guān)系有誤,程序設(shè)計(jì)中有很多彼此關(guān)聯(lián)的東西,比如變量要先創(chuàng)建再使用,有時(shí)編譯器會(huì)發(fā)現(xiàn)某個(gè)變量尚未定義,便會(huì)提示出錯(cuò)。這種情況有時(shí)是因?yàn)樽兞棵磳懹姓`,有時(shí)是因?yàn)榇_實(shí)忘了定義。除了錯(cuò)誤外,編譯器還會(huì)對(duì)程序中一些不合理的用法進(jìn)行警告(warning),盡管警告不耽誤程序編譯鏈接,但對(duì)警告信息不能掉以輕心,警告常常預(yù)示著隱藏很深的錯(cuò)誤,特別是邏輯錯(cuò)誤,應(yīng)當(dāng)仔細(xì)排查。 7.1.10鏈接錯(cuò)誤當(dāng)一個(gè)編譯單元中調(diào)用了庫(kù)函數(shù)或定義在其他編譯單元中的函數(shù)時(shí),在鏈接階段就需要從庫(kù)文件或其

9、他目標(biāo)文件中抽取該函數(shù)的二進(jìn)制代碼,以便進(jìn)行組合等一系列工作,當(dāng)函數(shù)名書寫錯(cuò)誤時(shí),鏈接器無(wú)法找到該函數(shù)對(duì)應(yīng)的代碼,便會(huì)提示出錯(cuò),指出名字未解析(unresolved)。一般來(lái)說(shuō),鏈接器給出的錯(cuò)誤提示信息是關(guān)乎函數(shù)名、變量名等的。 7.1.11邏輯錯(cuò)誤即使程序順利通過(guò)了編譯鏈接,也不是說(shuō)萬(wàn)事大吉,可以收工了,要檢查生成的可執(zhí)行程序,看其是否實(shí)現(xiàn)了所需的功能。實(shí)際上,運(yùn)行階段出現(xiàn)的邏輯錯(cuò)誤更難排查,更讓人頭疼,編譯錯(cuò)誤和鏈接錯(cuò)誤好歹有提示信息,但面對(duì)邏輯錯(cuò)誤,就像渾水摸魚??赡艹霈F(xiàn)的邏輯錯(cuò)誤有以下情況:與操作系統(tǒng)有關(guān)的操作,是否進(jìn)行了非法操作,如非法內(nèi)存訪問等。是否出現(xiàn)了死循環(huán),表現(xiàn)為長(zhǎng)時(shí)間無(wú)反應(yīng)

10、,假死,注意,長(zhǎng)時(shí)間無(wú)反應(yīng)并不一定都是死循環(huán),有的程序確實(shí)需要很長(zhǎng)時(shí)間,這種情況要仔細(xì)分析。程序執(zhí)行期間發(fā)生了一些異常,比如除數(shù)為0等,操作無(wú)法繼續(xù)進(jìn)行。程序能正確執(zhí)行,但結(jié)果不對(duì),此時(shí)應(yīng)檢查代碼的編寫是否合乎問題規(guī)范。 7.1.12排錯(cuò)排除錯(cuò)誤,有兩層含義,找到出錯(cuò)的代碼,修改該代碼。排錯(cuò)也有兩種形式,一是靜態(tài)排錯(cuò),編譯器和鏈接器發(fā)現(xiàn)的錯(cuò)誤基本都屬于這一類,通過(guò)觀察源程序便能確定問題所在并改正它。另一種是動(dòng)態(tài)排錯(cuò),邏輯錯(cuò)誤的發(fā)現(xiàn)和糾正都比較困難,要綜合考慮代碼、使用的數(shù)據(jù)和輸出結(jié)果的關(guān)聯(lián),仔細(xì)思考,嘗試更換數(shù)據(jù),觀察結(jié)果的改變,依此分析錯(cuò)誤可能存在的地方。如果還是不行,就要使用動(dòng)態(tài)檢查機(jī)制,

11、最基本的方法是“分而治之”,檢查程序執(zhí)行的中間狀態(tài),最常用的方法是在可能出錯(cuò)的地方插入一些輸出語(yǔ)句,讓程序輸出一些中間變量的值,確定可能出錯(cuò)的區(qū)域。此外,還可利用編譯環(huán)境提供的DEBUG工具,對(duì)程序進(jìn)行跟蹤、監(jiān)視和設(shè)斷點(diǎn)等,定位并排錯(cuò)。 7.1.13預(yù)處理命令宏定義預(yù)處理命令的引入是為了優(yōu)化程序設(shè)計(jì)環(huán)境,提高編程效率,合理使用預(yù)處理命令能使編寫的程序易于閱讀、修改、移植和調(diào)試,也有利于程序的模塊化設(shè)計(jì)。預(yù)處理命令必須獨(dú)占一行,并以#開頭,末尾不加分號(hào),以示與普通C語(yǔ)句的區(qū)別。原則上,預(yù)處理行可以寫在程序的任何位置,但推薦(或是慣常寫法)寫在程序文件的頭部。編譯器在對(duì)文件進(jìn)行實(shí)質(zhì)性的編譯之前,先

12、處理這些預(yù)處理行,這也是“預(yù)”字的含義。C語(yǔ)言的編譯預(yù)處理功能主要包括宏定義、文件包含和條件編譯3種。 7.1.14宏定義對(duì)宏已經(jīng)不再陌生,在字符常量一節(jié)中,已經(jīng)介紹過(guò)#define的用法,宏即是用#define語(yǔ)句定義的。宏定義是用宏名來(lái)表示一個(gè)字符串,在編譯預(yù)處理時(shí),對(duì)程序中所有出現(xiàn)的宏名,都用宏定義中的字符串來(lái)替換,稱為“宏代換”或“宏展開”。宏展開只是種簡(jiǎn)單的代換,字符串中可以包含任何字符,可以是常數(shù),也可以是表達(dá)式,預(yù)處理器進(jìn)行宏展開時(shí)并不進(jìn)行語(yǔ)法檢查。 7.1.15不帶參的宏定義不帶參數(shù)宏的一般定義形式為:#define 宏名 宏體宏名的命名規(guī)則與變量相同,一般習(xí)慣用大寫字母,以便

13、與變量區(qū)分,當(dāng)然,這并不是說(shuō)不允許使用小寫字母作為宏名。來(lái)看一個(gè)不帶參數(shù)宏的示例,從中學(xué)習(xí)一些宏的用法:#include /*使用printf要包含的頭文件*/#include #define SIDE 5#define SQUARE SIDE*SIDE/*宏定義允許嵌套*/#define PI 3.14159265 #define OUTPUT printf(Hello,Cn);void main(void)/*主函數(shù)*/int x=SQUARE;printf(x is %dn,x);if(PI4)OUTPUTprintf(PI is %f,PI);getchar();/*等待,按任意鍵繼續(xù)

14、*/ 7.1.16#define定義常量與宏常量#define定義的常量稱為符號(hào)常量,而const常量常稱靜態(tài)常量,相比#define,const有很多優(yōu)勢(shì),在實(shí)際使用時(shí),推薦采用const定義常量。對(duì)#define定義的符號(hào)常量,預(yù)處理器只是進(jìn)行簡(jiǎn)單的字符串替換,并不對(duì)其進(jìn)行類型檢查,而且會(huì)與程序中定義的同名變量沖突,如:#define num 10;void disp()int num;coutnum;編譯時(shí),預(yù)處理器會(huì)將disp函數(shù)中的語(yǔ)句“int num;”替換成“int 10”,若使用“const int num=10;”便不會(huì)出現(xiàn)這種問題。 7.1.17宏定義的規(guī)則1、預(yù)處理程序?qū)?/p>

15、宏定義不作語(yǔ)法檢查。2.宏定義不是普通C 語(yǔ)句,在行末不必加分號(hào),如加上分號(hào)則連分號(hào)也一起置換 例#define N 3Omain( ) int i; for(i=1;i=N;i+)printf(%dn,i); 7.1.18宏定義的規(guī)則宏名在源程序中若用引號(hào)括起來(lái),則預(yù)處理程序不對(duì)其作置換例#define PRICE 88main( ) printf(PRICE IS %d,PRICE);運(yùn)行結(jié)果如下:PRICE IS 88而不是 88 IS 88,即雙引號(hào)中的PRICE 沒有用88代替 同一個(gè)宏名不能重復(fù)定義如 #define PRICE 88和 #define PRICE 100 不能同時(shí)

16、出現(xiàn)在同一段程序中。 7.1.19宏定義的規(guī)則宏定義中的字符串不能替換用戶標(biāo)志符中與宏名相同的部分 7.4 #define PRICE 88main( ) int BOOK_PTICE=10;程序中的BOOK_PTICE中的PRICE不會(huì)被替換為BOOK_88。 7.1.20宏定義的規(guī)則宏定義允許嵌套,在宏定義的字符串中可以使用已經(jīng)定義的宏名。在宏展開時(shí)由預(yù)處理程序?qū)訉哟鷵Q。 #define M 10#define N 2 #define X M+100#define Y M*Nmain( ) printf(M=%dnN=%dnX=%dnY=%dn,M,N,X,Y);運(yùn)行結(jié)果是:M=10N=2

17、X=110Y=20在第三條宏定義#define X M+100語(yǔ)句中,用到了前面已經(jīng)定義過(guò)的宏M 7.1.21宏定義的規(guī)則宏定義一般寫在函數(shù)之外,其作用域?yàn)楹甓x命令起到源程序結(jié)束。如要終止其作用域可使用# undef命令。 #define N 100 main() #undef Nmax() N只在main函數(shù)中有效,在max中無(wú)效 7.1.22帶參數(shù)的宏定義語(yǔ)言有一類宏可以帶有參數(shù),在宏定義中的參數(shù)稱為形式參數(shù),在宏展開中的參數(shù)稱為實(shí)際參數(shù)。 帶參數(shù)的宏在編譯連接后,不僅要展開宏,而且要用實(shí)參去代換形參,在宏定義中的形參是標(biāo)識(shí)符,而宏展開中的實(shí)參可以是任意表達(dá)式。帶參宏定義的一般形式為:

18、#define 宏名(形參表) 字符串帶參宏展開的一般形式為: 宏名(實(shí)參表); 例: #define ADD(x) x*10 /*宏定義*/ a =ADD (3); /*宏展開*/在宏展開時(shí),用實(shí)參3去代替形參x,經(jīng)預(yù)處理宏展開后的語(yǔ)句為: a =3*10; 7.1.23帶參的宏定義#define CUBE(x) (x)* (x)* (x)main( ) double y; float z=10; int i; int j=2; y= CUBE (z); i= CUBE (j); printf(y=%8.1fni=%dn,y,i);運(yùn)行結(jié)果是:y=1000.0i=8執(zhí)行語(yǔ)句y= CUBE (

19、z);時(shí)自動(dòng)將z的值代替(x)* (x)* (x)中的x, 執(zhí)行語(yǔ)句i= CUBE (j);時(shí)自動(dòng)將j的值代替(x)* (x)* (x)中的x,并且將結(jié)果返回給CUBE,再分別賦值給y、i 7.1.24帶參的宏定義 類似函數(shù)的帶參數(shù)宏定義#include stdio.h#define exchange(a,b) int t;t=a;a=b;b=t;void main()int x=10;int y=20;printf(x=%d; y=%dn,x,y);exchange(x,y);printf(after exchange:x=%d; y=%dn,x,y);上述程序運(yùn)行結(jié)果如下:x=10; y=

20、20after exchange:x=20; y=10 7.1.25文件包含文件包含是C語(yǔ)言預(yù)處理的另一個(gè)重要功能,用“#include”來(lái)實(shí)現(xiàn),將一個(gè)源文件的全部?jī)?nèi)容包含到另一個(gè)源文件中,成為它的一個(gè)部分,文件包含的一般格式為:#include 或者#include “文件名”兩種形式的區(qū)別在于:使用尖括號(hào)表示在系統(tǒng)頭文件目錄中查找(由用戶在設(shè)置編程環(huán)境時(shí)設(shè)置),而不在源文件目錄中查找。使用雙引號(hào)則表示首先在當(dāng)前的源文件目錄中查找,找不到再到系統(tǒng)頭文件目錄中查找。#include “文件名”格式下,用戶可以顯式指明文件的位置,如:#include “D:ABC.h”#include “.X.

21、h”/*上級(jí)目錄下的X.h文件*/一個(gè)include命令智能包含一個(gè)文件,如果有多個(gè)文件要包含,則要使用多個(gè)include命令,不允許寫成下述形式:#include 7.1.26文件包含、一條include命令只能指定一個(gè)被包含文件,若有多個(gè)文件要包含,則需用多個(gè)include命令。不能這樣寫include 語(yǔ)句:#include “m1.h,m2.h” 或#include “m1.h”,”m2.h”而必須寫成:#include “m1.h” #include “m2.h”、文件包含允許嵌套,即在一個(gè)被包含的文件中又可以包含另一個(gè)文件。、文件包含語(yǔ)句中被包含的文件通常是以.h 結(jié)尾的頭文件,這

22、種頭文件中的內(nèi)容多為變量的定義、類型定義、宏定義、函數(shù)的定義或說(shuō)明,但被包含的文件也可以是以.c為擴(kuò)展名的語(yǔ)言源文件。 7.1.27條件編譯通過(guò)某些條件,控制源程序中的某段源代碼是否參加編譯,這就是條件編譯的功能,一般來(lái)說(shuō),所有源文件中的代碼都應(yīng)參加編譯,但有時(shí)候希望某部分代碼不參加編譯,應(yīng)用條件編譯可達(dá)到這以目的。條件編譯的基本形式為:#if 判斷表達(dá)式 語(yǔ)句段1#else 語(yǔ)句段2#endif#ifndef 標(biāo)識(shí)符 程序段1 #else 程序段2 #endif與第一種形式的區(qū)別是將“ifdef”改為“ifndef”。它的功能是,如果標(biāo)識(shí)符未被#define命令定義過(guò)則對(duì)程序段1進(jìn)行編譯,

23、否則對(duì)程序段2進(jìn)行編譯。這與第一種形式的功能正相反。 7.1.28編譯與預(yù)處理#if 常量表達(dá)式 程序段1 #else 程序段2 #endif它的功能是,如常量表達(dá)式的值為真(非0),則對(duì)程序段1 進(jìn)行編譯,否則對(duì)程序段2進(jìn)行編譯 7.1.29編譯及預(yù)處理小節(jié)討論了C語(yǔ)言程序編譯及預(yù)處理的相關(guān)內(nèi)容,C程序的編譯分編輯、預(yù)處理、編譯和鏈接幾個(gè)步驟,預(yù)處理指令是由預(yù)處理器負(fù)責(zé)執(zhí)行的,主要有頭文件包含、宏定義、條件編譯等,經(jīng)過(guò)預(yù)處理后,編譯器才開始工作,將每個(gè)編譯單元編譯成二進(jìn)制代碼文件,但此時(shí)分散的二進(jìn)制代碼文件中的變量和函數(shù)沒有分配到具體內(nèi)存地址,因而不能執(zhí)行,需要鏈接器將這些二進(jìn)制代碼文件、用

24、到的庫(kù)文件中相關(guān)代碼,系統(tǒng)相關(guān)的信息組合起來(lái),形成二進(jìn)制可執(zhí)行文件。掌握程序編譯鏈接的過(guò)程能幫助理解錯(cuò)誤的根源,提高調(diào)試的效率,是寫出高質(zhì)量代碼的必要條件。 實(shí)現(xiàn)宏定義加減乘除函數(shù),實(shí)現(xiàn)循環(huán)宏定義輸出字符串傳智播客,1234實(shí)現(xiàn)將C語(yǔ)言的語(yǔ)句漢化,類型漢化,以及變量層疊宏定義實(shí)現(xiàn)for循環(huán)1+2+3+n實(shí)現(xiàn)兩種模式,自然運(yùn)行的時(shí)候,不輸出調(diào)試語(yǔ)句,調(diào)試的時(shí)候輸出調(diào)試語(yǔ)句。實(shí)現(xiàn)條件編譯,實(shí)現(xiàn)多字節(jié)與unicode7.1.30編譯與預(yù)處理習(xí)題 7.2C語(yǔ)言鏈表什么是鏈表鏈表是一種常見的重要的數(shù)據(jù)結(jié)構(gòu)它是動(dòng)態(tài)地進(jìn)行存儲(chǔ)分配的一種結(jié)構(gòu)head12491249A135613561475B1475C102

25、11021D0頭指針各結(jié)點(diǎn)地址不連續(xù)各結(jié)點(diǎn)含有兩個(gè)部分表尾 7.2.1C語(yǔ)言鏈表鏈表是一種常見的重要的數(shù)據(jù)結(jié)構(gòu)它是動(dòng)態(tài)地進(jìn)行存儲(chǔ)分配的一種結(jié)構(gòu)鏈表必須利用指針變量才能實(shí)現(xiàn) 7.2.2C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單鏈表struct Student int num; float score; struct Student *next; a,b,c;1010189.510103901010785a結(jié)點(diǎn)b結(jié)點(diǎn)c結(jié)點(diǎn)a.next=&b;b.next=&c;numscorenext 7.2.3C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單鏈表建立簡(jiǎn)單的靜態(tài)鏈表 建立一個(gè)如圖所示的簡(jiǎn)單鏈表,它由3個(gè)學(xué)生數(shù)據(jù)的結(jié)點(diǎn)組成,要求輸出各結(jié)點(diǎn)中的數(shù)據(jù)。101018

26、9.510103901010785a結(jié)點(diǎn)b結(jié)點(diǎn)c結(jié)點(diǎn)numscorenext 7.2.4 C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單鏈表 建立簡(jiǎn)單的靜態(tài)鏈表解題思路:1010189.510103901010785a結(jié)點(diǎn)b結(jié)點(diǎn)c結(jié)點(diǎn)numscorenextheadhead=&a;a.next=&b;b.next=&c;NULLc.next=NULL; 7.2.5 C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單鏈表#include struct Student int num; float score; struct Student *next; 7.2.6C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單鏈表int main() struct Student a,b,c,*head,*p;

27、 a. num=10101; a.score=89.5; b. num=10103; b.score=90; c. num=10107; c.score=85; head=&a; a.next=&b; b.next=&c; c.next=NULL; p=head; do printf(“%ld%5.1fn”,p-num,p-score); p=p-next; while(p!=NULL); return 0; 7.2.7C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單鏈表 p=head; do printf(“%ld%5.1fn”,p-num,p-score); p=p-next; while(p!=NULL); return

28、 0;1010189.510103901010785a結(jié)點(diǎn)b結(jié)點(diǎn)c結(jié)點(diǎn)numscorenextheadNULLp相當(dāng)于p=&b; 7.2.8C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單鏈表 p=head; do printf(“%ld%5.1fn”,p-num,p-score); p=p-next; while(p!=NULL); return 0;1010189.510103901010785a結(jié)點(diǎn)b結(jié)點(diǎn)c結(jié)點(diǎn)numscorenextheadNULLp相當(dāng)于p=&b; 7.2.9C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單鏈表 p=head; do printf(“%ld%5.1fn”,p-num,p-score); p=p-next; while(

29、p!=NULL); return 0;1010189.510103901010785a結(jié)點(diǎn)b結(jié)點(diǎn)c結(jié)點(diǎn)numscorenextheadNULLp相當(dāng)于p=&c; 7.2.10C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表所謂建立動(dòng)態(tài)鏈表是指在程序執(zhí)行過(guò)程中從無(wú)到有地建立起一個(gè)鏈表,即一個(gè)一個(gè)地開辟結(jié)點(diǎn)和輸入各結(jié)點(diǎn)數(shù)據(jù),并建立起前后相鏈的關(guān)系。寫一函數(shù)建立一個(gè)有3名學(xué)生數(shù)據(jù)的單向動(dòng)態(tài)鏈表。 7.2.11C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表解題思路:定義3個(gè)指針變量:head,p1和p2,它們都是用來(lái)指向struct Student類型數(shù)據(jù)用malloc函數(shù)開辟第一個(gè)結(jié)點(diǎn),并使p1和p2指向它p1=p2=(struct Student*)ma

30、lloc(LEN);p1p2 7.2.12C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表解題思路:讀入一個(gè)學(xué)生的數(shù)據(jù)給p1所指的第一個(gè)結(jié)點(diǎn)p1scanf(%ld,%f,&p1-num,&p1-score);p21010189.5 7.2.13C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表解題思路:讀入一個(gè)學(xué)生的數(shù)據(jù)給p1所指的第一個(gè)結(jié)點(diǎn)使head也指向新開辟的結(jié)點(diǎn)headp1p2scanf(%ld,%f,&p1-num,&p1-score);1010189.5 7.2.14C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表解題思路:再開辟另一個(gè)結(jié)點(diǎn)并使p1指向它,接著輸入該結(jié)點(diǎn)的數(shù)據(jù)headp1p21010189.5 7.2.15C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表解題思路:再開辟另一個(gè)結(jié)點(diǎn)并使p

31、1指向它,接著輸入該結(jié)點(diǎn)的數(shù)據(jù)headp1p21010189.5p1=(struct Student*)malloc(LEN);scanf(%ld,%f,&p1-num,&p1-score);1010390 7.2.16C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表解題思路:使第一個(gè)結(jié)點(diǎn)的next成員指向第二個(gè)結(jié)點(diǎn),即連接第一個(gè)結(jié)點(diǎn)與第二個(gè)結(jié)點(diǎn)使p2指向剛才建立的結(jié)點(diǎn)headp1p21010189.5p2-next=p1;1010390 7.2.17C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表解題思路:使第一個(gè)結(jié)點(diǎn)的next成員指向第二個(gè)結(jié)點(diǎn),即連接第一個(gè)結(jié)點(diǎn)與第二個(gè)結(jié)點(diǎn)使p2指向剛才建立的結(jié)點(diǎn)headp1p21010189.5p2-next=p

32、1;1010390p2=p1; 7.2.18C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表解題思路:再開辟另一個(gè)結(jié)點(diǎn)并使p1指向它,接著輸入該結(jié)點(diǎn)的數(shù)據(jù)headp1p21010189.51010390 7.2.19C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表解題思路:再開辟另一個(gè)結(jié)點(diǎn)并使p1指向它,接著輸入該結(jié)點(diǎn)的數(shù)據(jù)headp1p21010189.51010390p1=(struct Student*)malloc(LEN);scanf(%ld,%f,&p1-num,&p1-score);1010785 7.2.20C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表解題思路:使第二個(gè)結(jié)點(diǎn)的next成員指向第三個(gè)結(jié)點(diǎn),即連接第二個(gè)結(jié)點(diǎn)與第三個(gè)結(jié)點(diǎn)使p2指向剛才建立的結(jié)點(diǎn)head

33、p1p21010189.510103901010785p2-next=p1; 7.2.21C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表解題思路:使第二個(gè)結(jié)點(diǎn)的next成員指向第三個(gè)結(jié)點(diǎn),即連接第二個(gè)結(jié)點(diǎn)與第三個(gè)結(jié)點(diǎn)使p2指向剛才建立的結(jié)點(diǎn)headp1p21010189.510103901010785p2-next=p1;p2=p1; 7.2.22C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表解題思路:再開辟另一個(gè)結(jié)點(diǎn)并使p1指向它,接著輸入該結(jié)點(diǎn)的數(shù)據(jù)headp1p21010189.5101039010107850 7.2.23C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表解題思路:再開辟另一個(gè)結(jié)點(diǎn)并使p1指向它,接著輸入該結(jié)點(diǎn)的數(shù)據(jù)headp1p21010189.5101

34、039010107850p1=(struct Student*)malloc(LEN);scanf(%ld,%f,&p1-num,&p1-score); 7.2.24C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表解題思路:輸入的學(xué)號(hào)為0,表示建立鏈表的過(guò)程完成,該結(jié)點(diǎn)不應(yīng)連接到鏈表中headp1p21010189.5101039010107850NULLp2-next=NULL; 7.2.25C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表#include #include #define LEN sizeof(struct Student)struct Student long num; float score; struct Student *n

35、ext;int n; 7.2.26C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表struct Student *creat(void) struct Student *head,*p1,*p2; n=0; p1=p2=( struct Student*) malloc(LEN); scanf(“%ld,%f”,&p1-num,&p1-score); head=NULL; while(p1-num!=0) n=n+1; if(n=1) head=p1; else p2-next=p1; p2=p1; p1=(struct Student*)malloc(LEN); scanf(“%ld,%f”,&p1-num,&p1-sc

36、ore); p2-next=NULL; return(head);p1總是開辟新結(jié)點(diǎn)p2總是指向最后結(jié)點(diǎn)用p2和p1連接兩個(gè)結(jié)點(diǎn) 7.2.27C語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)鏈表int main() struct Student *pt; pt=creat(); printf(“nnum:%ldnscore:%5.1fn”, pt-num,pt-score); return 0; 7.2.28C語(yǔ)言實(shí)現(xiàn)鏈表輸出輸出鏈表編寫一個(gè)輸出鏈表的函數(shù)print。100167.5100387100599NULLp 7.2.29C語(yǔ)言鏈表輸出解題思路:輸出p所指的結(jié)點(diǎn)使p后移一個(gè)結(jié)點(diǎn)p100167.5100387100599

37、NULLprintf(%ld %5.1fn,p-num,p-score); 7.2.30C語(yǔ)言鏈表輸出100167.5100387100599NULLp=p-next;解題思路:輸出p所指的結(jié)點(diǎn)使p后移一個(gè)結(jié)點(diǎn)printf(%ld %5.1fn,p-num,p-score);p 7.2.31 C語(yǔ)言鏈表輸出100167.5100387100599NULLp=p-next;解題思路:輸出p所指的新結(jié)點(diǎn)使p后移一個(gè)結(jié)點(diǎn)printf(%ld %5.1fn,p-num,p-score);p 7.2.32 C語(yǔ)言鏈表輸出100167.5100387100599NULLp=p-next;解題思路:輸出p所

38、指的新結(jié)點(diǎn)使p后移一個(gè)結(jié)點(diǎn)printf(%ld %5.1fn,p-num,p-score);p相當(dāng)于p=NULL; 7.2.33C語(yǔ)言鏈表輸出void print(struct Student *p) printf(nThese %d records are:n,n); if(p!=NULL) do printf(%ld %5.1fn, p-num,p-score); p=p-next; while(p!=NULL); 7.2.34C語(yǔ)言鏈表數(shù)組對(duì)應(yīng)著一個(gè)連續(xù)存儲(chǔ)的內(nèi)存塊,將同類型的元素一個(gè)個(gè)地排列起來(lái),是組織數(shù)據(jù)的很好的手段,聲明數(shù)組時(shí)需要告訴編譯器數(shù)組的大小(即元素的個(gè)數(shù)),以便開辟足夠大

39、小的內(nèi)存,但解決實(shí)際問題時(shí),元素的個(gè)數(shù)常常是不確定的,此時(shí)該如何聲明數(shù)組呢?如果指定的數(shù)組太小而實(shí)際數(shù)據(jù)太多,無(wú)法滿足要求,可如果指定的數(shù)組太大而實(shí)際卻用不了那么多,又會(huì)造成內(nèi)存浪費(fèi)。在這種背景下,有人提出用鏈表來(lái)存儲(chǔ)數(shù)據(jù),像用線串珠子一樣,元素不一定需要連續(xù)的內(nèi)存空間,只要在需要存儲(chǔ)數(shù)據(jù)時(shí),再申請(qǐng)存儲(chǔ)空間(動(dòng)態(tài)申請(qǐng)內(nèi)存空間或棧分配)即可,并采用指針將數(shù)據(jù)一個(gè)一個(gè)鏈接起來(lái),稱為鏈表,如所示: 7.2.35鏈表的結(jié)構(gòu)鏈表元素常稱為鏈表結(jié)點(diǎn),每一個(gè)結(jié)點(diǎn)是一個(gè)結(jié)構(gòu)體,包含兩個(gè)域:數(shù)據(jù)域和指針域。數(shù)據(jù)域保存數(shù)據(jù),指針域連接該結(jié)點(diǎn)到下一個(gè)結(jié)點(diǎn)。結(jié)點(diǎn)類型可以相同,也可不同,當(dāng)結(jié)點(diǎn)類型相同時(shí),稱為同質(zhì)鏈表,

40、否則,稱為異質(zhì)鏈表,在實(shí)際應(yīng)用中,常用的是同質(zhì)鏈表。每一個(gè)結(jié)點(diǎn)占用一塊存儲(chǔ)單元,結(jié)點(diǎn)的增減都十分容易,當(dāng)要在鏈表中增加一個(gè)結(jié)點(diǎn)時(shí),可動(dòng)態(tài)地為該結(jié)點(diǎn)分配一個(gè)存儲(chǔ)單元;當(dāng)要在鏈表中刪除一個(gè)結(jié)點(diǎn)時(shí),也可釋放該結(jié)點(diǎn)的存儲(chǔ)單元。就所示的鏈表來(lái)說(shuō),如果將該鏈表比作一串珠子,頭結(jié)點(diǎn)HEAD就是繩頭,找珠子就要從頭結(jié)點(diǎn)開始,頭結(jié)點(diǎn)指向的結(jié)點(diǎn)A是鏈表的第1個(gè)數(shù)據(jù)結(jié)點(diǎn),也就是第1顆珠子,A中不僅有數(shù)據(jù)域,還包含指向下一結(jié)點(diǎn)B的指針,依此類推,順藤摸瓜,即可遍歷整個(gè)鏈表。頭結(jié)點(diǎn)的數(shù)據(jù)域可以不包含任何信息,也可以存儲(chǔ)諸如元素個(gè)數(shù)等附加信息,或者干脆用一個(gè)指針代替頭結(jié)點(diǎn),如果鏈表為空,頭結(jié)點(diǎn)的指針域?yàn)榭铡?7.2.36

41、創(chuàng)建鏈表過(guò)程鏈表的建立一般是指先建立一個(gè)空鏈表,而后一個(gè)個(gè)地將元素插在隊(duì)尾。 7.2.37鏈表的插入顧名思義,插入即是往鏈表中加入一個(gè)新結(jié)點(diǎn),使鏈表變長(zhǎng)。受鏈表插入位置的影響,將一個(gè)元素插入鏈表有表頭,表尾,表中: 7.2.38鏈表刪除節(jié)點(diǎn)刪除幾乎可以看成是結(jié)點(diǎn)插入的逆操作,將到換一個(gè)順序即可:如果刪除的是第1個(gè)數(shù)據(jù)結(jié)點(diǎn),即從到,則應(yīng)使head指針指向E1,同時(shí)釋放掉Einsert申請(qǐng)的動(dòng)態(tài)內(nèi)存。如果刪除的是中間結(jié)點(diǎn),即從到,則只需讓E2-next指向Einsert-next,同時(shí),釋放掉Einsert占據(jù)的動(dòng)態(tài)內(nèi)存。如果刪除的尾結(jié)點(diǎn),即從到,只需讓E1-next為NULL,同時(shí)釋放掉Eins

42、ert占據(jù)的動(dòng)態(tài)內(nèi)存。 7.2.39鏈表逆置所謂鏈表的逆置,是指“頭變尾,尾變頭”,將原來(lái)的“ABCD”變成“DCBA”,先從單鏈表模型來(lái)看,如: 7.2.40鏈表銷毀在鏈表使用完畢后,需將其銷毀,回收所分配的內(nèi)存。由于是整體銷毀,實(shí)現(xiàn)起來(lái)比結(jié)點(diǎn)的刪除簡(jiǎn)單,可以采取如下策略:每次刪除第1個(gè)結(jié)點(diǎn)后面的結(jié)點(diǎn),最后再刪除頭結(jié)點(diǎn),這樣即可實(shí)現(xiàn)整個(gè)鏈表的銷毀。僅僅刪除第1個(gè)結(jié)點(diǎn)并不意味著整個(gè)鏈表被刪除掉了,鏈表是一個(gè)結(jié)點(diǎn)一個(gè)結(jié)點(diǎn)建立起來(lái)的 ,所以,銷毀它也必須一個(gè)結(jié)點(diǎn)一個(gè)結(jié)點(diǎn)地刪除才行。編寫鏈表銷毀的函數(shù)如下:void freeAll(STU* head)STU* p=NULL,*q=NULL;p=he

43、ad;while(p-next!=NULL)q=p-next;p-next=q-next;/*刪除結(jié)點(diǎn)*/free(q);/*釋放內(nèi)存*/free(head);/*釋放第1個(gè)結(jié)點(diǎn)所占內(nèi)存*/ 7.2.41鏈表與數(shù)組的比較數(shù)組鏈表鏈表與數(shù)組的比較.內(nèi)存中按照順序存放尋址容易大小固定刪除時(shí)需要很多移動(dòng)內(nèi)存中按照指針鏈?zhǔn)酱娣艑ぶ沸枰h(huán)大小可變查找時(shí)需要很多移動(dòng)啥時(shí)候用數(shù)組,啥時(shí)候用鏈表.各個(gè)不同 編寫代碼實(shí)現(xiàn)鏈表的查找某個(gè)元素是否存在1234 鏈表插入一個(gè)數(shù)據(jù) 編碼實(shí)現(xiàn)鏈表的逆置合并有序鏈表7.2.42鏈表習(xí)題 7.3棧,隊(duì)列,鏈表綜合學(xué)習(xí)鏈表、棧和隊(duì)列。鏈表支持的操作比較多,可以在鏈表中間自由地

44、刪除和插入元素,而棧和隊(duì)列的操作受到了一定程度的限制,對(duì)棧而言,只能在棧頂一端進(jìn)行元素的插入和刪除,而隊(duì)列只允許在一段插入,在另外一端刪除元素。數(shù)據(jù)結(jié)構(gòu)是合理組織數(shù)據(jù)的手段,掌握數(shù)據(jù)結(jié)構(gòu),能使代碼組織清晰,程序質(zhì)量高,易讀易維護(hù)。 7.3.1循環(huán)鏈表和前面介紹的單鏈表一樣,循環(huán)鏈表是一種鏈?zhǔn)降拇鎯?chǔ)結(jié)構(gòu),不同的是,循環(huán)鏈表的最后一個(gè)結(jié)點(diǎn)的指針是指向該循環(huán)鏈表第1個(gè)結(jié)點(diǎn)的,也就是說(shuō),頭尾相加構(gòu)成一個(gè)環(huán)形結(jié)構(gòu)。循環(huán)鏈表和單鏈表的操作基本一致,有兩點(diǎn)需要特別注意:(1)新建循環(huán)鏈表時(shí),必須使最后一個(gè)結(jié)點(diǎn)的指針指向第1個(gè)結(jié)點(diǎn),而不是像單鏈表一樣對(duì)其賦值為NULL。(2)在判斷是否達(dá)到鏈表尾部時(shí),是判斷該

45、結(jié)點(diǎn)指針域是否指向第1個(gè)結(jié)點(diǎn),而不是像單鏈表一樣判斷其是否為NULL。 7.3.2雙鏈表雙鏈表與單鏈表的相似,是對(duì)單鏈表的改進(jìn)。在單鏈表中,每個(gè)結(jié)點(diǎn)指向下一個(gè)結(jié)點(diǎn)(后繼結(jié)點(diǎn)),需要操作時(shí),需要從鏈表頭開始查找。雙鏈表對(duì)結(jié)點(diǎn)的結(jié)構(gòu)進(jìn)行了改進(jìn),使其既包含一個(gè)指向下一結(jié)點(diǎn)(后繼結(jié)點(diǎn))的指針,也包含一個(gè)指向上一結(jié)點(diǎn)(前驅(qū)結(jié)點(diǎn))的指針,仍然以前面的student結(jié)構(gòu)為例,要將其作為雙鏈表的結(jié)點(diǎn),可改寫為:struct student/*定義結(jié)構(gòu)student*/int num;/*學(xué)號(hào)*/int score;/*成績(jī)*/struct student* next;/*指向后繼結(jié)點(diǎn)指針*/struct st

46、udent* prev;/*指向前驅(qū)結(jié)點(diǎn)指針*/; 7.3.3棧棧是種“先入后出”的結(jié)構(gòu),打個(gè)比方,棧相當(dāng)于放餐具的帶底木桶,而數(shù)據(jù)相當(dāng)于一個(gè)個(gè)的盤子,刷完的盤子一個(gè)個(gè)摞起來(lái)放在桶里,用盤子時(shí)就一個(gè)個(gè)從桶中取出。很容易理解,最先刷好的盤子會(huì)放在桶底,此時(shí),只有上面的盤子用光了才會(huì)將其拿出來(lái),這就是所謂的先入后出FILO(First In Last Out),等價(jià)的說(shuō)法是后入先出。一個(gè)棧有以下要素:棧底(表示棧的開始位置,木桶的底部),棧頂(當(dāng)前數(shù)據(jù)已經(jīng)排放在什么位置了,當(dāng)前盤子摞了多高了),不含元素的棧稱為空棧。形象的示意如: 7.3.4順序棧與鏈?zhǔn)綏8鶕?jù)元素儲(chǔ)存方式的不同,可以將棧分為順序棧

47、和鏈?zhǔn)綏深悾海?)順序棧利用一組連續(xù)的內(nèi)存單元依次存放自棧底到棧頂?shù)臄?shù)據(jù),同時(shí),用一個(gè)指針top只是棧頂?shù)奈恢茫贑語(yǔ)言中,這可用數(shù)組來(lái)實(shí)現(xiàn),一般是先開辟一塊區(qū)域,在編程中可根據(jù)需要再對(duì)此區(qū)域進(jìn)行調(diào)整。(2)鏈?zhǔn)綏f準(zhǔn)綏5慕Y(jié)構(gòu)與鏈表類似,如所示,其中,top為棧頂指針,始終指向棧頂元素,棧頂元素的指針指向下一個(gè)元素,依此類推,直到棧底,棧底元素的指針區(qū)域?yàn)榭杖绻鹴op為空,表示該棧是個(gè)空棧。 7.3.5堆棧的操作對(duì)棧元素的操作有一定限制,不允許隨意訪問棧中間的元素,只允許訪問棧頂元素,對(duì)棧的操作有以下幾種:判斷棧是否為空,判斷棧是否已滿(只針對(duì)順序棧),將一個(gè)元素壓入棧,從棧中彈出一個(gè)元素,

48、銷毀一個(gè)棧(或稱清空一個(gè)棧)。判斷棧是否為空相對(duì)來(lái)說(shuō)比較簡(jiǎn)單,只要判斷下top指針是否為NULL即可,下面給出棧的使用范例,如: 7.3.6函數(shù)與棧在系統(tǒng)中,棧有著重要的應(yīng)用,舉函數(shù)調(diào)用為例,在C語(yǔ)言中,調(diào)用函數(shù)與被調(diào)用函數(shù)之間的連接和信息交換也是由編譯程序通過(guò)棧來(lái)完成的。當(dāng)在函數(shù)A中調(diào)用函數(shù)B時(shí),函數(shù)A稱調(diào)用函數(shù)而函數(shù)B稱被調(diào)用函數(shù),在運(yùn)行函數(shù)B之前,有以下工作要完成:保存現(xiàn)場(chǎng),將參數(shù)、返回地址等信息傳遞給函數(shù)B。為函數(shù)B中的局部變量分配存儲(chǔ)空間。將程序流程轉(zhuǎn)到函數(shù)B的入口處。當(dāng)函數(shù)B執(zhí)行完畢返回時(shí),要完成:保存函數(shù)B輸出結(jié)果。釋放為函數(shù)B中局部變量分配的內(nèi)存。依照保存的返回地址將程序流程轉(zhuǎn)

49、到調(diào)用函數(shù)A中。 7.3.7鏈表銷毀日常生活中,去銀行取款、火車站買票等都需要排隊(duì),隊(duì)列這個(gè)名詞大家一定不會(huì)陌生,和棧不同,隊(duì)列的特點(diǎn)是“先到先辦”FIFO(First In First Out),可將隊(duì)列形象地比作管道,如所示: 用隊(duì)列檢測(cè)一下回文數(shù)1234 實(shí)現(xiàn)雙鏈表,實(shí)現(xiàn)查找,刪除,添加節(jié)點(diǎn),逆序,以及兩個(gè)鏈表歸并排序,可能存在相同的節(jié)點(diǎn)要?jiǎng)h掉,并進(jìn)行排序 用棧實(shí)現(xiàn)進(jìn)制轉(zhuǎn)換用棧來(lái)實(shí)現(xiàn)數(shù)學(xué)表達(dá)式解析 實(shí)現(xiàn)一個(gè)可以拓展的存儲(chǔ)結(jié)構(gòu)鏈表,實(shí)現(xiàn)查找,刪除,添加節(jié)點(diǎn),逆序,以及2鏈表歸并排序,可能存在相同的節(jié)點(diǎn)7.3.8鏈表,隊(duì)列,棧習(xí)題 項(xiàng)目實(shí)踐算法 信息處理 游戲 安全案例實(shí)踐案例實(shí)踐案例實(shí)踐案

50、例實(shí)踐7.4C語(yǔ)言實(shí)戰(zhàn) 自頂向下,逐步求精問題所在問題分析問題分解設(shè)計(jì)邏輯與封裝逐步實(shí)現(xiàn)123457.4.1C語(yǔ)言設(shè)計(jì)規(guī)則 7.4.2面向過(guò)程的編程方法 入口出口面向過(guò)程的編程方法傳入數(shù)據(jù)傳出結(jié)果對(duì)單個(gè)模塊而言,只有一個(gè)入口,一個(gè)出口,是一種從上到下的流程式方法,減少了模塊的相互聯(lián)系 使模塊可作為插件或積木使用,降低程序的復(fù)雜性,提高可靠性面向過(guò)程 編寫高質(zhì)量的C程序 設(shè)計(jì)規(guī)則設(shè)計(jì)理念封裝可復(fù)用7.4.3C語(yǔ)言設(shè)計(jì)規(guī)則 耦合度,是指模塊之間相互依賴性大小的度量,耦合度越小,模塊的相對(duì)獨(dú)立性越大。內(nèi)聚度,是指模塊內(nèi)各成份之間相互依賴性大小的度量,內(nèi)聚度越大,模塊各成份之間聯(lián)系越緊密,其功能越強(qiáng)。

51、AmericaEuropeAsia巴西美國(guó)非洲俄羅斯澳大利亞內(nèi)聚耦合7.4.4實(shí)現(xiàn)高內(nèi)聚與低耦合 案例實(shí)現(xiàn)五子棋案例拓展如何實(shí)現(xiàn)一個(gè)連連看,俄羅斯方塊游戲3D游戲引擎信息安全信息系統(tǒng) 案例實(shí)現(xiàn)通訊錄 案例拓展實(shí)現(xiàn)火車票訂票系統(tǒng),實(shí)現(xiàn)理財(cái)系統(tǒng) 案例實(shí)現(xiàn)傳智播客教主黎活明大戰(zhàn)企業(yè)面試官 案例拓展實(shí)現(xiàn)你自己夜闖飛鵬幫,大戰(zhàn)洛陽(yáng)城,浴血五雷塔 案例實(shí)現(xiàn)C語(yǔ)言實(shí)現(xiàn)數(shù)據(jù)加密解密 案例實(shí)現(xiàn)C語(yǔ)言實(shí)現(xiàn)自我復(fù)制,自殺 案例拓展-如何跨平臺(tái)實(shí)現(xiàn)-脫離Windows7.4.5項(xiàng)目實(shí)戰(zhàn) 7.5 100經(jīng)典C語(yǔ)言基本筆試題檢驗(yàn)?zāi)闱懊鎸W(xué)習(xí)的效果好壞,就看你是否能夠通過(guò)世界五百?gòu)?qiáng)嚴(yán)酷的C語(yǔ)言考核,不過(guò)五百?gòu)?qiáng)很有挑戰(zhàn),你先搞

52、定基礎(chǔ)的面試題100題。面試筆試機(jī)試檢驗(yàn)?zāi)闶欠裢P(guān)100條經(jīng)典C語(yǔ)言筆試題目題目類型基本數(shù)據(jù)類型的考察(1-4)數(shù)組、指針、內(nèi)存、結(jié)構(gòu)體??键c(diǎn)(5-28) 宏、頭文件、關(guān)鍵字的考察(29-54)程序閱讀、改錯(cuò)(55-75)編程練習(xí)(76-100) 100條經(jīng)典C語(yǔ)言筆試題目1、請(qǐng)?zhí)顚?bool , float, 指針變量 與“零值”比較的 if 語(yǔ)句。 提示:這里“零值”可以是 0, 0.0 , FALSE 或者“空指針” 。例如 int 變量 n 與“零值”比較的 if 語(yǔ)句為: if ( n = 0 ) if ( n != 0 ) 以此類推。 100條經(jīng)典C語(yǔ)言筆試題目(1)請(qǐng)寫出 boo

53、l flag 與“零值”比較的 if 語(yǔ)句: 【標(biāo)準(zhǔn)答案】if ( flag ) if ( !flag )100條經(jīng)典C語(yǔ)言筆試題目(2)請(qǐng)寫出 float x 與“零值”比較的 if 語(yǔ)句: 【標(biāo)準(zhǔn)答案】 const float EPSINON = 0.00001; if (x = - EPSINON) & (x =”或“0 & b0 &(*ca | *cb) | (a0 & ba | *cb);100條經(jīng)典C語(yǔ)言筆試題目22、關(guān)于內(nèi)存的思考題(1)你能看出有什么問題?100條經(jīng)典C語(yǔ)言筆試題目23、關(guān)于內(nèi)存的思考題(2)你能看出有什么問題?100條經(jīng)典C語(yǔ)言筆試題目25、關(guān)于內(nèi)存的思考題(

54、3)你能看出有什么問題?100條經(jīng)典C語(yǔ)言筆試題目26、關(guān)于內(nèi)存的思考題(4)你能看出有什么問題?100條經(jīng)典C語(yǔ)言筆試題目27、 關(guān)鍵字volatile有什么含意? 并給出三個(gè)不同的例子。 【參考答案】一個(gè)定義為volatile的變量是說(shuō)這變量可能會(huì)被意想不到地改變,這樣,編譯器就不會(huì)去假設(shè)這個(gè)變量的值了。精確地說(shuō)就是,優(yōu)化器在用到這個(gè)變量時(shí)必須每次都小心地重新讀取這個(gè)變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個(gè)例子:1). 并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)2). 一個(gè)中斷服務(wù)子程序中會(huì)訪問到的非自動(dòng)變量(Non-automatic variables)3

55、). 多線程應(yīng)用中被幾個(gè)任務(wù)共享的變量100條經(jīng)典C語(yǔ)言筆試題目28、嵌入式系統(tǒng)經(jīng)常具有要求程序員去訪問某特定的內(nèi)存位置的特點(diǎn)。在某工程中,要求設(shè)置一絕對(duì)地址為0 x67a9的整型變量的值為0 xaa66。編譯器是一個(gè)純粹的ANSI編譯器。寫代碼去完成這一任務(wù)。 【參考答案】這一問題測(cè)試你是否知道為了訪問一絕對(duì)地址把一個(gè)整型數(shù)強(qiáng)制轉(zhuǎn)換(typecast)為一指針是合法的。這一問題的實(shí)現(xiàn)方式隨著個(gè)人風(fēng)格不同而不同。典型的類似代碼如下:int *ptr;ptr = (int *)0 x67a9;*ptr = 0 xaa55;100條經(jīng)典C語(yǔ)言筆試題目29、頭文件中的 ifndef/define/e

56、ndif 干什么用? 【標(biāo)準(zhǔn)答案】防止該頭文件被重復(fù)引用。 100條經(jīng)典C語(yǔ)言筆試題目30、#include 和 #include “filename.h” 有什么區(qū)別? 【標(biāo)準(zhǔn)答案】對(duì)于#include ,編譯器從標(biāo)準(zhǔn)庫(kù)路徑開始搜索 filename.h ; 對(duì)于#include “filename.h” ,編譯器從用戶的工作路徑開始搜索 filename.h 。100條經(jīng)典C語(yǔ)言筆試題目31、const 有什么用途?(請(qǐng)至少說(shuō)明兩種)(1)可以定義 const 常量 (2)const 可以修飾函數(shù)的參數(shù)、返回值,甚至函數(shù)的定義體。被 const 修飾的東西都受到強(qiáng)制保護(hù),可以預(yù)防意外的變動(dòng)

57、,能提高程序的健壯性。 100條經(jīng)典C語(yǔ)言筆試題目32、 static有什么用途?(請(qǐng)至少說(shuō)明兩種) 【標(biāo)準(zhǔn)答案】 1.限制變量的作用域(static全局變量);2.設(shè)置變量的存儲(chǔ)域(static局部變量)。100條經(jīng)典C語(yǔ)言筆試題目33、堆棧溢出一般是由什么原因?qū)е碌模?【標(biāo)準(zhǔn)答案】沒有回收垃圾資源。100條經(jīng)典C語(yǔ)言筆試題目34、如何引用一個(gè)已經(jīng)定義過(guò)的全局變量? 【標(biāo)準(zhǔn)答案】可以用引用頭文件的方式,也可以用extern關(guān)鍵字,如果用引用頭文件方式來(lái)引用某個(gè)在頭文件中聲明的全局變理,假定你將那個(gè)變量寫錯(cuò)了,那么在編譯期間會(huì)報(bào)錯(cuò),如果你用extern方式引用時(shí),假定你犯了同樣的錯(cuò)誤,那么在編

58、譯期間不會(huì)報(bào)錯(cuò),而在連接期間報(bào)錯(cuò)。 100條經(jīng)典C語(yǔ)言筆試題目35、全局變量可不可以定義在可被多個(gè).C文件包含的頭文件中?為什么? 【標(biāo)準(zhǔn)答案】可以,在不同的C文件中以static形式來(lái)聲明同名全局變量??梢栽诓煌腃文件中聲明同名的全局變量,前提是其中只能有一個(gè)C文件中對(duì)此變量賦初值,此時(shí)連接不會(huì)出錯(cuò)。100條經(jīng)典C語(yǔ)言筆試題目36、隊(duì)列和棧有什么區(qū)別? 【標(biāo)準(zhǔn)答案】隊(duì)列先進(jìn)先出,棧后進(jìn)先出。100條經(jīng)典C語(yǔ)言筆試題目37、 Heap與stack的差別。 【標(biāo)準(zhǔn)答案】Heap是堆,stack是棧。Stack的空間由操作系統(tǒng)自動(dòng)分配/釋放,Heap上的空間手動(dòng)分配/釋放。Stack空間有限,H

59、eap是很大的自由存儲(chǔ)區(qū)C中的malloc函數(shù)分配的內(nèi)存空間即在堆上,C+中對(duì)應(yīng)的是new操作符。程序在編譯期對(duì)變量和函數(shù)分配內(nèi)存都在棧上進(jìn)行,且程序運(yùn)行過(guò)程中函數(shù)調(diào)用時(shí)參數(shù)的傳遞也在棧上進(jìn)行。100條經(jīng)典C語(yǔ)言筆試題目38、用宏定義寫出swap(x,y),即交換兩數(shù)。 【標(biāo)準(zhǔn)答案】 #define swap(x, y) (x)=(x)+(y);(y)=(x)(y);(x)=(x)(y);100條經(jīng)典C語(yǔ)言筆試題目39、寫一個(gè)“標(biāo)準(zhǔn)”宏,這個(gè)宏輸入兩個(gè)參數(shù)并返回較小的一個(gè)。 【標(biāo)準(zhǔn)答案】#define Min(X, Y) (X)(Y)?(Y):(X)/結(jié)尾沒有;100條經(jīng)典C語(yǔ)言筆試題目40、

60、帶參宏與帶參函數(shù)的區(qū)別(至少說(shuō)出5點(diǎn))? 【標(biāo)準(zhǔn)答案】帶參宏帶參函數(shù)處理時(shí)間編譯時(shí)運(yùn)行時(shí)參數(shù)類型無(wú)需定義程序長(zhǎng)度變長(zhǎng)不變占用存儲(chǔ)空間否是運(yùn)行時(shí)間不占運(yùn)行時(shí)間調(diào)用和返回時(shí)占100條經(jīng)典C語(yǔ)言筆試題目41、關(guān)鍵字volatile有什么含意? 【標(biāo)準(zhǔn)答案】提示編譯器對(duì)象的值可能在編譯器未監(jiān)測(cè)到的情況下改變。100條經(jīng)典C語(yǔ)言筆試題目42、 int main()int x=3;printf(%d,x);return 1;問函數(shù)既然不會(huì)被其它函數(shù)調(diào)用,為什么要返回1? 【標(biāo)準(zhǔn)答案】mian中,c標(biāo)準(zhǔn)認(rèn)為0表示成功,非0表示錯(cuò)誤。具體的值是某中具體出錯(cuò)信息。100條經(jīng)典C語(yǔ)言筆試題目43、已知一個(gè)數(shù)組ta

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝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)論