一、基礎研究
先對函數fa進行研究,代碼如下:
fa函數的參數為一個字符指針,他存儲要輸出的字符串。因為要顯示在屏幕的中央位置,所以我們要把字符串放在段地址b800處。用strlen獲取字符串的長度,因為屏幕為25行80列,所以如果字符串長度超過80,即一行放不下,那么就執行if后面的語句,這時要確保字符串整體位於屏幕中央,需要計算行數,而首地址的列數固定為3就可以了;如果字符串長度不超過80,即一行能夠放得下,那么將字符串放在中間行第12行,而首地址的列數需要計算以確保字符串在屏幕中央,我們通過行數和列數計算字符串首地址時用(總行/列數-字符串占的行/列數(行加1列不加1))/2即可得出字符串首地址的行/列數。因為我們要在屏幕中央顯示字符串,這樣會覆蓋掉屏幕上原來的信息,所以我們要提前將要顯示的區域的信息保存起來,在我們的字符串現實之后,再將這些信息恢復。那么這些信息保存在哪里呢?保存在另一段內存中,因為傳入的字符串長度是不確定的,所以要保存的屏幕信息的大小也是不確定的,我們無法先開辟一個固定的空間來保存它,只能動態地開辟空間來保存。所以我們需要使用malloc函數來動態地開辟空間,並將屏幕上的信息保存到這段內存中。這里傳入的字符串長度為n,但是屏幕上一個字符是用2個字節來顯示的,一個存儲字符內容,一個存儲顏色屬性,所以我們在轉移時轉移的字節數應該是字符串長度的兩倍。
之后顯示提示字符串並等待用戶輸入,直到用戶輸入了字符’y’,’Y’,’n’,’N’。之后將之前存儲的屏幕信息還原並將按鍵信息返回。我們來看返回語句:return(ch==‘y’||ch==’Y’);如果用戶輸入了’y’或’Y’,則這里會返回一個非0值,如果用戶輸入了’n’或’N’,則這里會返回0.
再來看main函數是怎么使用fa函數的,代碼如下:
程序在調用fa函數時直接在里面傳入了要顯示的字符串,我們知道字符串是一個字符數組,而數組在作為參數時會退化成一個字符指針,所以可以與fa的參數類型對接。
我們需要實現一個ask函數,ask函數實現的功能與fa函數相似,只是fa函數是實現所有功能,而ask函數是通過調用子函數實現具體功能。它們顯示字符串、等待用戶輸入的功能是一樣的。所以我們只需要修改fa最后的返回語句,改成用函數指針調用函數即可。程序如下:
如果用戶輸入的是’y’,’Y’,則調用子函數,之后返回,如果用戶輸入的是’n’,’N’,則直接返回。
我覺得ask所實現的特性是fa所實現的特性所衍生的。fa函數是用一個函數實現所有的功能,但是這樣一個函數里面的代碼太多了,會導致程序的維護性和可讀性降低,所以ask在fa的基礎上用子函數實現特定功能,這樣修改和讀起來都更加方便快捷。所以ask函數要比fa函數更好,因為它可以增加子函數對程序的功能進行擴展,而且函數的可讀性和維護性更好。ask函數的設計思想是將函數的功能盡可能地細化,盡量做到每一個函數只實現一個功能,每一個函數的語句盡可能地少,最好在3句以內。這樣可以將程序的可讀性和維護行做到最好。
我們將函數ask的代碼加入到cs .lib中,這樣我們要實現完整程序,只需要在c文件里寫好子函數,再在main函數里調用就行了。
我們之前的封裝是對共性的封裝,這種封裝到一定的程度就成了對對象的封裝,這個時候我們對問題的抽象化已經到達了一定的程度,但是我們對對象的實例化與方法的調用等操作都是在main函數里的,也就是說我們對個性的實現主要是在main函數里,也就是我們對需求的實現主要是在main函數里。而且這些實現需求的語句是十分零碎雜亂的。要讓程序更加有序,我們可以將需求的實現也封裝起來,這樣我們只需要在main函數里進行實例化和函數調用就可以了。而需求是需要函數來完成的,所以我們要把實現一個需求的語句封裝在一個函數里,這樣調用這個函數就可以實現需求。而fa函數是將實現需求的語句全部封裝在函數內,而ask函數是將每一個小的需求都再封裝在一個小的函數里,這樣會使程序封裝度更高,更加的有序。所以我們要使整個程序有序,不僅需要封裝對象,也需要封裝需求,不僅需要封裝數據,也需要封裝函數,即要做到數據、方法的有序,要做到所有函數內都是有序的,所有需求的實現都是有序的。
二、擴展研究
1、形如ch==’y’返回的bool型如果是非0值,是1還是有規律的數,如果不是1,是什么?
答:由編譯器的不同而不同,有的編譯器的值是-1,有的是1.
三、研究總結
為了將程序的功能細化,我們可以每一個功能用一個函數實現,這樣方便程序的測試、修改、擴展,做到了完全的有序化。事實上我們實現的這個ask函數還屬於功能比較復雜的庫函數,我們看printf函數、sizeof函數、kbhit函數、getch函數等,功能都非常單一,但是很實用,這樣我們寫程序時才能想的起來怎么用它們,如果你寫了一個功能強大的庫函數,要傳入很多參數,實現很復雜的功能,但是實現大多數程序時都不適用,甚至你都想不起來該怎么用,這個函數就沒有那些簡單的、基本的庫函數有價值。如果你實現的庫函數可以表達我們某一種基本的需求,比如輸出、輸入、返回、調用等等,那么它才是有價值的。
在比較簡單的事物的基礎上實現比較復雜的事物,這是比較簡單的,在比較復雜的事物的基礎上實現比較復雜的事物,這是比較難的。所以一個函數的功能要單一,我們才好用它。因為實現程序、表達思想的是程序員,不是我們調用的庫函數,這些封裝好的東西只是簡化我們工作的,不是代替我們寫程序的,它們只能算是一個個單詞,是我們程序員把它們串聯起來形成一條條語句,形成有特色功能的程序。
而且我們寫程序,不要把自己想的太聰明,而是要把自己往蠢里想,正是因為我們時時都有可能犯錯,所以我們才要通過規范的程序設計思想來約束自己,正是因為每個人都時時可能犯錯,所以才要通過法律、道德、各種價值觀、人生觀、世界觀來約束自己,指導自己怎么去走正確的路,做對的事。
程序設計思想就是指導我們在解決問題時采用合適的思路來分析和解決,而面向對象的程序設計思想能夠讓我們更好地認識問題,面向過程的程序設計思想能夠讓我們更好地解決問題。我們當然可以將這兩種思想結合起來。而程序設計的關鍵點就是有序,為了實現這個目標,我們對程序進行各種層次和角度的封裝,盡力使其在實現功能的基礎上,變得更加有序、合理,便於擴展和組織,以方便我們借助程序對問題進行更深層次的思考。它的意義不僅在於讓程序員更容易理解並進行擴展和修改,也在於借助於這個程序思考和解決問題。