繼續說一說前面提到的編程在於表達的問題。
語言是表達思想的工具。所謂學習C語言,不過是運用C語言把自己的思想表達出來、實現某種目的,本質上用其他語言也是可以的,只有具體文詞語法的區別,而沒有質的差異。因此,編寫程序之初,首先是確立解決問題的思想。
舉個實例。對三個或多個數值排序,是很多初學者都練習過的題目,基本上都能做出來,其基本算法很多,再巧妙的快速排序算法都有,但你有沒有發現,這些算法的基礎,都是基於賦值的,也就是說,排序的過程,也是挪動數據的過程。然而,你想過沒有,你固然可以對int x[n]這樣的數組用x[i]=x[i+1]之類運算,但如果要對元素是結構體的數組排序,還能這樣賦值嗎?儘管算法是不變的,但你卻無法輕易用以前的辦法實現排序結構體,然而,現實中最常見的正是排序這類數據!怎麼辦呢?雖然可以編寫一個專門賦值的函數對結構數據進行賦值運算,則可保算法不變,但如果結構是很龐大的一塊數據,賦值消耗的時間和資源恐怕是無法忍受的,更糟糕的情況,是結構體中包含指針,挪動結構的內存地址就意味著相關的指針需要跟隨變動,這個細緻的工作,即使你做了,也只能對這種具體的結構體有效,下次不同的結構體,就得全部再來一遍。沒有哪個正常的程序員會容忍這樣情況發生在自己身上!
現在,是充分調動所學知識的時候了。指針能夠派上用場。既然無法搬動數據實體,那麼就搬動它的“標籤”!構造一個新的結構體,作為原數組的映像,結構只有三項,第一個是數據在原來數組中的下標,第二個是需要比較的值(用以作排序依據的那個),第三個是排序後應在的下標。無論原來數組的元素有多龐大,現在我們只要排序這個微縮了的小型數組就可以了。在編寫函數代碼的時候,應該把這樣的算法抽象成一個可重用的函數,傳入一個函數指針,指向專用於某種數據結構的排序函數,返回比較關係即可,那麼無論要對任何數據類型排序,這個排序算法都是通用的(回憶一下那個三數排序程序,要分別對int、float、double編寫三個版本的函數,隨著數據類型的增多,這樣的版本也會不斷地積累下去,直到你自己厭惡透頂。程序員不是打字員,不是指法飛快地敲大同小異的代碼就可以的)。這種手法,在數據庫軟件中就是“索引文件”的基本原理,無論數據庫的每筆記錄有多龐大、多複雜,都不需要在物理上挪動數據,而是對抽象出來的微量數據進行排序,然後把排序後的結果通知用戶,用戶按圖索驥抽取實際的數據,就呈現排序的效果了。
現在你看到,這種思想與具體語言是無關的,甚至不需要真正的指針(如果語言不支持指針也沒問題),即使某種語言支持結構體賦值這樣的操作,無論在消耗資源這個層面上考慮,還是節約函數版本的角度上考慮,也不能就用原來的那種排序手法了,而這個才是真正通用的、泛型的,C++中的泛型算法,你看過就知道是按這種思想構造的原理,因此,即使不用C++的泛型,用C也未嘗不可實現。明白這樣的原理,無論學的是什麼語言,基本上都難不倒你了。至於具體語言的語法,查閱資料即可,關鍵是要非常清楚自己想幹什麼、要達到什麼目的。
編程的精粹,首先是你自己要有想法,然後才是實現。只會實現別人交付的方案,那是初中級程序員,沒用的。做一萬道題,也不比自己需要某種功能而去實現它有用。自己想需求並實現之,而不是被動做題,這是我給你的忠告。
[
本帖最后由 TonyDeng 于 2012-1-12 02:43 编辑 ]