易鋒,馬慧,何懷文,翁佩純
(電子科技大學中山學院計算機學院,廣東中山528400)
目前大多數高校計算機類專業將C 語言作為入門的編程語言,開設了以C 語言為基礎的程序設計基礎課程,目的是培養學生程序設計能力和編程思維。程序設計基礎是計算機類專業核心基礎課程,是數據結構與算法和操作系統等專業課的先修課程。因此程序設計基礎的教學對計算機類專業來講極為重要。
采用C語言的程序設計基礎,內容全面、抽象,語法規則繁雜;從程序設計基礎到高級應用;知識點豐富、重難點多,跨度極大,學生在學習過程中存在較大困難[1]。這不僅導致學生對基本語法知識掌握較差,而且阻礙對學生程序設計能力訓練和編程思維的培養。
針對該問題,有教師從教學內容、教學方法、教學實踐等多方面闡述了教改方案,并取得了一定效果[2-3]。但是導致基于C語言的程序設計基礎課程學習門檻較高的一個重要原因是學生所處的時代與C語言出現的年代之間的軟硬件差異;特別是C語言存在許多對內存的精細管理,導致學生很難理解和掌握相關教學內容[4]。由于缺乏對C 語言出現的歷史背景的了解,學生學習中很難知其然,更難達到知其所以然的教學效果。
另外一方面,當前計算機內存并沒有成為當前流行編程語言首要考慮的問題。許多大學生在初、高中學習過編程課程,比如應用于科學計算的Python 語言已經成為許多初高中編程課程的首選語言[5]。Python 支持“對象型”或者“無類型”的數據,也就是按需分配內存。在Python 編程中,所有的變量在使用前并不需要顯式定義。編程語言上的差異,教學中如果不加引導和辨析,會導致學生在學習C 語言的過程中,充滿了疑惑和問題。
實際上,通過對比C 和Python 差異,能突出兩種語言的特點。利用兩種語言各自優點,更有利于培養學生計算思維、程序設計思想和編程技能。有分析,才能有比較;有比較,才能有鑒別[6]。利用Python 語法簡單,上手容易的特點輔助引入問題建模、算法設計等程序設計思想和計算思維[7];繼而引入C的實現,這樣可以更好地幫助學生掌握C 的繁雜語法。有鑒于此,本文在程序設計基礎上引入對比教學法,并在2021 級計算機和軟件工程兩個專業班級進行了教學實踐,結果表明對課程教學質量的提高有較大的促進作用。
20 世紀80 年代,為了能寫出讓計算機更快運行的程序,C程序員要學會像計算機一樣思考,這使得編程需要耗費大量的時間。吉多·范·羅蘇姆(Guido van Rossum)針對該問題,同時結合了Shell編程的優點,發明了Python語言。可以說Python語言的設計之初就是為了解決C語言學習和使用中的缺點,是天然的適合與C 語言組合,作為對比教學設計的語言[8]。在C 語言程序設計基礎教學過程中,注意C語言某些語法知識出現的歷史背景,并有意識地引入Python 語言的語法作為對比,這樣層層遞進,逐步深入、分辨異同,可以幫助學生深入掌握C語言中的重點和難點。下面分為以下七個部分對C 語言與Python 進行對比教學設計。
從程序設計思想角度,可以將高級編程語言分為面向對象和面向過程兩類。面向過程是將要解決的問題自頂向下,按解決步驟把問題逐步細分為更小的問題,然后編寫相應的函數解決這些步驟對應的問題,C語言是典型的面向過程的語言。面向過程的編程語言特點是速度快,性能高;缺點是對程序員的要求高,不易維護、復用性差、不易擴展,不適合開發操作系統,硬件驅動。
面向對象是對要解決的問題中涉及的對象進行建模,利用對象描述解決問題中涉及屬性、行為,有封裝、繼承、多態的特性。Python是面向對象的語言,以功能而不是步驟對問題進行劃分。優點是易維護,復用性好,易擴展;缺點是性能比面向過程語言的程序低,適合桌面應用、網應用等軟件開發。
程序設計基礎課程伊始,引導學生建立對面向過程和面向對象語言的正確認識,了解兩種不同的程序設計思想,通過對比,為后續的面向對象程序設計課程做鋪墊,打基礎。
使用高級編程語言編寫的源程序要在計算機上執行,必須轉換為二進制指令,稱為編譯。根據編譯的不同,可將高級編程語言分為編譯型語言和解釋性語言。編譯是將源程序編譯成可執行的目標程序,編譯和運行是分開的;解釋是在執行程序的時候對源代碼進行編譯和執行,編譯和運行合二為一。
C語言是典型的編譯型語言,其編譯過程如圖1所示。
沒有編譯原理基礎的大一新生對上面的編譯流程理解存在困難。Python 是一種典型的解釋性語言。教學中可以以輸出“hello world”為例,演示C語言和Python語言的區別。C語言程序首先對源程序進行編碼,然后經過編譯和鏈接生成目標可執行程序,然后再執行。Python語言可以直接在環境中調用函數進行輸出;或者編寫源程序后,調用Python 命令來執行源程序,不會生成可執行程序。
C 語言出現在20 世紀70 年代,當時個人電腦典型的內存為幾百KB。為了能寫出高效運行的程序,C語言程序員需要對內存進行精確管理與使用。這種考慮,導致C語言是一種靜態弱類型語言,定義了超過十種的變量類型。在C 語言中,變量必須先定義后使用,每種變量類型有取值范圍,而且不同數據類型存在相互的隱式轉換和顯示轉換。學生在學習本知識點時,存在非常大的困難。
而Python出現在20世紀90年代,計算機,包括個人電腦的內存已經大大提高。出現了動態類型、內存自動管理、面向對象中垃圾自動回收等內存自動管理技術。因此,Python將數據類型的指定交給解釋器來管理,是動態強類型語言。在Python中,變量使用前不需要先定義變量的類型,解釋器會根據變量所賦值自動決定變量的類型;而且一般情況下,可以認為整數類型和浮點類型是沒有范圍限制的。
教學中以Python變量為切入點,引入變量和變量類型。因為Python 中基本類型少,結合使用Python 的bin()函數,可以使得學生比較容易理解變量類型與變量在內存中存儲的關系。此后,引入C語言出現歷史背景,引導學生思考,如何在較小內存前提下,更加高效地存儲數據,以此過渡到C 語言中的數據類型。在講授過程中可以以不同類型的溢出為例,幫助學生理解C 語言基本變量類型、數據類型的范圍及相互間轉換的原理。
雖然在變量使用方面,Python比C語言更為簡單,但在運行速度方面,前者不及后者。課堂中設計了“1+…+1”的實例演示兩種語言運行速度方面的差異。在累加百萬次的時候,兩者差距不明顯;但是當累加十億次后,兩者運行的時間差距達到幾十倍。這種運行時間的差距是由編譯類型和解釋類型,以及Python 的內存自動管理等因素造成。解此例可以進一步向學生闡述兩種語言的特點和不同的應用領域。
C和Python 包含順序結構、選擇結構和循環結構三種控制結構。
對于選擇結構,C用零表示條件為假,非零表示條件為真;Python則提供用于判斷真假的Bool類型,也兼容C語言的條件規則;教學中可以使用bool()函數進行測試舉例。C 使用&&,||,!的抽象符號表示邏輯與、或、非運算,學生難以記憶;而Py‐thon使用英文單詞AND、OR 和NOT 表示,兩者對應關系如表1所示。通過對比,學生更容易記住C中抽象符號所表達的含義及運算規則。在實現上,C 提供了if、switch 和?:運算符等條件控制語句;Python 只提供了if 條件語句。Python 之所以可以簡化,因為switch和?:運算符均可以由if語句等價實現。教學中,可以引導學生在C中使用if實現switch和?:控制語句。

表1 C和Python的邏輯值和邏輯運算
對于循環結構,C 提供while、do-while 和for 三種循環控制語句;Python提供while和for循環控制語句。通過對比C和Py‐thon的流程控制語句的異同,可以使同學更加深入理解不同控制語句之間的關系;了解不同語言在流程控制語句上的借鑒與發展。
Python 中的函數定義和使用相對簡單,沒有對函數聲明、函數返回值的限定要求。教學中以Python 中的簡單加法例子為切入點,引入函數,介紹函數的定義、實現過程和調用。以Python的例子為基礎,引入C語言的函數定義形式。闡述兩者的區別和相同點,加深學生對C 語言函數定義的掌握。首先C語言的函數需要有返回值類型;其次C語言的函數體,與Python的縮進定義不同的是由一對{}括起來的語句組成。C語言的語句之后均帶有分號;以表示語句的結束,Python的每條語句占一行。根據C語言靜態弱類型的特點,指出函數聲明的作用。兩者定義的函數均需要定義函數名,函數名后為一對圓括號;如果有參數,參數要寫在圓括號內;均由return語句指定函數的返回值。參數的傳遞中,對于簡單類型,兩者都是值傳遞,也即形參的更改不會修改實參的值。
數組是用一個變量名保存多個相同類型的值。在Python中,一般認為沒有內置對數組的支持,可以使用元組或列表代替。相比C語言,Python的列表定義和初始化更為簡單[9]。
教學中,首先介紹Python 中列表的使用,讓學生首先熟悉程序設計中數組的使用方法。然后引入C 語言的數組,結合C語言的出現歷史背景,指出C語言的數組表示內存中一片連續的存儲區。C99 之前,為了優化對內存的使用,定義數組時必須指定數組類型和大小,在使用過程中數組大小是不可變的;隨著技術進步,C99標準規定了可以使用變長數組。通過對比Python數組定義和初始,加深學生對C語言數組定義和初始化規則的理解和記憶。
此外數組作為實參,是傳址方式,即實參和形參共用同一個存儲空間。在高級編程語言中,為了實現內存的高效使用,對于數組這種復合數據類型的參數傳遞,傳遞的是數組的地址值。通過C語言和Python中參數傳遞的對比,引導學生理解傳值和傳地址作為參數的時機選擇原理。
Python提供了存儲字符串的類型——String,及豐富的字符串處理函數。Python 中的字符串由一對單引號或一對雙引號定義。而在C語言中一對單引號定義的是單個字符,一對雙引號定義的是字符串。如果在字符串中出現的單引號或雙引號字符,Python的定義可以避免其引起的結束歧義;而在C語言,則需要使用轉義字符進行轉義。在Python中,字符串也是以列表方式存儲,其簡單的定義和豐富的函數,可以幫助學生快速掌握字符串的定義和使用。
課堂教學中,首先使用Python 引入字符串,然后介紹C 語言中的字符串的定義和使用,特別要指出C語言使用字符數組對字符串進行存儲和表示,且字符數組的末尾為元素0。根據Python提供的字符串處理函數,以及C語言中字符串存儲特點,引導學生實現Python字符串不同處理函數的功能。
本文2021 年在程序設計基礎中引入對比教學法。通過2019、2020和2021級期末考試成績分布情況,可以考察對比教學的效果。同時利用超星泛雅平臺提供的問卷調查工具,設計了調查問卷了解和分析2021級學生對對比教學模式的反饋。
2019 級、2020 級和2021 級軟件兩個班級的期末考試成績分布情況如圖2 所示。采用對比教學法展開教學的期末考試成績優秀(≥80)率明顯提高,不及格率也有下降。2021 級期末考試90分以上占比達到20%以上,相比2019級的10%和2020級的14%有了很大的提升;80~89分的占比也從13%左右提升至15%。從圖2 可以看到,提高的部分主要來源于60~79 分數段的減少。優秀成績的占比提高,中等學生和不及格學生占比下降,說明使用對比教學法,特別是輔助使用Python語言,一方面可以讓本身學有余力的同學除了掌握基本的C 語言語法知識,還能進一步掌握本課程要求培養的計算思維和編程能力;另一方面,對于能滿足基本要求的同學,則能促進這些同學理解C 語言中諸如函數、數組、指針等語法,熟練掌握了素數判斷、函數遞歸等基本算法的流程和設計思想。

圖2 連續三屆學生成績對比
在學期末,利用超星泛雅課程平臺提供的調查問卷工具設計了對比教學的問卷,主要調查學生的編程基礎、課堂學習效果、課程難點分布以及對比教學對學習本課程的幫助等。從調查問卷的統計結果來看,初高中階段,100%的同學參加了信息技術教育課程;其中有37%的同學接觸過各種形式的編程,對編程有初步的了解;8%的同學在初高中學習或者自學過Py‐thon語言,只有不到1%的同學在進入大學之前接觸過C語言。有68%的同學認為C 語言數據類型是本課程中第一個遇到的難點;所有難點中,指針占比最高,達到89%,隨后分別是基本算法(包括閏年判斷、素數判斷、整數數位求解等算法)、函數、數組、指針、字符串。對于C語言和Python,91%的同學認為Py‐thon 的語法更加簡單,更容易上手;87%的同學認為在課堂中引入Python 語言進行對比教學對學習程序設計基礎課程內容和C語言的語法知識有幫助;24%的同學認為引入Python增加了課程的內容,增加了作業題量;7%的同學認為,學習過程中會將Python和C語言混淆。總的來說,大部分學生比較認可在程序設計基礎課程中引入Python語言,使用對比教學提高教學質量。
Python在程序設計基礎課程中的優勢是語法簡單,相較于C語言更加容易被理解,上手容易,擁有豐富的學習資源;使用Python進行程序設計更容易,而且更符合新生的思維方式。讓學生從簡單的Python入手,大大降低了學習程序設計基礎的門檻,消除了學生對C語言煩瑣語法和復雜代碼的恐懼心理。教學中采用兩種語言實現同一個任務,通過對比,可以深刻理解C 語言的煩瑣語法知識,不僅做到知其然,而且能做到知其所以然。對比學習能夠讓學生聚焦于程序設計基礎中的計算思維和編程思想的訓練;同時能夠有效避免學生以往在學習C語言過程中,程序代碼錯誤率高的問題;幫助學生理解C 語言的語法細節,提高學生編程技能。
雖然對比式教學引入Python,但因其語法簡單,所以并不會過多增加教學內容。對比式教學目的是通過比較,培養學生計算思維、編程等能力。由簡入繁,遵循學生從簡單到復雜的認識規律,從而在教學上做到有的放矢,使課程教學目標更加明確、教學內容安排更易理解,同時可以為后續課程更好地進行銜接,更好地搭建專業知識體系,避免知識點的孤立化、碎片化。在教學過程中,講解C 語言知識點時,對Python 的語法只是做適當延展,為C語言的學習做好鋪墊。在講解煩瑣的C語言語法規則時要有意識與Python進行對比,讓學生認識到每處語法不同的深層次原因,特別是C語言中復雜語法是在歷史背景下有來由的,這樣就實現了知識點的深刻理解。
此外,對比教學法較好地解決了學生學習時難度太大,積極性不高,學習目的不明確的問題。在教學實踐中,分別用Py‐thon 和C 語言給學生布置的作業。Python 比C 語言要簡潔很多,以Python為引入,利用Python的簡潔語法,可以讓學生快速完成布置的作業,掌握諸如數據類型、函數、數組等通用知識點的使用。然后再使用C 語言,使用更為細碎煩瑣的語法,更為細致地完成相同的作業,從而提高學習效果和教學質量。
雖然對比教學法的引入可以一定程度上解決以C 語言為基礎的程序設計基礎教學中遇到的問題,但同時也帶來了課程內容增加、作業量加大等問題;而且以Python作為對比語言,不能解決學生學習C 語言指針時的各種困惑和疑問。對于前一個問題,可以增加課時;或者利用網絡教學平臺,將有關Python的內容事先放置在課程學習平臺上,讓同學預習和復習。對于后面一個問題,學生在學習指針時最大的疑惑在于如何使用,所以可以嘗試將數據結構的部分內容引入,增加學生對指針必要性的理解,以及對使用規則的熟悉。這也是本文接下來要繼續準備做的工作。
通過在程序設計基礎中使用Python和C語言的對比,論述了對比教學法在教學過程中所起的作用,更好地開展了程序設計基礎課程教學,提出了一個新的課堂教學設計。該教學方法的有效實施,對教學質量的提高有較大的促進作用。