陳 濤,朱 俊,裔傳俊,張 麗,李 菊
(南京理工大學(xué)紫金學(xué)院 計算機(jī)學(xué)院,江蘇 南京 210023)
C 語言是高校計算機(jī)類學(xué)生必修的一門專業(yè)基礎(chǔ)課,其教學(xué)目標(biāo)是通過這門課程的學(xué)習(xí),使學(xué)生建立基本的編程思想,獲得程序設(shè)計的基本訓(xùn)練,進(jìn)而為后續(xù)學(xué)習(xí)其他計算機(jī)專業(yè)的課程打下良好的基礎(chǔ)[1],但在實際教學(xué)過程中發(fā)現(xiàn),上述目標(biāo)達(dá)成度很低。許多學(xué)生經(jīng)過一個學(xué)期的C語言學(xué)習(xí),僅停留在做題、考試等淺層次的知識掌握上,一部分學(xué)生甚至視編程為畏途,喪失了進(jìn)一步學(xué)習(xí)的興趣。
C 語言是一門操作性和應(yīng)用性很強(qiáng)的課程,應(yīng)試能力固然重要,但其核心在于培養(yǎng)學(xué)生的編程能力。編程能力就是一種利用計算機(jī)解決問題的能力,要求學(xué)生能夠靈活運用所掌握的理論知識,把一個待求解的實際問題轉(zhuǎn)化為代碼邏輯。高等教育是以能力培養(yǎng)為中心的教育,需要圍繞能力培養(yǎng)來實施教育教學(xué)[2]。
C 語言課程一般安排在大一上學(xué)期講授,對于初次接觸計算機(jī)專業(yè)學(xué)習(xí)的新生而言,通常會覺得難以理解,這給C 語言教學(xué)工作帶來一定的困難。從教學(xué)現(xiàn)狀來看,主要存在以下問題。
(1)課程內(nèi)容偏重語法知識,缺少算法能力的培養(yǎng)。C 語言知識點多,擁有豐富的數(shù)據(jù)類型和函數(shù)庫。對于教師而言,如果沒有實際項目開發(fā)經(jīng)驗,很容易把教學(xué)重點放在復(fù)雜的語法規(guī)則上面。著名計算機(jī)科學(xué)家沃斯提出“程序=算法+數(shù)據(jù)結(jié)構(gòu)”[3],如果培養(yǎng)學(xué)生編程能力,不能忽視基本算法能力的培養(yǎng)。
(2)“教本位”授課,忽視解決問題能力的培養(yǎng)。在C 語言教學(xué)中,當(dāng)前主流方式是以課堂講授為主。面對C 語言紛繁的概念和語法,教師唯恐學(xué)生不能理解,在課堂上反復(fù)講解這些所謂的重點和難點,卻忽視培養(yǎng)學(xué)生分析問題和解決問題的能力。這樣做的結(jié)果是培養(yǎng)出來的學(xué)生僅限于編寫類似“Hello World”的簡單控制臺程序,只要碰到稍微復(fù)雜的問題,往往束手無策??梢?,這種“教本位”的授課方式亟待改變。
(3)編碼以完成功能為主,缺失工程能力的培養(yǎng)。對于程序員而言,通過編碼不僅要實現(xiàn)完整的功能,而且還要保證代碼具有良好的可讀性。換言之,我們培養(yǎng)出來的學(xué)生需要具備一定的編程規(guī)范意識,這也是一種基本的編程能力。筆者曾經(jīng)以編程規(guī)范的視角去審視當(dāng)前主流的國內(nèi)C 語言教材,沒有發(fā)現(xiàn)一本是能做到合格的。這些教材在編碼的縮進(jìn)、空格、換行、內(nèi)存申請等的處理隨心所欲,缺少基本的工程思維。再者,許多教師授課中也不注重培養(yǎng)學(xué)生的規(guī)范意識,從而導(dǎo)致這門課程在培養(yǎng)學(xué)生的工程能力方面乏善可陳。
(4)上機(jī)以驗證為主,不注重代碼調(diào)試能力的培養(yǎng)。C 語言的學(xué)習(xí)離不開上機(jī)實驗,在機(jī)房中,大多數(shù)同學(xué)都能完成實驗題目的編碼工作(當(dāng)然代碼規(guī)模很小,在數(shù)十行之內(nèi)),實現(xiàn)軟件功能。對于這種簡短的代碼,如果在編譯、鏈接、運行中沒有錯誤,學(xué)生就自認(rèn)為完成了實驗要求,萬事大吉;如果出現(xiàn)錯誤,卻束手無策,往往對著屏幕發(fā)呆,無法有效地進(jìn)行排除。對于上述問題,如果通過老師的幫助獲得了解決,許多學(xué)生不再做進(jìn)一步的思考,后續(xù)碰到類似問題做不到舉一反三;如果不能及時解決,代碼得不到運行結(jié)果,長久下來就會挫傷學(xué)習(xí)該門課程的積極性。
(5)以知識為主的考核方式,無法引導(dǎo)學(xué)生提升自主編程能力。大多數(shù)情況下,期末考試是通過一張試卷來決定最終成績,無法真實地反映學(xué)生的編程能力。許多學(xué)生為了應(yīng)付考試,只注重理論知識的學(xué)習(xí),不注重上機(jī)實踐,在考試前突擊學(xué)習(xí),對于一些編程題目甚至通過死記硬背的方式應(yīng)付考試,根本不理解代碼的邏輯和結(jié)構(gòu)。有時候,有些實踐能力較強(qiáng)的學(xué)生所取得的成績可能反而沒有這類應(yīng)試型的學(xué)生好??梢哉f,這種重理論、輕實踐的考核機(jī)制存在很大弊端,不利于引導(dǎo)學(xué)生提升自主編程能力[4]。
教學(xué)內(nèi)容是指教學(xué)過程中需要傳遞的信息,是教師給學(xué)生傳授的知識和技能。毫無疑問,作為編程能力組成基礎(chǔ)的語法知識、算法能力、工程能力等需要體現(xiàn)在教學(xué)設(shè)計中。
在C 語言教學(xué)大綱中,一般按照重點、難點去標(biāo)識教學(xué)內(nèi)容。例如,把“循環(huán)的嵌套”“指針數(shù)組”“函數(shù)指針”等識別為重要內(nèi)容,分配較多的授課時間。這種以知識的難易程度來區(qū)分教學(xué)內(nèi)容,有時無助于編程能力的培養(yǎng)。C 語言是一門實踐性很強(qiáng)的課程,應(yīng)面向工程實際需要來組織教學(xué)內(nèi)容。
(1)識別工程應(yīng)用知識,納入教學(xué)大綱。借助來自企業(yè)的雙師型人才,通過會議、訪談等方式,審視當(dāng)前教學(xué)大綱不足。例如,內(nèi)存分配、文件操作這些原先不被重視的內(nèi)容,識別出是軟件開發(fā)中必備的知識技能。在教學(xué)中,把內(nèi)存分配重新列入教學(xué)大綱,在課堂重點講授;對于文件操作,由于學(xué)時等因素,放在課程設(shè)計中讓學(xué)生自學(xué),要求每個課程設(shè)計題目不應(yīng)當(dāng)僅限于控制臺的命令行操作,必須增加文件操作的內(nèi)容。
(2)增加編程規(guī)范內(nèi)容。參考華為等IT 企業(yè)的C 語言編程規(guī)范,重點在代碼排版、變量或函數(shù)命名、內(nèi)存使用、注釋等方面指導(dǎo)學(xué)生學(xué)習(xí)[5]。對于教師,要求課件、范例程序必須符合編程規(guī)范,并有義務(wù)向?qū)W生指出教材中哪些代碼沒有按照規(guī)范要求去寫;對于學(xué)生,要求作業(yè)、上機(jī)等的代碼嚴(yán)格遵循編程規(guī)范,提升代碼的可讀性。
語言是工具,算法是程序設(shè)計的核心。算法是求解問題的計算步驟,一些計算機(jī)領(lǐng)域的經(jīng)典算法可以說是培養(yǎng)編程能力的最佳工具。C 語言課程不是算法課程,不適合也不可能對算法做系統(tǒng)的介紹,故在安排算法教學(xué)內(nèi)容上,以入門級的排序和遞歸算法為主,培養(yǎng)學(xué)生的計算思維能力。
(1)排序算法是計算機(jī)算法中最簡單的部分,非常適合在學(xué)習(xí)數(shù)組時引入。排序算法方式很多,一般要求學(xué)生掌握選擇排序、插入排序、快速排序等三種算法,能力高者可繼續(xù)學(xué)習(xí)希爾排序、歸并排序等算法。
(2)遞歸的本質(zhì)就是高中階段的數(shù)學(xué)歸納法,對于大一學(xué)生而言,通過遞歸算法的學(xué)習(xí),可以感受到從數(shù)學(xué)邏輯到計算機(jī)編程的一個轉(zhuǎn)換過程,培養(yǎng)計算思維能力。此外,遞歸算法也是分治法、動態(tài)規(guī)劃等算法的基礎(chǔ),適度引入有助于提升計算機(jī)課程學(xué)習(xí)的興趣。
C 語言使用靈活,語法規(guī)則很多。在教學(xué)設(shè)計上,以“夠用”為邊界取舍語法內(nèi)容,以指針為主線安排教學(xué)順序。
(1)以實用為原則,精簡語法規(guī)則。學(xué)習(xí)C語言的目的是為了編寫程序,而非復(fù)雜的語法規(guī)則本身。由此,基于程序設(shè)計需要,對于多重指針、多維數(shù)組、靜態(tài)函數(shù)等內(nèi)容不做要求;對于數(shù)據(jù)類型、運算符優(yōu)先級等內(nèi)容進(jìn)行弱化。例如,數(shù)據(jù)類型重點學(xué)習(xí)int、char、double 等常用類型,對于其他類型及無符號類型,點到為止;對于運算符的優(yōu)先級,則要求遵循編程規(guī)范,通過加括號顯示指定優(yōu)先級,不要求學(xué)生去記憶復(fù)雜的優(yōu)先級順序。
(2)在教學(xué)順序上,提前引入指針內(nèi)容。C語言的精髓在于指針,指針也是實際開發(fā)中的重點。大部分教材都是按照基本語法、數(shù)組、函數(shù)、指針、結(jié)構(gòu)體的順序編寫,作者本意是按照先易后難的認(rèn)知規(guī)律組織教學(xué)。實則不然,如果按照這種順序授課,把指針部分放在課程快要結(jié)束的時候來講,無法強(qiáng)化指針內(nèi)容的學(xué)習(xí)。故在教學(xué)設(shè)計中,把指針的基本概念放在數(shù)組之前,以指針為主線串起后面的數(shù)組、函數(shù)、結(jié)構(gòu)體部分章節(jié)的教學(xué),通過反復(fù)演練,讓學(xué)生深刻掌握指針的應(yīng)用。
教學(xué)實踐是師生互動、傳授知識和解答困惑的過程,主要有課堂授課、上機(jī)實驗、期末考試等環(huán)節(jié)。在C 語言教學(xué)中,需要在上述各環(huán)節(jié)著重培養(yǎng)學(xué)生的編程能力。
案例教學(xué)是一種開放式、互動式的教學(xué)方式,在大學(xué)授課中有著廣泛的應(yīng)用。在C 語言課程中,通過綜合性案例把散亂的多知識點貫穿起來,借助案例輔助教學(xué),可有效培養(yǎng)學(xué)生分析問題和解決問題的能力。
(1)學(xué)用結(jié)合,培養(yǎng)學(xué)生的求知欲望。在理論授課中,需要有意識地把C 語言語法學(xué)習(xí)和使用相結(jié)合,引導(dǎo)學(xué)生如何將解題步驟轉(zhuǎn)換為程序?qū)崿F(xiàn)。例如,在講解例題時,教師可采取現(xiàn)場編程的教學(xué)方法,直接在開發(fā)環(huán)境上演示編程過程,從而教會學(xué)生如何編寫程序;另外,對于編好的代碼進(jìn)行現(xiàn)場運行,演示代碼調(diào)試過程,從而教會學(xué)生如何調(diào)試程序。從教學(xué)效果來看,現(xiàn)場編程比PPT 講解程序更能引起學(xué)生的興趣,更能激發(fā)學(xué)生學(xué)習(xí)的積極性。
(2)以案例輔助教學(xué),培養(yǎng)學(xué)生綜合運用知識的能力。鑒于C 語言內(nèi)容多而凌亂的特點,在教學(xué)中,當(dāng)一組相關(guān)的知識點學(xué)習(xí)結(jié)束后,可構(gòu)建融合多知識點的綜合性案例,培養(yǎng)學(xué)生解決問題的能力[6]。例如,在學(xué)習(xí)了指針和數(shù)組后,我們設(shè)計了“字符串操作”案例,通過編碼實現(xiàn)字符串長度、字符串比較、字符串拷貝和字符串拼接等4 個子問題,來深化課堂教學(xué)。在本案例授課時,教師可通過現(xiàn)場編程,帶領(lǐng)學(xué)生實現(xiàn)某個子問題;然后,在其他問題教學(xué)中,教師可僅講解要點,讓學(xué)生自行完成其他子問題的編碼;最后,教師基于學(xué)生完成的情況,進(jìn)行總結(jié)點評。實踐證明,案例教學(xué)改變了以教師為中心的“教本位”模式,增加了師生互動,讓學(xué)生成為課堂的另一主角。學(xué)生不再是光聽不練,而是需要不斷思考,去解決問題并完成編碼。
結(jié)對編程(pair programming)是一種敏捷軟件開發(fā)方法,是指兩個程序員在同一臺計算機(jī)上共同工作并完成任務(wù)。把產(chǎn)業(yè)界的結(jié)對編程引入實驗教學(xué),有助于培養(yǎng)學(xué)生相互學(xué)習(xí)、相互支持的團(tuán)隊協(xié)作能力,從而實現(xiàn)編程能力的共同提升[7]。
(1)活用結(jié)對編程,引導(dǎo)學(xué)生共同進(jìn)步。在軟件開發(fā)中,結(jié)對編程是對程序員而言的,組隊成員需要具有豐富的經(jīng)驗,在工作中一人編碼一人審視。對于學(xué)生特別是大一新生而言,幾乎沒有編碼經(jīng)歷,顯然不能直接套用業(yè)界的最佳實踐。在教學(xué)中,我們活用結(jié)對編程,不拘泥于其形式,將其定位為一種學(xué)習(xí)互助小組。首先,在上機(jī)前一周,要求學(xué)生兩兩完成自由組隊,成立結(jié)對小組;然后,在實驗課上,結(jié)對成員要求并排坐在一起,但在編碼形式上,不要求一人編碼一人觀察,可在討論問題后分別進(jìn)行;最后,采用共同評價方式,按照小組評定實驗成績。上述措施實行以后,大部分的組隊方式都是同一宿舍或者好朋友在一個結(jié)對小組內(nèi),兩人在實驗課上共同完成任務(wù),能力高者自覺幫助另一成員,達(dá)到了共同進(jìn)步的教學(xué)目標(biāo)。
(2)加強(qiáng)上機(jī)過程指導(dǎo),注重培養(yǎng)調(diào)試能力。在實驗課上,不能僅僅要求學(xué)生獲取程序的運行結(jié)果,還要培養(yǎng)基本的代碼調(diào)試能力。一般來說,編碼完成后,不可能編譯、鏈接、執(zhí)行一帆風(fēng)順,往往存在語法錯誤或邏輯錯誤。其中語法錯誤調(diào)試起來比較簡單,在編譯階段就可發(fā)現(xiàn),教師可要求學(xué)生認(rèn)真閱讀編譯器給出報錯原因,并對于出現(xiàn)較高的英語單詞或句子,摘抄下來強(qiáng)化記憶。邏輯錯誤則較難解決,需要教會學(xué)生設(shè)置斷點、單步跟蹤等調(diào)試手段,將動態(tài)執(zhí)行過程分解為靜態(tài)片段,推測錯誤來源。
由于每個實驗班人數(shù)較多(多于60 人),為了提升教學(xué)效果,在實踐中要求每實驗室配備1~2 名高年級學(xué)生作為助教,協(xié)助老師處理上機(jī)中出現(xiàn)的問題。在實驗課上,對于程序出現(xiàn)的錯誤,先以結(jié)對小組為單位,在小組內(nèi)討論,不能解決的方可求助老師或助教。在老師或助教指導(dǎo)過程中,結(jié)對小組成員都要認(rèn)真學(xué)習(xí),掌握求助問題的解決方法。
教學(xué)改革中實行新的考核方式,降低期末筆試成績的比重,增加實驗上機(jī)測試,將C 語言綜合成績確定為:平時成績(20%)+筆試成績(40%)+實驗成績(40%)。平時成績主要考查學(xué)生的出勤記錄、作業(yè)情況和學(xué)習(xí)態(tài)度等;筆試成績就是傳統(tǒng)的期末考試,主要考查基本知識、閱讀程序和程序分析能力;實驗成績則是在課程結(jié)束后,安排一次集中的上機(jī)考試,考查學(xué)生綜合運用C 語言知識解決問題的能力。上機(jī)測試時間限定在2 小時,教師提供多個綜合性的問題供學(xué)生選擇,要求學(xué)生當(dāng)場完成,并從運行結(jié)果、編程規(guī)范、程序邏輯等方面評定實驗成績。這種綜合性的考核機(jī)制,較為真實地反映了學(xué)生對本門課程的掌握情況,避免了在學(xué)習(xí)過程中不重視編程實踐的現(xiàn)象。
近年來,面向編程能力培養(yǎng)的C 語言教學(xué)模式在我校計算機(jī)相關(guān)專業(yè)進(jìn)行了試點,并獲得了良好效果。通過教學(xué)班級學(xué)生調(diào)查來看,這種方法激發(fā)了學(xué)生的編程興趣,大家在學(xué)習(xí)過程中更加重視上機(jī)實踐,編程能力普遍得到了很大提高。從考核結(jié)果來看,筆試成績和實驗成績的分?jǐn)?shù)段比例均衡,筆試成績高者實驗成績也都落在高分段,達(dá)到了教學(xué)改革的初衷。此外,本教學(xué)模式也可推廣到計算機(jī)專業(yè)的其他程序設(shè)計類課程的教學(xué)中,如C++、Java、Python 等。
當(dāng)然,沒有哪一種教學(xué)模式是一勞永逸的,我們的教學(xué)改革仍然任重道遠(yuǎn)。例如,在結(jié)對編程上如何協(xié)調(diào)組隊成員的能力差異,做到兩人即可共同進(jìn)步又能夠能力高者先行;在案例教學(xué)中如何解決大班授課和案例互動的矛盾,以實現(xiàn)最佳的案例教學(xué)效果等。上述這些訴求都是在后續(xù)C 語言教學(xué)實踐中需要進(jìn)一步探索的問題。