




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
./郝斌老師的C語言:課堂講解全程動手敲代碼,講解細致,對于重要知識點的講解不厭其煩,是一個難得的C語言入門教程。在這里對老師的辛勤付出表示感謝。郝斌c語言視頻教程·概述:課程計劃為什么學習c語言:Fortran語言主要用于科學計算,在第三代語言中,以1980年為分水嶺,分為結構化和面向對象語言。Basic語言是vb的前生,pascal語言一般是用于教學。C語言是最重要的,其他的語言一般很少用了。結構化的代表語言是c語言。結構化語言的數據和操作是分離的,導致在寫大項目的時候,會出現各種各樣莫名其妙的問題。在面向對象的語言中c++是最復雜的語言。由于c++語言太復雜,sun公司對c++進行了改裝,產生了java語言。而c#是由微軟開發(fā)的,和java相似,幾乎一模一樣。在高級語言的執(zhí)行速度上,c是最快的,c++其次,而java和c#是最后的。Java和c#流行,主要的一個原因是可以跨平臺。C語言的發(fā)展和過程:C語言的特點:·優(yōu)點:代碼量小,速度快,功能強大?!と秉c:危險性高,開發(fā)周期長,可移植性弱。危險性高:寫同一個程序,在java中會報錯,而在c中不會報錯,為什么呢,因為c認為程序你想怎么寫就怎么寫,c語言認為你寫的程序不是很離譜,他都認為你寫的這個程序有特殊的含義。可以直接通過,而java則不可以。開發(fā)周期長:c語言是面向過程的語言,面向過程的語言的特點就是在開發(fā)大項目的時候,很容易崩潰,好比蓋大樓,C語言還要造大量的磚塊、鋼筋等結構原材料,而C++C#JAVA則進行了一定的繼承封裝等操作,相當于原材料直接給你,你只需要用它蓋樓即可?,F在市場上的語言分三塊C/c++:單純的學習c是什么都做不了的。JavaC#可移植性不強:這是針對java來說的,因為java的可移植性太強了,所以就感覺說c的可移植性不強。金山公司最主要是靠wps辦公軟件來發(fā)展的。Wps是c語言開發(fā)的,其安裝包比Office少了10多倍。三大操作系統(tǒng):windows,unix,linuxWindows內核是c語言寫的,而外殼是c++寫的。Java永遠不可能寫操作系統(tǒng)。因為java運行速度太慢了。而linux和unix都是純c寫的。操作系統(tǒng)控制了硬件,如果說操作系統(tǒng)的運行速度慢,那么當我們在運行軟件的時候,運行速度會更慢。為什么使用c語言寫操作系統(tǒng)呢,首先是因為c的運行速度快,然后是因為c可以直接控制硬件,而其他語言不可以。沒有指針的語言是不能直接訪問硬件的。C語言的應用領域:驅動一般是用c和匯編來寫的。數據庫一般是用c和c++來寫的C語言的重要性:雖然應用場合相對較窄,但貼近系統(tǒng)內核,較底層。病毒最基本的是要感染系統(tǒng),數據結構,c,c++這三門語言是必須要學習的。牛人牛語:怎樣學習c語言要將編程當成一項事業(yè)來經營,而不是糊口的工具。多思考,多上機。不能光看,光聽,而要排錯,調試。在犯錯誤中成長。參考資料王爽寫的c++也很不錯學習的目標:掌握簡單的算法--解決問題的方法和步驟。熟悉語法規(guī)則。能看懂程序并調試程序。C語言的關鍵字:C語言程序的格式:一定要養(yǎng)成良好的習慣:代碼規(guī)范邊寫邊保存,括號成對出現,應用空格VC6.0軟件操作:新建保存關閉〔關閉空間.cpp是原始文件,可單獨拷貝到其它電腦。第二講:〔14c語言編程必備知識Cpu,內存條,硬盤,顯卡,主板,顯示器之間關系。Cpu不能直接處理硬盤上的數據,必須要先調入內存Helloword程序是如何運行起來的。什么是數據類型數據類型--數據的分類,對編程而言,首要考慮問題是數據的輸入和存儲??梢苑譃锳:基本數據類型:整型整型int --4字節(jié)一字節(jié)byte=8位bit短整型shortint -2長整型longint -8浮點型單精度浮點數float:存儲范圍小-4雙精度浮點數double:存儲范圍大 -8 Float和Double都不能保證將小數完全準確保存。字符char:c語言中是沒有字符串string -1〔區(qū)別于JAVA、C#中有string且C#中char為2字節(jié)B:復合類型:就是把基本類型拼湊在一起結構體枚舉實用共用體—基本淘汰4.什么是變量變量的本質是內存中一段存儲空間。IntI;i=5;I是變量,程序向系統(tǒng)申請了一個內存單元,在程序運行中,i的值可以改變,但程序結束后,其所占的空間不是釋放,而是被系統(tǒng)收回權限。Cpu,內存條,vc++6.0,操作系統(tǒng)之間的關系。變量為什么必須初始〔即賦值軟件運行與內存關系〔垃圾數據-9868598658軟件在運行前需要向操作系統(tǒng)申請存儲空間,在內存空間足夠空閑時,操作系統(tǒng)將分配一段內存空間并將該外存中軟件拷貝一份存入該內存空間中,并啟動該軟件運行。在軟件運行期間,該軟件所占內存空間不再分配給其他軟件。當該軟件運行完畢后,操作系統(tǒng)將回收該內存空間〔注意:操作系統(tǒng)并不清空該內存空間遺留下來的數據,以便再次分配給其他軟件使用?!恫僮飨到y(tǒng)》一門課中系統(tǒng)分配表中會講到,用1標記表示內在是被占用的,用0標記表示是空閑的。綜上所述,一個軟件所分配到的空間中極可能存在著以前其他軟件使用過后的殘留數據,這些數據被稱之為垃圾數據,所以通常情況下我們?yōu)橐粋€變量,為一個數組,分配好存儲空間之前都要對該內存空間初始化。如何定義變量數據類型變量名稱=賦予的值;等價于數據類型變量名;變量名=要賦予的值;舉例子:inti=3;等價于inti;i=3;Inti,j;等價于inti;intj;Inti,j=3等價于inti;intj;j=3;IntI=3,j=5;等價于inti;intj;I=3;j=5;什么是進制–逢幾進一我們規(guī)定八進制前面加0〔零,十六進制前面加0x。常用計數制對照表:Printf的基本用法:常量在c中是如何表示的當個字符使用單引號括起來,多個字符串使用雙引號括起來〔指針、數組。在c中,默認是double類型的。在后面加F表示當做float來處理,否則會有警告提示--丟失部分字節(jié)。常量以什么樣的二進制代碼存儲在計算機中?編碼:整數是以補碼的形式轉換為二進制代碼存儲在計算機浮點數是以ieee754標準轉換為二進制代碼存儲字符本質實際是與整數的存儲方式相同,ASII碼標準。第三次課:代碼規(guī)范化·可以參考林銳《高質量c/c++編程》·代碼的規(guī)范化非常的重要,是學習一門編程語言的基礎,代碼可以允許錯誤,但不能不規(guī)范。例如:成對敲括號{}〔加空格于運算符和數字之間I=1+2;加縮進分清上下級地位。換行--進行功能區(qū)域分隔or{}括號單獨成一行?!ごa規(guī)范化的好處1:整齊,別人和自己都容易看懂。2:代碼規(guī)范了,代碼不容易出錯。3:一般的程序可以分為三塊: a:定義變量 b:對變量進行操作 c:輸出值什么是字節(jié)·存儲數據的單位,并且是硬件所能訪問的最小單位。內存中存儲的最小單位是位bit<0或1>,但是硬件控制的時候不能精確到位,只能精確到字節(jié)〔8位,是通過地址總線來控制的,而精確到位是通過軟件來控制的,叫做位運算符來精確到位的。1字節(jié)=8位1K=1024字節(jié)1M=1024K1G=1024M1T=1024G2G的內存條的總空間:2*1024*1024*1024*8=4*1032不同類型數據之間相互賦值的問題不同數據類型之間最好不要相互轉換。如果需要明白這個知識點,那么需要明白補碼。什么是ASCII碼以char定義變量的時候,只能使用單引號括起一個字符才是正確的。在上圖中注釋的最后一樣是重復定義了ch的值,是錯誤的,而下面的ch=‘c’是指把c賦值給ch,是正確的。上圖中輸出的值是98<將字符以整數%d的形式輸出>Ascll碼規(guī)定了ch是以哪個值去保存,ascii碼不是一個值,而是一種規(guī)定,規(guī)定了不同的字符是以哪個整數值去表示。其它規(guī)定還有GB2312UTF-8等。字符本質上與整數的存儲方式相同[字符的存儲]基本的輸入和輸出函數的用法:第三次課Printf〔將變量的內容輸出到顯示器上。四種用法輸什么是輸出控制符,什么是非輸出控制符輸出控制符包含如下:Printf為什么需要輸出控制符:·01組成的代碼可以表示數據也可以表示指令。必須要有輸出控制符告訴他怎么去解讀?!と绻?1組成的代碼表示的是數據的話,那么同樣的01代碼組合以不同的格式輸出就會有不同的輸出結果,所以必須要有輸出控制符。在上圖中,intx=47,如果前面加0〔零048表示的是八進制,如果前面加0x〔零x0X47則表示的是十六進制,而在輸出的時候,則是o<字母o>表示八進制,ox〔字母o,x表示十六進制。非輸出控制符:非輸出控制符在輸出的時候會原樣輸出。Scanf〔通過鍵盤將數據輸入到變量中有兩種用法:示例:非輸入控制符:在輸入的時候也會原樣輸入。但是強烈建議:在使用scanf的時候,不使用非輸入控制符。給多個變量賦值:需要記住,非控制符需要原樣輸入。如何使用scanf編寫出高質量代碼運算符:算術運算符:加〔+,減〔—乘〔*除〔/取余〔%關系運算符:>,>=,<,<=,!=,邏輯運算符:!〔非,&&〔且,||〔或賦值運算符:=,+=,*=,/=例如:a+=3是等價于a=a+3,a/=3等價于a=a/3其優(yōu)先級別是算術>關系>邏輯>賦值。取余的結果的正負只和被除數有關。第四節(jié)流程控制〔第一個重點:什么是流程控制程序代碼執(zhí)行的順序。流程控制的分類順序執(zhí)行選擇執(zhí)行定義:某些代碼可能執(zhí)行,可能不執(zhí)行,有選擇的執(zhí)行某些代碼。分類:ifIf最簡單的用法:如果想控制多個語句的執(zhí)行或者不執(zhí)行,那么需要使用{}括起來。3.if…else…的用法:if…elseif…else的用法:C錯誤的if…elseif…else語句:在上圖中,當執(zhí)行到哈哈那句時,下面的else將會被算作另外一個語句來執(zhí)行,而在我們的c語言中,沒有以else開頭的語句。所以會出錯。If實例:If常見的問題:變量的替換:求三個數字的大?。篊語言常見誤區(qū):紙老虎素數:只能被1和自己整除的數,如1,5,9等。回文數:正著寫和倒著寫一樣的數。如1221,121,等編程實現求一個十進制數字的二進制形式:求一個數字的每位是奇數的數字取出來組合形成的新數字。求一個數字到過來的數字。1:如果不懂,那么就看答案??炊鸢冈谇?。沒錯誤了,在嘗試改。如何看懂一個程序:流程:每個語句的功能:試數:對一些小算法的程序:嘗試自己編程結局。解決不了,看答案。關鍵是把答案看懂。看懂之后嘗試自己修改程序,且知道修改之后程序的不同輸出結果的含義。照著答案去敲調試錯誤不看答案,自己獨立把程序編出如果程序實在是徹底無法了解,就把他背會。空語句的問題:在上圖中,最終的結果會是AAAA,BBBB,程序也不會報錯,為什么呢,因為在程序執(zhí)行的時候,會在;哪里認為是一個空語句。也就是說,如果if成立,那么執(zhí)行空語句。If常見錯誤解析〔重點上面這個程序是錯誤的,為什么呢,在該程序中,總的有4個語句,而在以else開頭的那個語句中是有錯誤的,因為在c語言中是沒有以else開頭的這種語法。在上面這個程序中,最終的值是AAAA,雖說后面的3>1也滿足條件,但是當3>2滿足條件后,該if語句就會終止,后面的語句是不會在執(zhí)行的。既然7行要寫表達式,就要寫if。循環(huán)的定義、分類。定義:某些代碼會被重復執(zhí)行。分類:forwhiledo……while在上圖中,先執(zhí)行1,在執(zhí)行2,2如果成立,標志著循環(huán)成立,那么在執(zhí)行4,最后在執(zhí)行3,3執(zhí)行完后代表一次循環(huán)完成,然后在執(zhí)行2.以此類推。1永遠只執(zhí)行一次。++I等價于i+1求1-10的所有奇數的和:求1-12之間的所有能被3整除的數字之和:For所控制的語句:在上圖中,for默認只能控制一個語句,但是如果要控制多個語句時候,那么需要使用{}把語句括起來。求1+1/2+1/3….1/100的和在上圖中,重點是強制數據類型轉換也就是<float><i>那句:如果把print那句換為下面這句會怎么樣呢:也是錯的,為什么呢,因為i是整型,1也是整型,所以不管你怎么轉換也是整型啊,如果想要這樣寫的話,那么我們需要把1改成1.0也可以的。也就是:試數詳細步驟舉例:浮點數存?。呵?-100之間所有奇數的和:求1-100之間的奇數的個數:求1-100之間奇數的平均值:求1-100之間的奇數之和,在求1-100之間的偶數之和:多個for循環(huán)的嵌套使用:整體是兩個語句。上圖中,先執(zhí)行1,在執(zhí)行2,如果2成立,執(zhí)行4,在執(zhí)行5,如果5成立執(zhí)行A,在執(zhí)行6,在執(zhí)行5,如果5不成立,意味著里面的循環(huán)結束,然后執(zhí)行3,在執(zhí)行2,如果2成立又執(zhí)行4,在執(zhí)行5,如果5成立在執(zhí)行6,在執(zhí)行5,如果5不成立,在執(zhí)行3,在執(zhí)行2,如果2不成立,意味著本次循環(huán)結束,在執(zhí)行B,在上圖中,需要注意的是,如果2成立的話,那么每次4都需要執(zhí)行。進制之間的轉換:如234為5進制,那么轉換成10進制是多少:
2x5x5+3x5+4的值就是轉換成的10進制。234e是16進制,轉換成2進制是多少:
2x16x16x16+3x16x16+4x16+12的值就是轉換成10進制的值。注意上面的規(guī)律。那么把十進制轉換成r進制呢,其實很簡單,就是把10進制數除以r,直到商是0的時候。然后取余數,余數倒序排列:瑣碎的運算符:自增:自減:和自增一樣。三目運算符:最終的輸出結果是1.逗號表達式:最終結果是6.上圖中,逗號是個順序點,即所有的副作用必須在下個語句前生效,其最后結果為1,j+2只是產生臨時值,并沒有把j+2的值賦個j。如果寫成j+=2,那最后的值則變?yōu)?.For的嵌套使用舉例:上例中輸出的結果是9個哈哈,1個嘻嘻。在上圖中,整個程序分成3個語句,輸出的結果是3個嘿嘿,3個哈哈,1個嘻嘻。其結果是:While〔先付錢后吃飯 1:執(zhí)行的順序: 2:與for的相互比較:用for來求1-100之和:用while實現1-100之和。只需要把for語句替換為:For和while是可以相互轉換的,可以用下面的表達式來表示:While和for在邏輯上完全等價,但是for在邏輯上更強。更容易理解,更不容易出錯。推薦多使用for。
3:while舉例:試數:通過上面的試數,應該能很快的理解回文數的算法。 4:什么時候使用while,什么時候使用for:沒法說,用多了就自然而然知道了Do…while〔先吃飯后付錢一元二次方程:Switch的用法:電梯程序:Case是程序的入口,當進入程序后,程序會從上往下執(zhí)行,如果有break,那么會中斷程序,如果沒有,那么會一直執(zhí)行。Break的用法:在多層循環(huán)中,Break只能終止他最近的循環(huán)。在多層switch中,break也是只能終止距離他最近的switch。Break只能用于循環(huán)和switch,不能用于if。如果用于if,必須要當循環(huán)中嵌套if的時候。Continue的用法:上圖中,如果執(zhí)行continue,那么C,D將不會被執(zhí)行,會執(zhí)行3.在上圖中,如果執(zhí)行了continue,那么后面的C,D將不再執(zhí)行,而會去執(zhí)行表達式。數組:--非重點數組的使用:為什么需要數組1:為了解決大量同類型數據的存儲和使用問題。2:用數組可以模擬現實世界。Inta[25]:一維數組,可以當做一個線性結構。Inta[8][6]:可以當做一個平面,意思是8行6列。有48個元素。Inta[3][4][5]:可以當做一個三維立體。Inta[3][4][5][6]:可以當做一個四維空間。數組的分類一維數組怎樣定義一維數組:·為n個變量分配存儲空間:數組內存空間是連續(xù)的?!に械淖兞款愋捅仨毾嗤簲到M不可能第一個元素是整形,第二個元素是浮點型。·所有變量所占用的字節(jié)必須相等。例子: int[5]數組不是學習重點的原因?數組一旦定義,其長度是死的。有關一維數組的操作--都需要自己另外編程序實現而我們通常用第三方軟件〔工具如數據庫等方便直接地實現。對數組的操作:初始化賦值排序求最大/小值倒置查找插入刪除·初始化:上圖中a[5]前面如果沒有加上數據類型,那么這里的a[5]不是指一個數組,其中的5只的是下標。上圖中,數組的5個元素不是用a來代表的,是用a0,a1…a4來代表的,所以說數組名a代表的不是數組的5個元素,數組名代表的是數組的第一個元素的地址?!べx值把一個數組元素給全部倒過來:·排序·求最大/小值倒置查找插入刪除二維數組:二維數組的初始化:輸出二維數組內容:多維數組:是否存在多維數組:不存在因為內存是線性一維的,在內存中是不分行不分列的。N維數組可以當做每個元素是n-1維數組的一維數組。函數〔第二個重點:為什么需要函數:·避免了重復性操作?!び欣诔绦虻哪K化?!沧陨隙?逐步細化,大問題分解成小問題用它作為參照,可以對比JAVA和C#面向對象的思想。C語言基本單位是函數,C#、C++和JAVA基本單位是類。什么叫做函數·邏輯上:能夠完成特定功能的獨立的代碼塊。物理上:能夠接收數據[也可以不接收數據],能夠對接收的數據進行處理[也可以不對數據進行處理],能夠將數據處理的結果返[也可以沒有返回值]?!た偨Y:函數是個工具,他是為了解決大量類似問題而設計的,函數可以當做黑匣子〔內部原理不用管。如何定義函數·函數的返回值,函數的名字〔函數的形參列表 {函數的執(zhí)行體}·函數定義的本質:詳細描述函數之所以能夠實現某個特定功能的具體方法。函數中的變量叫做形參;數組中的變量叫元素。一旦函數執(zhí)行完畢,其內部的形參所占空間就被收回?!eturn表達式的含義:Return是終止被調函數,向主調函數返回表達式的值,如果表達式為空,則只終止函數,不向被主函數返回任何值。Break是用來終止〔就近的循環(huán)和switch語句。而return是用來終止被調函數的?!ず瘮捣祷刂档念愋?也稱為函數的類型,因為如果函數名前的返回值類型和函數執(zhí)行體中的return表達式中表達式的類型不同的話,則最終函數返回值的類型以函數名前的返回值類型為準。例:在上圖中,函數的返回值以函數前的數值類型為準。函數的分類·有參函數和無參函數?!び蟹祷刂岛蜔o返回值?!旌瘮岛陀脩糇远x函數?!て胀ê瘮岛椭骱瘮怠瞞ain函數1:一個程序有且只有一個主函數。2:主函數可以調用普通函數,普通不能調用主函數。3:普通函數可以相互調用。4:主函數是程序的入口,也是函數的出口。5:值傳遞函數和地址傳遞函數。判斷一個數是否是素數:使用函數判斷一個數是否是素數:函數和程序的調用應該注意的地方:函數的聲明:當函數沒有返回值時,那么規(guī)范的寫法是要在函數中寫明void的。在上圖中,第一個void表示沒有返回值,而第二個void表示不接收形參,也就是函數不接收數據。如果想把函數寫在程序的后面,那么需要寫函數聲明:函數聲明的含義是告訴編譯器f<>是個函數名。如果不加函數聲明,那么編譯器在編譯到f的時候,不知道f是個什么,如果加了函數聲明,那么編譯器編譯到f的時候,就知道f是個函數?!ば枰⒁獾氖?調用語句需要放在定義語句的后面,也就是說,定義函數的語句要放在調用語句的前面。如果函數調用寫在了函數定義的前面,則必須加函數前置聲明,函數前置聲明的作用是:1:告訴編譯器即將可能出現的若干個字母代表的是一個函數。"打招呼"2:告訴編譯器即將可能出現的若干個字母所代表的函數的形參和返回值的具體情況。3:函數聲明必須是一個語句,也就是在函數聲明后需加分號。4:對庫函數的聲明也就是系統(tǒng)函數。是通過#include<庫函數所在的文件的名字.h>來實現的。如stdio.h形參和實參要求:1:形參和實參個數是一一對應的。2:形參和實參的位置也是一一對應的。3:形參和實參的數據類型需要相互兼容?!と绾卧谲浖_發(fā)中合理的設計函數來解決實際問題。求1到某個數字之間的數是否是素數,并將他輸出:合理設計函數1合理設計函數2:合理設計函數3:合理的設計函數4:合理設計函數5:常用的系統(tǒng)函數和如何通過書籍來學習函數:Turboc2.0實用大全—機械工業(yè)出版社遞歸:〔略棧:相當于一個杯子〔容器變量的作用域和存儲方式:全局變量和局部變量:局部變量:局部變量的使用范圍只能在本函數內部使用。全部變量:全局變量和局部變量命名沖突的問題:在同一個范圍之內不能定義兩個一樣的局部變量:在一個函數內部,如果定義的局部函數的名字和全局變量名一樣時,局部變量會屏蔽掉全局變量:上例中最終的輸出結果是8,因為局部變量把全局變量給屏蔽掉了。指針:〔C語言的靈魂內存的存儲是以一個字節(jié)為一個編號,也就是8位合在一起給一個編號,不是0,1就給編號。內存分為很多個單元,每個單元就會分配一個編號。地址:內存單元的一個編號。而指針和地址一個概念的。也就是說指針就是地址。普通變量:只能存放一個值。指針變量:同樣是一個變量,但是指針變量存放其他變量的地址。*p代表的是p所指向的那個變量。在上圖中*p和i是同一個東西,但是*p和p不是同一個東西。在上圖中,int*p是一個聲明,開頭的int*是他的數據類型。P是變量的名字。不能理解我定義了一個整形變量,這個整形變量的名字叫做*p。所謂int*類型,實際就是存放int變量地址的類型。*p代表的是以p的內容為地址的變量。解析:p的內容是一個地址,在上圖中,p的內容就是i的地址,*p其指向的變量當然就是i變量了。指針和指針變量:指針就是地址,地址就是指針。地址就是內存單元的編號。指針變量:存放地址的變量。而指針只是一個值,這個值是內存單元的一個編號。指針變量才是一個變量,他里面才可以存放數據。指針和指針變量是兩個不同的概念,但是需要注意的是,通常我們在敘述時會把指針變量簡稱為指針,實際他們含義并不一樣。指針的重要性:指針的分類:指針的定義:·地址:內存單元的編號,是一個從0開始的非負整數。范圍:cpu對內存是通過控制、數據、地址三條總線來進行控制的??刂疲篶up會先把內存中的數據讀入,進行處理后,在返回給內存,然后內存在把數據寫入硬盤。數據:用于數據的傳輸,不管是把內存中的數據發(fā)送給cpu,還是把cpu的數據寫如內存條,都是由數據線來完成的,但是數據傳輸的方向則是由控制線來控制的。地址:地址線則是確定數據要寫入內存中的那個單元。所謂的一個單元就是一個字節(jié)。一條地址總線能控制2的1次方,一般的機器有32個地址線,最終能夠控制2的32個單元,而每個單元是八位,而最終我們的內存能夠存儲2的32次方*8位。則換算為G的話,最終大小為4G.那么地址總線的范圍則是4G大。指針:指針就是地址,地址就是指針。指針變量就是存放內存單元編號的變量。指針變量和指針是兩個不同的概念。指針的本質就是一個操作受限的非負整數。指針不能進行算術運算-相加乘除。但是能相減。如果兩個指針變量指向的是同一塊連續(xù)空間的不同存儲單元,則這兩個指針變量才可以相減。類似于同一個小區(qū)同一樓層六牌號相減表示兩房間隔。這時才有現實意義?;绢愋偷闹羔槪篒nt*p:p只能存放int類型的地址。P=&i:把i的地址賦給p。然后p就指向了i,*p就等于i。其實就是1:該語句保存了i的地址。2:p保存了i的地址,所以p指向i。3:p既然指向i,*p就是i。*p:表示以p的內容為地址的變量。*p:p是有指向的,p里面是個垃圾值,*p則是說以p的內容為地址的變量。因為不知道p的值是多少,所以不知道*p到底代表的是那個變量。而*p=i,i=5,最終的結果就是把5賦給了一個所不知道的單元。上圖中,第一個error是數據類型不符合,不能相互轉換。*q代表的是整形,因為*q代表的是以q的地址為內容的變量。而p是地址〔int*類型。第二個error同樣有錯,因為q沒有賦值。經典指針程序-互換兩個數字:1:先用函數來互換:最終的輸出結果沒有互換,因為函數的a,b已經執(zhí)行完成,分配給內存的空間已經釋放了,所以最終a,b的值還是主函數a,b的值?;Q的是形參的a,b。和主函數沒有關系。在上圖中,輸出的值也是沒有互換的,輸出的同樣是3,5,需要注意的是,互換的只是p、q的內容,局部函數變化了,但是主函數是沒有變化的。最終正確的程序:*號的三種含義:1:乘法2:定義指針變量。Int*p,定義了一個名字叫p的變量,int*表示p只能存放int變量的地址。3:指針運算符。該運算符是放在已經定義好的指針變量的前面。如果p是一個已經定義好的指針變量,則*P表示以p的內容為地址的變量。注意理解形參,實參,和局部變量的關系。指針可以是函數返回一個以上的值:不使用指針的話,只能使用用return來返回一個值。如何通過被調函數修改主調函數普通變量的值指針和數組:指針和一維數組:〔數組名下標與指針關系指針變量的運算·一維數組名:一維數組名是個指針常量,他存放的是一維數組第一個元素的地址。常量是不能被改變的,也就是說,一維數組名是不能被改變的。數組名a存放的是一維數組第一個元素的地址,也就是a=&a。printf<"%#X\n",&a[0]>;=====printf<"%#X\n",a>;指針和二維數組:下標和指針的關系:·如果p是個指針變量,則p[i]永遠等價于*<p+i>確定一個一維數組需要幾個參數,[如果一個函數要處理一個一維數組,則形參需要接收該數組的哪些信息。]確定一個一維數組需要兩個參數,1:數組名,從數組的名稱就可以知道數組的第一個值,因為一維數組的名稱就是數組的第一個元素的地址。2:是數組的個數。來計算該數組有多少個值。區(qū)別于字符串〔只需要一個參數—首地址因為字符串默認其后面都有一個"/0"作為結束標志。而數組并沒有相關約定。在上圖中,a是個指針變量,所以上面局部函數f的pArr則要定義成指針函數才可以,而len則是int類型。代表接收的是整型的數字。在上圖中因為數組a的名稱代表的是a的第一個元素的地址,所以在函數f中所定義的指針變量pArr和a是相同的,因為a也是指針類型。也就是說pArr=a=a[0],pArr[1]=a[1]=*<pArr+1>=*<a+1>,pArr[2]=a[2]=*<pArr+2>=*<a+2>.所以在f函數中pArr[3]=a[3],所以第二個printf輸出的結果是88.總結:pArr[i]=a[i]=*<pArr+i>=*<a+i>在沒有學習指針時,可將a[3]認為是數組中第4個元素,但現在應該對其內部原理有更深刻認識。這里下標也當成指針了,從首元素開始向后移動3個,即指向第4個元素。在上圖中因為數組a的名稱代表的是a的第一個元素的地址,所以在函數f中所定義的指針變量pArr和a是相同的,因為a也是指針變量類型。也就是說pArr=a=a[0],pArr[1]=a[1]=*<pArr+1>=*<a+1>,pArr[2]=a[2]=*<pArr+2>=*<a+2>.通過上圖,我們知道,我們在f函數中修改數組的值,相當于修改主函數中相對應的值。何謂變量地址/一個指針占幾個字節(jié)Sizeof<變量名/數據類型>其返回值就是該變量或數據類型所占字節(jié)數。一個指針變量無論其指向變量占幾個字節(jié),其本身所占大小都是4字節(jié)。*p具體指向幾個字節(jié),要靠前面類型確定,如果為int則為4字節(jié),如果double則占8字節(jié)。CPU與內存交互時有32根線,每根線只能是1或0兩個狀態(tài),所有總共有232個狀態(tài)。1個狀態(tài)對應一個單元。如全為0全為1等。內存中第一個單元,即32根線狀態(tài)全為0。00000000000000000000000000000000其大小為4字節(jié)所有每個地址〔硬件所能訪問的用4個字節(jié)保存〔而不是一位bit一個變量的地址—用該變量首字節(jié)的地址表示。這也就是為什么指針變量始終只占4字節(jié)的原因。接下來是:138課動態(tài)分配內存〔很重要專題:138講動態(tài)內存分配<所有高級語言,沒有C里深刻,對JAVA、C#理解有益>傳統(tǒng)數組的缺點:1.數組長度必須事先指定,而且只能是常整數,不能是變量例子inta[5];//必須事先指定,而且只能是常整數intlen=5;inta[len];//error2.傳統(tǒng)形式定義的數組,該數組的內存程序員無法手動釋放數組一旦定義,系統(tǒng)為數組分配的內存空間就會一直存在,除非數組所在的函數運行終止。在一個函數運行期間,系統(tǒng)為該函數中的數組分配的空間會一直存在。直到該函數運行完畢時,數組的空間才會被系統(tǒng)自動釋放〔不是清零。例子:voidf<void>{inta[5]={1,2,3,4,5};}//數組a占20個字節(jié)的內存空間,程序員無法手動編程釋放它,數組a只能在f<>函數結束被系統(tǒng)釋放3.數組的長度一旦定義,數組長度就不能再更改。數組的長度不能在函數運行的過程中動態(tài)的擴充或縮小4.傳統(tǒng)方式定義的數組不能跨函數使用A函數定義的數組,只有在A函數運行期間才可以被其他函數使用,但A函數運行完畢后,A函數中的數組將無法在被其他函數使用。#include<stdio.h>voidg<int*pArr,intlen>{pArr[2]=88;//parr[2]==a[2]等價于} voidf<void>{inta[5]={1,2,3,4,5};//數組a只在f<>執(zhí)行時有效g<a,5>;printf<"%d\n",a[2]>;}intmain<void>{f<>;//結果:88//printf<"a[0]=%d\n",a[0]>;//errorreturn0;}為什么需要動態(tài)分配內存很好的解決的了傳統(tǒng)數組的4個缺陷動態(tài)內存分配舉例_動態(tài)數組的構造難點/*2011-05-01malloc是memory<內存>allocate<分配>的縮寫動態(tài)內存空間是怎么造出來的?*/#include<stdio.h>#include<malloc.h>intmain<void>{ inti=5;//分配了4個字節(jié),靜態(tài)分配int*p=<int*>malloc<100>;/* 1.要使用malloc函數,必須要添加malloc.h頭文件2.malloc函數只有一個形參,并且形參是整型3.100表示請求系統(tǒng)為本程序分配100個字節(jié)4.malloc函數只能返回第一個字節(jié)的地址,但此時并不能確定該變量的類型,只有將這個地址被強制類型轉化成存放整型變量的地址,這時才傳達出指向整型變量的信息。5.系統(tǒng)總共分配了104個字節(jié)的內存空間,p變量本身占4個字節(jié)〔靜態(tài)分配,p所指向的內存占100個字節(jié)〔動態(tài)分配若為int則可存25個,若為char則可存100個變量。6.p本身所占的內存是靜態(tài)分配的,p所指向的內存是動態(tài)分配的*/free<p>; //free<p>表示把p說指向的內存空間給釋放掉,//p本身的內存不能釋放,只有main函數終止時,由系統(tǒng)自動釋放*p=5;//*p代表的就是一個這int變量,*p這個整型變量的內存分配方式和inti=5;不同。//*p是內存是動態(tài)分配的,inti是靜態(tài)的。printf<"同志們好!\n">; return0;}/*2011-05-01目的:malloc使用_2*/#include<stdio.h>#include<malloc.h>voidf<int*q>//q是p的拷貝或副本q等價于p*q等價于*p*q=200則*p=200{//*p=200; //errorf<>沒有p變量,p是在main<>函數定義的//q=200;//errorq是指針變量〔地址,200是整數int*q=200; //OK!類型一致//**q語法錯誤!*q整型變量,只有指針變量前可以加* //free<q>; //把q指向的內存釋放掉}intmain<void>{ int*p=<int*>malloc<sizeof<int>>; //sizeof<int>=4;*p=10; printf<"%d\n",*p>;//10f<p>; printf<"%d\n",*p>;//200//f<>函數中free<q>作用后,則輸出-572662307〔垃圾值return0;}/*2011-05-02目的:動態(tài)一維數組示例realloc<pArr,100>//擴充動態(tài)內存空間<原來50變100;原來150變100> //保留原來動態(tài)內存中未被截取的內容*/#include<stdio.h>#include<malloc.h>intmain<void>{//inta[5];//系統(tǒng)靜態(tài)地分配20個字節(jié)的空間給數組aintlen; int*pArr; printf<"請輸入你要存放的元素個數:">; scanf<"%d",&len>; //5 pArr=<int*>malloc<4*len>; //pArr指向這20個字節(jié)動態(tài)空間的前4個字節(jié)/* 動態(tài)的構造了一個一維數組,該數組的長度len,數組名是pArr,數組元素類型是int類似與intpArr[len];len可以根據需要變化*///對一維數組進行操作,如:對動態(tài)一維數組進行賦值for<inti=0;i<len;++i> scanf<"%d",&pArr[i]>; printf<"動態(tài)數組元素為:\n">;//對一維數組進行輸出for <i=0;i<len;++i> printf<"%d\n",pArr[i]>; free<pArr>; //動態(tài)空間被釋放printf<"%d\n",*<pArr+1>>;//動態(tài)空間被釋放,原來動態(tài)數組數元素內容為垃圾值-572662307return0;}/*在VC++6.0輸出結果:請輸入你要存放的元素個數:446810動態(tài)數組元素為:46810*/使用動態(tài)數組的優(yōu)點:1.動態(tài)數組長度不需要事先給定;2.內存空間可以手動釋放;3.在程序運行中,動態(tài)內存空間大小可以通過realloc函數手動擴充或縮小靜態(tài)內存和動態(tài)內存的比較靜態(tài)內存是由系統(tǒng)自動分配,有系統(tǒng)自動釋放靜態(tài)內存是在棧分配的動態(tài)內存是由程序員手動分配、手動釋放動態(tài)內存是在堆分配的/*2011-05-02目的:多級指針--自己畫幾個示意圖就會豁然開朗。/#include<stdio.h>intmain<void>{ inti=10; //i int*p=&i; //最終*p就是i; int**q=&p;//q只能存放int*類型的地址即p的地址&pint***r=&q;//r只能存放int**類型的地址即q的地址&q//r=&p;//error!因為r是int***類型,只能存放int**類型變量的地址printf<"i=%d\n",***r>;*r=q;**r=*q=p***r=**q=*p=i;printf<"i=%d\n",**q>;*q=p;**q=*p===i printf<"i=%d\n",*p>;*p=i; printf<"i=%d\n",i>; return0;}/*在VC++6.0輸出結果:i=10i=10i=10i=10*/#include<stdio.h>//多級指針在函數中的應用voidf<int**q>{ **q=100; //*q就是p}voidg<>{ inti=10; int*p=&i; printf<"i=%d*p=%d\n",i,*p>; f<&p>;//p是int*類型&p就是int**類型printf<"i=%d*p=%d\n",i,*p>;}intmain<void>{g<>; return0;}/* 在VC++6.0輸出結果:i=10*p=10 i=100*p=100*/ #include<stdio.h>#include<malloc.h>voidf<int*q>//q是p的拷貝副本{*q=1;}voidg<int**r>{ **r=2;}voidh<int***s>{ ***s=3;}voidi<int****t>{ ****t=4;}//要想修改函數變量的值,只能發(fā)送該變量的地址,修改一個以上的值,必須用指針intmain<void>{ int*p=<int*>malloc<4>; printf<"*p=%d\n",*p>; //垃圾值f<p>;//調用的是指針printf<"*p=%d\n",*p>; //1 g<&p>;//調用的是指針變量的地址printf<"*p=%d\n",*p>; //2//h<&<&p>>;//errorC2102:'&'requiresl-value int**pp=&p;//pp是存放p地址的指針,int**整型指針的指針類型h<&pp>;//調用的是存放p指針的指針的地址int***整型指針的指針的指針類型printf<"*p=%d\n",*p>; //3int***ppp=&pp;i<&ppp>;//調用的是一個三級指針的指針的地址,int****整型四級指針printf<"*p=%d\n",*p>; //4return0;}跨函數使用內存的問題難點/*2011-05-02目的:跨函數使用內存函數內的靜態(tài)空間,不能被其他函數調用訪問*/#include<stdio.h>voidf<int**q>//理解為int**q{inti=5;//*q等價于p *p和**q都不等價于p//*q=i;//error*q等價于p推出p=i;錯!*q=&i; //**q=*p=i;}intmain<void>{int*p; f<&p>; printf<"%d\n",*p>; return0;}/*結果:5本語句語法沒有問題,但邏輯上有問題內存越界:程序訪問了一個不該被訪問的內存函數內的靜態(tài)空間,不能被其他函數調用訪問函數中的內存空間,隨函數終止而被釋放。內存空間釋放后的內容不屬于其他函數,其他函數無權限訪問。但釋放后的內存空間的地址是可以被其他函數讀取的。但指針變量可以存貯任何函數中靜態(tài)內存空間的地址,p都能存垃圾,p想存誰存誰。只是它此時已經沒有權限讀取〔訪問i這個地址的數據了,出錯。*//*2011-05-02目的:動態(tài)內存可以跨函數訪問程序運行在棧頂進行靜態(tài)空間是在棧里面分配的,函數終止本質叫做出棧,所以靜態(tài)空間隨著函數終止而釋放,動態(tài)空間是在堆里面分配的,與棧無關,與函數終止無關,不隨著函數終止而釋放。堆和棧相關深入知識就需要《數據結構》和《操作系統(tǒng)》兩門課學習,而這兩門課難度大,理論性強,短期內收不到立竿見影的成效,屬于內功心法,因此大多培訓班已經取消了學習??梢杂胒ree<>釋放*/#include<stdio.h>#include<malloc.h>voidf<int**q> //*q等價p已經聲明了q的類型為int**{*q=<int*>malloc<sizeof<int>>;//sizeof<整數類型>/*不要用4,因為c語言只規(guī)定shortint字節(jié)數小于int字節(jié)數小于longint字節(jié)數,沒有規(guī)定明確的字節(jié)數,無統(tǒng)一硬性規(guī)定。不同軟件系統(tǒng)可能出現不同,統(tǒng)一用sizeof<int>來獲取實際值int*p;在p聲明的情況下,構造動態(tài)空間也可以寫成p=<int*>malloc<sizeof<int>>;*/ //*q等價p,等價于p=<int*>malloc<sizeof<int>>; //q=5; //error!q指針//*q=5; //error!p=5 **q=5; //OK!等價于*p=5}intmain<void>{ int*p; f<&p>;//只有調用變量的地址,才能改變變量的值printf<"%d\n",*p>;//f函數中,沒有free<q>;所以動態(tài)空間仍然保留,動態(tài)空間中的內容可以被訪問return0;}/*在VC++6.0輸出結果:5*/ 枚舉什么是枚舉把一個事物所以可能的取值一一列舉出來/*日期:2011-05-04目的:枚舉*/#include<stdio.h>//自定義了一個數據類型,并沒有定義變量,該數據類型的名字enumWeekDayenumWeekDay{ //MonDay,TuesDay,WednesDay,ThursDay,FriDay,SaturdDay,Sunday MonDay=10,TuesDay,WednesDay,ThursDay,FriDay,SaturdDay,Sunday};//分號intmain<void>{//intday;//day定義成int類型范圍太大不合適,day的取值只可能有7個<0-6>,浪費空間enumWeekDayday=FriDay;//初始化一個enumWeekDay類型變量dayprintf<"%d\n",day>; return0;}/*在VC++6.0輸出結果:414*/怎么使用枚舉/*日期:2011-05-04目的:枚舉2*/#include<stdio.h>enumweekday{ MonDay,TuesDay,WednesDay,ThursDay,FriDay,SaturdDay,Sunday};voidf<enumweekdayi>//本函數的目的只是期望接受0-6之間的數字,將形參定義為枚舉{switch<i> { case0: printf<"MonDay!\n">; break; case1: printf<"TuesDay!\n">; break; case2: printf<"WednesDay!\n">; break; case3: printf<"ThrusDay!\n">; break; case4: printf<"FriDay!\n">; break; case5: printf<"ThursDay!\n">; break; case6: printf<"SunDay!\n">; break; }}intmain<void>{ f<FriDay>;//雖然FriDay本質上就是5,但直接寫出f<5>;就是錯的,也不可能寫成Friday大小寫敏感return0;}枚舉的優(yōu)缺點優(yōu)點:代碼更安全〔強制輸入,比較直觀〔有意義缺點:書寫麻煩,不能出錯??偨Y:當是有限個元素時,用枚舉更安全,高效。位運算符約翰·馮·諾依曼〔JohnVonNouma,1903-1957,美藉匈牙利人被稱為計算機之父:2大貢獻二進制計算機設備分類:運算器控制器存儲器輸入設備輸出設備什么是進制數字是本質,進制只是不同表現方式一個十六進制位,要用4個二進制數表示,<1>16=〔00012前面補齊二進制逢二進一十進制逢十進一 dec八進制逢八進一 oct 0數字inti=05;十六進制逢十六進一hex 0x數字0X數字 inti=0x5;inti=0X5;生活中:七進制七天進周十二進制十二月進年二十四進制二十四小時進日六十進制六十分鐘進小時六十秒鐘進分鐘匯編里1101B二進制1357O八進制2049D十進制3FB9H十六進制十進制<D> 二進制<B> 八進制<O> 十六進制<H> 00 0 0 11 1 1210 2 2311 3 34100 4 45101 5 56110 6 67111 7 781000 10 891001 11 9101010 12 a<A>111011 13 b<B>121100 14 c<C>131101 15 d<D>141110 16 e<E>151111 17 f<F>1610000 20 10017=7+1*8=150x17=7+1*16=251234=4+1*10三次方+2*10二次方+3*10一次方0x32c=c+3*16二次方+2*16一次方=4354最高冪數是位數-1#include<stdio.h>intmain<void>{ inti=0x32c; printf<"i=%d\n",i>; printf<"i=%x\n",i>; printf<"i=%o\n",i>;/* printf的用法%d以十進制輸出%x或%X以十六進制輸出%o或%O以八進制輸出 */return0;}#include<stdio.h>intmain<void>{ inti=1000; print<"%X\n",i>//3E8printf<"%#X\n",i>//OX3E8%#X推薦return0;}補碼:原碼:也叫符號絕對值最高位0表示正1表示負,其余二進制位是該數字的絕對值的二進制位在計算機中,從未被使用!反碼反碼運行不便,也沒有在計算機中應用 移碼表示數值平移n位,n稱為移碼量移碼主要用于浮點數的階碼的存儲 補碼地址是內存單元編號從0到4G-1即2的32次方-1總線若是32位,則有32個0,1主要解決整數的存儲int4字節(jié)32位個0,1A已知十進制求二進制求正整數的二進制除2取余,直到商為零,余數倒序排列求負整數的二進制先求出與該負數相對應的正整數的二進制代碼,然后,將所有位取反末尾加1,不夠位數時,左邊補一4字節(jié)int-5先求5的二進制00000000000000000000000000000101所有位取反,末尾加11111111111111111111111111111101116進制:FFFFFFFB2字節(jié)shortint<-3>先求3的二進制0000000000000011所有位取反,末尾加11111111111111101用十六進制表示:FFFD求零的二進制全是零B已知二進制求十進制如果首位是0,則表明是正整數,按普通方法來求如果首位是1,則表明是負整數,將所有位取反末尾加1,所得數字就是該負數的絕對值習題:FFFFFFF5已知二進制求其代表的整數是多少?11111111111111111111111111110101由于最高位是1,所以最終是負數,先對其所有取反00000000000000000000000000001010末尾加1后00000000000000000000000000001011該值為11所以最終結果:-11如果全是零,則對應的十進制數字就是零C二進制到十六進制4位一段從右到左分別轉化不夠左邊初零〔001011102--<2E>16D十六進制到二進制一位轉化成4位,不夠左邊補0〔116--〔000000000000000000000000000000012E二進制轉到八進制從右往左,三位一段不夠被0F八進制與十六進制不能直接轉化。通過中間進制。進制總結:進制屬于什么知識點,許多人愛不懂裝懂。學習好它有利于將來學習底層如匯編等知識,但要往高級語言發(fā)展則不需要掌握,另外學好它對后面位運算等有幫助。學習后應掌握:在在VC++6.0中一個int類型變量所能存儲的數字的范圍是多少32位系統(tǒng),32個0,1組合表示的內存單元,8個十六進制數組合int類型變量所能存儲的最大正數用十六進制表示:7FFFFFFF int類型變量所能存儲的絕對值最大負整數用十六進制表示:80000000 最小負數的二進制代碼是多少1〔0-031個0最大正數的二進制代碼是多少0〔1-131個1已知一個整數的二進制代碼求原始的數字按"已知二進制求十進制"求數字超過最大正數會怎樣變成負數01111111=12710000000-128不同數據類型轉化丟失最高位.只截留后者類型所占的字節(jié)數。例如:int類型轉化為char則高3位字節(jié)被截取。只保留最后一位字節(jié)。結構體〔非重點為什么需要結構體為了表示一些復雜的事物,而普通的基本類型無法滿足實際要求。什么叫結構體把一些基本類型數據組合在一起形成的一個新的復合數據類型。如何定義結構體3種方式://第一種只是定義了一個新的數據類型,并沒有定義變量推薦采用1structStudent{ Intage;Floatscore;Charsex;};//第二種structStudent{ Intage;Floatscore;Charsex;}st;//第三種struct{ Intage;Floatscore;Charsex;}st;怎樣使用結構體變量賦值和初始化 定義的同時可以整體賦值。 如果定義完之后,則只能單個賦初值。如果取出結構體變量中的每一個成員{重點}1結構體變量名.成員名2指針變量名->成員名〔更常用它會在計算機內部轉化成<*指針變量名>.成員名的方式來執(zhí)行。所以兩者是等價的。例子:StructStudent{Intage;Floatscore;Charsex;};Intmain<void>{StructStudentst={80,66.6f,’F’//初始化定義的時候賦值66.6在C語言中默認是double類型,如果希望一個實數是float類型,則必須在末尾加f或F,因此66.6是double,66.6f或66.6F是floatstructStudentst2; st2.age=10; st2.score=88; st2.sex='F';//第二種方式單獨賦值StructStudent*pst=&st;//&st不能寫成stPst->age=88;//通過結構體指針變量printf<"%d%f\n",st.age,pst->score>;Return0;}理解:1pst->age會在計算機內部轉化成<*pst>.age的方式來執(zhí)行,沒有為什么,這就是->的含義,這也是一種硬性規(guī)定。2所以pst->age等價于<*pst>.age也等價于st.age 3pst->的含義:pst所指向的那個結構體變量中的age這個成員。 結構體變量的大小略大于其內部成員類型所占字節(jié)數之和。試:sizeof<struct>若想通過函數對主函數結構體變量進行修改,則主函數必須發(fā)送地址,外函數定義指針結構體變量,通過外函數內部語句完成對變量的修改。而僅想輸出、讀取操作,則不用傳地址,定義指針過程。例:/*2009年11月24日9:17:43通過函數完成對結構體變量的輸入和輸出*/#include<stdio.h>#include<string.h>structStudent{ intage; charsex; charname[100];};//分號不能省voidInputStudent<structStudent*>;voidOutputStudent<structStudentss>;intmain<void>{ structStudentst;//15行 InputStudent<&st>;//對結構體變量輸入必須發(fā)送st的地址//printf<"%d%c%s\n",st.age,st.sex,>;//此行和下行輸出函數功能相同 OutputStudent<st>;//對結構體變量輸出可以發(fā)送st的地址也可以直接發(fā)送st的內容 return0;}voidOutputStudent<structStudentss>{ printf<"%d%c%s\n",ss.age,ss.sex,>;}voidInputStudent<structStudent*pstu>//pstu只占4個字節(jié){ <*pstu>.age=10;//pstu->name="張三豐";或<*pstu>.name="張三豐";都是error,提示錯誤信息:cannotconvertfrom'char[5]'to'char[100]' strcpy<pstu->name,"張三豐">;//用字符串拷貝命令解決問題 pstu->sex='F'; }/*//本函數無法修改主函數15行st的值所以本函數是錯誤的voidInputStudent<structStudentstu>{ stu.age=10; strcpy<,"張三">;//不能寫成="張三"; stu.sex='F';}*/結構體:應該發(fā)送地址還是內容設計函數的目的:必須考慮功能單一,還要考慮安全因素C++中指針前可加const則只能讀而不能修改其指向的變量。指針的優(yōu)點:耗用內在小〔4字節(jié)快速傳遞數據執(zhí)行速度快。因此:推薦使用結構體變量作為函數參數來傳遞/*2009年11月24日9:17:43 示例: 發(fā)送地址還是發(fā)送內容 目的: 指針的優(yōu)點之一: 快速的傳遞數據, 耗用內存小 執(zhí)行速度快*/#include<stdio.h>#include<string.h>structStudent{ intage; charsex; charname[100];};//分號不能省voidInputStudent<structStudent*>;voidOutputStudent<structStudent*>;intmain<void>{ structStudentst;//15行 //printf<"%d\n",sizeof<st>>; InputStudent<&st>;//對結構體變量輸入必須發(fā)送st的地址 OutputStudent<&st>;//對結構體變量輸出可以發(fā)送st的地址也可以直接發(fā)送st的內容但為了減少內存的耗費,也為了提高執(zhí)行速度,推薦發(fā)送地址 return0;}voidOutputStudent<structStudent*pst>{ printf<"%d%c%s\n",pst->age,pst->sex,pst->name>;}voidInputStudent<structStudent*pstu>//pstu只占4個字節(jié){ <*pstu>.age=10; strcpy<pstu->name,"張三">; pstu->sex='F'; }結構體變量的運算不能加減乘除操作,只能相互賦值。例如:structStudent { Intage;Charsex;Char[100];};StructStudentstr1,str2;Str1=str2/str2=str1;都是正確的。舉例:動態(tài)構造存放學生信息的結構體數組#include<stdio.h>#include<malloc.h>//必須先添加頭文件mallocstructStudent{ intage; floatscore; charname[100];};intmain<void>{ intlen; structStudent*pArr; inti,j; structStudentt; //動態(tài)的構造一維數組 printf<"請輸入學生的個數:\n">; printf<"len=">; scanf<"%d",&len>; pArr=<structStudent*>malloc<len*sizeof<structStudent>>; //printf<"%d\n",sizeof<structStudent>>;//108字節(jié) //輸入 for<i=0;i<len;++i> { printf<"請輸入第%d個學生的信息:\n",i+1>; printf<"age=">; scanf<"%d",&pArr[i].age>; printf<"name=">; scanf<"%s",pArr[i].name>;//name是數組名,本身就已經是數組首元素的地址,所以pArr[i].name不能改成&pArr[i].name printf<"score=">; scanf<"%f",&pArr[i].score>; } //按學生成績升序排序冒泡算法 for<i=0;i<len-1;++i> { for<j=0;j<len-1-i;++j> { if<pArr[j].score>pArr[j+1].score>//>升序<降序 { t=pArr[j];//注意t的類型為StructStudent pArr[j]=pArr[j+1]; pArr[j+1]=t; } } } printf<"\n\n學生的信息是:\n">; //輸出 for<i=0;i<len;++i> { printf<"第%d個學生的信息是:\n",i+1>; printf<"age=%d\n",pArr[i].age>; printf<"name=%s\n",pArr[i].name>; printf<"score=%f\n",pArr[i].score>; printf<"\n">; } return0;}總結:對于一個人事管理或圖書管理項目,分析流程:第一步;存儲第二步:操作第三步:輸出前兩個過程最難、最核心是"數據結構"研究的重點,一般都屏蔽了。數組和變量雖然都可以存儲,但都不完美。比如:人事關系圖、交通圖等,都不好用數組保存。從事關系結構只能用"樹"還保存,而對于兩個起終點:公交線路查詢,實現時間最小/距離最短/花費最低等功能,只能用"圖"來存。而圖和樹都必須有指針知識,它們屬于較高深的思想層次的東西。因此要學好數據結構必須要懂得指針。若感興趣:可以繼續(xù)學習郝斌老師的《數據結構》教學視頻。鏈表〔較難C語言和數據結構的連接<過渡>鏈表是數據結構第一部分而是C語言最后一章內容,由此可以比較兩者難度算法:通俗定義:解題的方法和步驟狹義定義:對存儲數據的操作對不同的存儲結構,要完成某一個功能所執(zhí)行的操作是不一樣比如:要輸出數組中所有的元素的操作和要輸出鏈表中所有的元素的操作是不一樣的這說明:算法是依附于存儲結構的不同的存儲結構,所執(zhí)行的算法是不一樣的廣義定義:廣義的算法也叫泛型C++無論數據是如何存儲的,對該數據的操作都是一樣的分層思想,站在更高的層次看,把內部的實現給屏蔽數組和鏈表都是線性的,都是先輸出一個元素后,再輸出下一個元素我們至少可以通過兩種結構來存儲數據數組優(yōu)點:存取速度快缺點:需要一整塊連續(xù)的空間〔對于龐大數據,往往沒有一個適合的較大的連續(xù)的空間如a[30000000000000]插入和刪除元素效率很低<插入和刪除中間某個元素,其后的所有都要前后移動>鏈表優(yōu)點:插入刪除元素效率高缺點:查找某個位置的元素效率低〔由于不是連續(xù)的,不同由下標直接找,必須由頭至尾逐一比對查找兩者各有所長,至今沒有出現一個更優(yōu)的存儲方式,可集數組、鏈表優(yōu)點于一身。鏈表專業(yè)術語:首結點:存放第一個有效數據的結點尾結點:存放最后一個有效數據的結點,指針域的指針為NULL,尾結點的標志頭結點:頭結點的數據類型和首結點的類型是一模一樣的頭結點是首結點前面的那個節(jié)點頭結點并不存在有效數據設置頭結點的目的是為了方便對鏈表的操作頭指針:存放頭結點地址的指針變量確定一個鏈表需要一個參數,頭指針對于每個鏈表元素,分為左右兩部分,左邊為數據單元,右邊為下一元素地址。例:#include<stdio.h>#include<malloc.h>#include<stdlib.h>structNode{ intdata;//數據域 structNode*pNext;//指針域};//函數聲明structNode*create_list<void>;voidtraverse_list<structNode*>;intmain<void>{ structNode*pHead=NULL; pHead=create_list<>;//create_list<>:創(chuàng)建一個非循環(huán)單鏈表,并將該鏈表的頭結點的地址付給pHead traverse_list<pHead>; return0;}structNode*create_list<void>{ intlen;//用來存放有效節(jié)點的個數 inti; intval;//用來臨時存放用戶輸入的結點的值 //分配了一個不存放有效數據的頭結點 structNode*pHead=<structNode*>malloc<sizeof<structNode>>; if<NULL==pHead> { printf<"分配失敗,程序終止!\n">; exit<-1>; } structNode*pTail=pHead; pTail->pNext=NULL; printf<"請輸入您需要生成的鏈表節(jié)點的個數:len=">; scanf<"%d",&len>; for<i=0;i<len;++i> { printf<"請輸入第%d個節(jié)點的值:",i+1>; scanf<"%d",&val>; structNode*pNew=<structNode*>malloc<sizeof<structNode>>; if<NULL==pNew> { printf<"分配失敗,程序終止!\n">; exit<-1>;//終止程序 } pNew->data=val; pTail->pNext=pNew; pNew->pNext=NULL; pTail=pNew; } returnpHead;}voidtraverse_list<structNode*pHead>{ structNode*p=pHead->pNext; while<NULL!=p> { printf<"%d",p->data>; p=p->pNext; } printf<"\n">; return;}對于以上例題:不要求逐行敲出,但要能看懂。字符串的處理兩種:字符數組字符指針位運算&按位與-- 每一位都按位與<區(qū)別&j取地址> 1&1=1 1&0=0 0&0=0 0&1=0|按位或-- 每一位都按位與~取反 -- 每一位取反^按位異或-- 相同為零不同為11^0=1 0^1=1 1^1=0 0^0=0<<按位左移-- 左移n位相當于乘以2的n次方i<<3表示把i的所有二進制位左移動3位,右邊補零面試題:A>i=i*8; B>i=i<<3;請問上述兩個語句,哪個語句執(zhí)行的速度快答案:B快乘法在運算器里,運行原理比較復雜按位左移,簡單!>>按位右移-- 右移n位相當于除以2的n次方,首位為0補0,首位是1補1i>>3表示把i的所有二進制位右移動3位,左邊補零防止過度右移,容易喪失精度和意義位運算的現實意義:通過位運算符,我們可以對數據的操作精確到每一位。NULL二進制全部為零的含義: 0000000000的
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 吉林省延邊朝鮮族自治州汪清縣第六中學2025年高三高考模擬沖刺卷(提優(yōu)卷)(四)化學試題含解析
- 上海市浦東新區(qū)上海民辦張江集團校2025屆初三畢業(yè)班教學質量檢測試題數學試題含解析
- 江蘇省鹽城市濱??h蔡橋初級中學2025年高三下學期質量調查(一)物理試題含解析
- 山西省長治二中2024-2025學年全國高三模擬考(二)全國卷英語試題試卷含解析
- 瀝青路面施工方案培訓
- 湛江市大成中學高二上學期第四次月考物理試題
- 2025水產養(yǎng)殖承包合同范本
- 2025建筑材料購銷合同模板下載
- 2025建筑材料采購銷售合同模板
- 2025維修承包合同2
- (高清版)TDT 1036-2013 土地復墾質量控制標準
- 人際交往與溝通課件第六章 人際交往禮儀
- 社會穩(wěn)定風險評估 投標方案(技術標)
- 銷售銷售數據分析培訓講義
- 超密集組網技術及其應用
- 兩位數除以一位數(有余數)計算題200道
- 產后早開奶好處健康宣教
- 人效分析報告
- 2024屆江蘇省期無錫市天一實驗校中考聯(lián)考英語試題含答案
- 內鏡室院感培訓知識
- 北師大版數學三年級下冊《長方形的面積》
評論
0/150
提交評論