前 言
緣起
2016年底,電子工業出版社與中新金橋信息技術有限公司合作,計劃做一批立體化網絡課程建設項目,作者因有《C 語言程序設計新視角》(以下簡稱《新視角》)一書,有幸參與到項目之中。在C語言課程視頻的錄制過程當中,作者引入了許多新的思路與方法,因此有了對《新視角》進行完善再版的想法。
寫作思路
《新視角》一書結合作者多年教學實踐經驗,針對學生在學習程序設計中的困惑,側重引入問題、分析問題、討論解決問題的方法,本書是基於《新視角》的改進版本。在C語言、數據結構等程序設計課程的講授以及課後和學生的溝通中,筆者認識到在編程學習中大家遇到的普遍問題歸納起來有四難:概念晦澀理解難,規則眾多記憶難,法無定法編程難,bug深藏調試難。
著名數學家歐拉(Leonhard Euler)說過,如果不能把解決數學問題背後的思維過程傳授給學生,那麼數學教學就沒有意義,這種觀點同樣適用於其他各學科或課程的教學。理解原理、掌握解決問題的思維方法是學習過程的要點。分析學生在學習程序設計中的問題,最主要的問題是編程概念建立困難,其次是程序調試技巧難以把握。按照問題輕重的順序,《新視角》一書嘗試從以下這些方面來解決問題——重思維,揭本質,強調試,輕語法。《新視角》經過這些年的使用,發現依然有不少需要改進的地方,特別是在問題引入和解析各種機制設置的原因方面,本書對此做了較大篇幅的增加。
1.重思維
圖靈獎獲得者、現代計算機科學的先驅人物高德納,在其代表作《計算機程序設計的藝術》中指出,編程是把問題的解法翻譯成為計算機能“理解”的明確術語的過程,這是在人們開始試圖使用計算機時最難以掌握的。C語言又是在高級編程語言中公認屬於較難掌握的,有枯燥乏味、規則眾多、艱深晦澀的一面。
計算機是一種自動化的工具,人們用這種工具來解決問題,會受到很多機器特性的限制,在一個與人們以往解決問題的運作規則不一樣的繫統中,已有的處理問題的經驗很可能用不上。在程序設計語言中有很多概念是隻學習過數理化知識的學生們從未接觸過的,課堂上直接按傳統教科書的內容講述解釋後,發現他們較難理解和接受。
Garr Reynolds在《演說之禪》中這樣寫道:“好的故事可以終生受用,用於傳道授業,用於分享,用於啟迪,當然,也可以用於勸解。講故事是吸引觀眾,滿足他們對於邏輯、結構以及情感方面需求的一個重要方式。”本書中許多引例都是從有趣的故事開始,從實際問題引出與編程相關的話題,提出問題,引起讀者思考,再從人直接解決問題到使用機器解決問題的不同角度加以討論,分析相同與不同,最後提出相關的程序設計概念。為在敘述中有代入感,書中設計了布朗教授一家參與問題的討論。布朗教授或以初學者的視角提出問題、探索解決方案,或以專家的身份討論問題;布朗太太是編程小白,偶爾會有貌似可笑的外行言論;布朗教授的兒子小布朗是小學生,也常會提些看起來幼稚的問題。另外還有布朗教授的學生、同事及親屬參與“演出”。這樣的設計思路,是遵循金出武雄(Takeo Kanade)教授在總結科研成功之道時提出的“像外行一樣思考,像專家一樣實踐”方法論的一次實踐。
“如果我們從不同的角度對同一個概念進行學習並研究與其相關的問題,就能建立更多且更深層次的信息鏈接。這些信息鏈接和與其相關的內容交織,共同構成了我們日常所說的‘理解’。大腦處理的所有信息都不是孤立的,而是具有邏輯關繫的一組信息。當這些信息具有結構性,能夠和已經學過的知識、和學生的生活實際建立密切的聯繫時,就容易讓人從不同的角度來思考這一信息,從而對其有深入且透徹的理解。”(Salman Khan,《翻轉課堂的可汗學院》)《新視角》通過解析人與計算機解決問題的同與不同,探索問題的解決方法,培養學生基於計算機特點進行邏輯思維的素養。根據計算機解決問題的特點,通過介紹讀程列表法、算法設計法以及經典的算法描述法等方法,讓學生先學讀程再學編程,從大的方向上把握編程的一般方法,逐步建立程序的思維。
2.揭本質
“重視知識的本質,對於程序員來說這一點尤其重要。程序員的知識蕪雜海量,而且總是在增長變化的。很多人感嘆跟不上新技術。應對這個問題的辦法隻能是抓住不變量。大量的新技術其實隻是一層皮,背後的支撐技術其實都是數十年不變的東西。底層知識永遠都不過時,算法數據結構永遠都不過時,基本的程序設計理論永遠都不過時。”(劉未鵬,《暗時間》)
編程沒有現成的公式可以套用,雖然學生通過大量實例的學習可以從中總結出一些規律,但對於程序設計語言為什麼設這樣或那樣的處理規則,可能在短時間內不一定能琢磨明白。知其然還要知其所以然,隻有清楚了各種規則設計的原理,纔能徹底理解規則,進而熟悉和掌握規則,最後舉一反三熟練應用。從原理的剖析入手,這樣能提高學習效率,學會用計算機解決問題的方法。本書增加了許多從實際的問題引入概念的內容,讓學生知道程序設計各重要概念的來龍去脈;增加了對重要機制的設置原因進行本質討論分析,把有關聯關繫的概念進行橫向或縱向分析鏈接,對重點的概念或相關聯的概念提煉出其中的要素,以期增加學生對課程關鍵內容的把握。
3.強調試
“無論一個程序的設計結構如何合理,也無論文檔如何完備,如果不能產生正確的結果,則其一文不值。”(Chris H. Pappas等所著的《C++程序調試》)人們制造的產品,一般都有一定的誤差存在,比如設備或儀器。軟件產品是一個例外,軟件的最終交付形態是二進制的可執行碼,執行碼是不能容忍誤差的,而人類的思維特性正好與之相反,是模糊和充滿誤差的,因此程序員很難一次就寫出完全正確的代碼。
張銀奎在其《軟件調試》一書中指出,“軟件調試技術是解決復雜軟件問題的最強大工具。如果把解決復雜軟件問題看作一場戰鬥,那麼軟件調試技術便是一種可以直擊要害而且銳不可當的武器。應該說學會調試器命令不難,但如何用調試器調試程序,找到bug,卻是一件很不容易的事情。”調試的技巧和經驗需要很長時間的練習纔能積累起來,對初學者而言是不容易掌握的,由此造成很多學生懼怕編程。
“我們可以在調試程序和偵破謀殺案之間找出相似點來。實際上,在幾乎所有的謀殺懸念小說中,謎案都是通過仔細分析線索,將表面上不重要的細節全聯結起來而最終偵破的。”(Glenford J. Myers,《軟件測試的藝術》)“調試有點像捕魚:相同的情緒、熱情和刺激。長時間靜靜地工作後最終得到的是別人所不能體驗的喜悅。”(Eugene Kotsuba)掌握了程序調試技術,讀者在學習和開發程序時就能獨立發現問題、解決問題,這樣可以大大提高學習的興趣和信心。
除了查找程序中的錯誤,調試其實對程序設計中不少概念的理解也是非常有幫助的,比如地址、、賦值、參數傳遞、作用域等,課堂上調試演示給予的直接的感性認識,比抽像的語言描述概念生動直觀得多。“除了使用調試器調試程序、尋找代碼中的問題,還可以認識其他軟件、探索操作繫統、觀察硬件等。”(張銀奎,《軟件調試》)不同的調試器,基本調試功能的工作方式和工作原理是基本一致的,“與MS-DOS中的第一個調試器Debug.com相比,雨後春筍般湧現的各種調試器,它們的大多數在原理上並沒有多少進步,隻是界面不同而已。”(Kaspersky,Hacker Debugging Uncovered)可以說,學會調試,對後續諸多的計算機類課程學習都是有益的,因此,教會學生調試的方法和技巧應該是編程類課程的一個非常重要的內容。
筆者在企業任程序員多年,參與過歷時4年多、獲國家科技進步獎的大型軟件開發、開發成功後多用戶單位安裝調試、售後服務等繫列工程工作,對程序測試與調試有一定的實踐經驗。在授課過程中一直堅持在課堂上穿插演示調試,學生隻要有要求,隨時可以將任何一個程序展開進行跟蹤調試講解。後來發現,即使在課上多次演示重要程序實例的調試,學生也掌握得並不好。細究原因,調試是一個復雜過程,不同的數據組織、程序邏輯、現場查看處理等情形非簡單幾句描述就可以清楚明白,學生當時看懂了,但要回想復習時,就沒有可以參考的紙面資料,所以在《新視角》一書中把各章很多重點實例的調試過程及技巧都“靜態固化”到紙面上,讓學習者學習調試時有切實可行的參照方法。調試內容千變萬化,技巧也非常多,本書隻討論了最基本的調試方法與技巧,目前鮮有同類教科書有這樣全面的處理方法,專門介紹調試的書籍也較少。
編程是一個不斷修改纔能完善的過程,其間往往要經過多次測試和調試。本書簡單介紹了測試樣例的設計原則和設計時機,讓讀者充分認識到程序測試的重要性,在學習編程之初就建立程序健壯性的概念。
4.輕語法
“輕”不是輕視語法,而是先介紹最基本的語法規則,讓初學者在理解中記憶,在使用過程中逐步熟練,使學習者不至於一開始就被C語言繁復的規則所困惑。對於相關深入的語法或復雜的、不常用的規則,作者把握的原則是讓學生知道知識歸類、會根據線索自己查找說明手冊或使用方法。針對計算機編程課程的特點,根據學生程度不同,由淺入深層層遞進設置不同難度的練習。
內容結構
本書探究從問題到解的計算機解決問題的方法論,以計算機解決問題的流程做主線,按照數據組織、數據處理、處理結果分別涉及的知識點層層展開,通過問題引入、類比解析概念,自頂向下逐步細化描述算法,數據分析實現存儲、代碼實現問題得解,到最後的測試調試驗證結果。
數據的介紹從基本形式開始,隨著問題要處理信息復雜程度的增加,通過討論各種數據可能的組織方式,如數組、數據地址、復合數據、文件等,介紹數據在計算機中的組織結構和存儲方法,另外還有數據的輸入、輸出方法。
算法是解決問題的步驟和方法,計算機算法需根據計算機解題特點來設計。算法由程序語句來實現,程序語句有相應語法規則及使用方法,程序有基本控制結構,程序開發有特定的步驟和方法。
隨著問題復雜程度的增加,程序規模需要從單一模塊(函數)變為多模塊結構,本書通過討論處理問題規模改變之後需要增加的處理機制,介紹函數的