崔 玲,張榮茜,鄭小靜
(北京工業(yè)大學(xué) 信息學(xué)部,北京 100124)
C 語言程序設(shè)計(jì)課程實(shí)踐性較強(qiáng),是最能體現(xiàn)計(jì)算思維的一門課程,對(duì)于非計(jì)算機(jī)專業(yè)的學(xué)生來說有一定難度。語法點(diǎn)多、內(nèi)容抽象,即使掌握了語法,學(xué)生在分析問題和解決問題時(shí)仍會(huì)感到無從下手,久而久之,一些同學(xué)喪失學(xué)習(xí)積極性,一些同學(xué)雖然很努力,但是因?yàn)槌醮谓佑|程序設(shè)計(jì),顯得非常吃力。課堂教學(xué)如何引導(dǎo)學(xué)生快速接受程序設(shè)計(jì)理論,是一線教師著重思考的問題。
建構(gòu)主義學(xué)習(xí)理論[1-2]強(qiáng)調(diào)要以學(xué)生為中心,在學(xué)習(xí)過程中充分發(fā)揮學(xué)生的主動(dòng)性,能夠讓學(xué)生在原有知識(shí)和經(jīng)驗(yàn)的基礎(chǔ)上主動(dòng)學(xué)習(xí)、構(gòu)建新的知識(shí)。建構(gòu)主義學(xué)習(xí)理論的主要教學(xué)方法有3種:支架式教學(xué)、拋錨式教學(xué)、隨機(jī)進(jìn)入教學(xué)。
支架式教學(xué)指的是為學(xué)習(xí)者建構(gòu)知識(shí)的概念框架,該思想來源于心理學(xué)家維果斯基的“最近發(fā)展區(qū)”理論[3-4]。維果斯基認(rèn)為,學(xué)習(xí)者對(duì)于所要解決的問題和原有能力之間存在差異,這個(gè)差異就是“最近發(fā)展區(qū)”,而教育就是要消除這個(gè)差異,同時(shí)引導(dǎo)學(xué)習(xí)者進(jìn)入更高水平的“最近發(fā)展區(qū)”。支架式教學(xué)主要由以下環(huán)節(jié)組成。
(1)搭建腳手架。圍繞知識(shí)點(diǎn),按照“最近發(fā)展區(qū)”的要求建立概念框架。
(2)進(jìn)入情境。將學(xué)生引入一定的問題情境。
(3)獨(dú)立探索。教師給予適時(shí)提示,讓學(xué)生獨(dú)立探索,在概念框架中不斷提升自己。
(4)協(xié)作學(xué)習(xí)。學(xué)生進(jìn)行協(xié)商討論,在集體討論的基礎(chǔ)上完成對(duì)知識(shí)的意義建構(gòu)。
(5)學(xué)習(xí)效果評(píng)價(jià)。對(duì)學(xué)習(xí)效果的自我評(píng)價(jià)和相互評(píng)價(jià)。
建構(gòu)主義認(rèn)為,學(xué)習(xí)者獲取知識(shí)應(yīng)該主動(dòng)去學(xué)習(xí)、體驗(yàn),而不是由教師傳授。該方法也被稱為案例教學(xué),或者基于問題的教學(xué)。
拋錨式教學(xué)主要由以下環(huán)節(jié)組成:①創(chuàng)設(shè)情境。為學(xué)生提供與實(shí)際情況類似的問題情境。②確定問題。為學(xué)生選擇與當(dāng)前學(xué)習(xí)主題相關(guān)的問題作為學(xué)習(xí)的主要內(nèi)容。③自主學(xué)習(xí)。為學(xué)生提供求解問題線索,讓學(xué)生主動(dòng)搜集信息、思考方案來解決問題。④協(xié)作學(xué)習(xí)。⑤學(xué)習(xí)效果評(píng)價(jià)。
對(duì)于復(fù)雜問題,學(xué)生可選擇不同途徑、不同方式進(jìn)入同樣教學(xué)內(nèi)容的學(xué)習(xí),這就是“隨機(jī)進(jìn)入教學(xué)”。隨機(jī)進(jìn)入教學(xué)主要由以下環(huán)節(jié)組成:①呈現(xiàn)基本情境。②隨機(jī)進(jìn)入學(xué)習(xí)。③思維發(fā)展訓(xùn)練。教師提出的問題要有利于促進(jìn)學(xué)生認(rèn)知能力的發(fā)展,要有利于建立學(xué)生的思維模型。同時(shí)還可提出一些延伸問題培養(yǎng)學(xué)生發(fā)散性思維。④協(xié)作學(xué)習(xí)。⑤學(xué)習(xí)效果評(píng)價(jià)。
在建構(gòu)主義學(xué)習(xí)理論的指導(dǎo)下,結(jié)合程序設(shè)計(jì)課程的特點(diǎn),進(jìn)行課堂教學(xué)設(shè)計(jì),引導(dǎo)學(xué)生在原有知識(shí)基礎(chǔ)上快速構(gòu)建新知識(shí)。
學(xué)習(xí)循環(huán)之前,學(xué)生已經(jīng)學(xué)會(huì)如何輸出1 行“Happy New Year!”,接下來讓學(xué)生思考:如何輸出10 行“Happy New Year!”?學(xué)生可能回答:復(fù)制、粘貼,那么可以再問:如果輸入1 000 行呢?
在給出對(duì)應(yīng)的for 循環(huán)代碼之后,可以讓學(xué)生繼續(xù)思考:
如何輸出1 到10?
如何輸出1、3、5、7、9 的序列?
編寫程序驗(yàn)證學(xué)生的想法,最后讓學(xué)生總結(jié)語句的執(zhí)行順序,以及影響輸出結(jié)果的語句都有哪些。
通過以上實(shí)例,教師可以自然地引出for 循環(huán)的語法格式,并指出for 循環(huán)的四要素:循環(huán)變量初值、循環(huán)條件、循環(huán)變量變化規(guī)律和循環(huán)體。
再比如,講解例題“輸入n 個(gè)學(xué)生成績(jī),計(jì)算平均分”之后,讓學(xué)生思考如何編程實(shí)現(xiàn)“輸入班級(jí)學(xué)生成績(jī),計(jì)算平均分(其中班級(jí)人數(shù)未知,可用-1 表示輸入結(jié)束)”。學(xué)生根據(jù)已經(jīng)學(xué)習(xí)過的for 語句可以編程實(shí)現(xiàn),但是會(huì)發(fā)現(xiàn)循環(huán)條件與循環(huán)變量無關(guān)。此時(shí)教師可引出while 語句,并通過比較,分析for 語句和while 語句的相似和不同之處。最后進(jìn)行總結(jié):雖然for 語句、while 語句均可實(shí)現(xiàn)循環(huán)問題的求解,但由語法形式可知,for 語句更適合循環(huán)次數(shù)已知的問題,而while 語句則適合循環(huán)次數(shù)未知的問題。
不僅例題講解要由淺入深,而且實(shí)踐練習(xí)也要由易到難,如掌握了for 語句的基本語法格式之后,教師可以設(shè)計(jì)與例題相似的題目,讓學(xué)生進(jìn)行編程練習(xí)。
練習(xí)1:輸出A 到Z;
練習(xí)2:輸出AaBb……Zz;
練習(xí)3:輸出100 到1 000 之間的偶數(shù)。
對(duì)于練習(xí)1,可以提示學(xué)生,利用已學(xué)知識(shí)解決問題:①字符類型可以參與算術(shù)運(yùn)算,如ch=ch+1;②語法中未規(guī)定循環(huán)變量必須是整型。
練習(xí)2 有一定難度,雖然與練習(xí)1 相似,但是多數(shù)學(xué)生無法一下總結(jié)出AaBb……Zz 的規(guī)律。此時(shí)教師可以提醒:在已學(xué)過的分支語句中,執(zhí)行的語句可以是復(fù)合語句,那么循環(huán)語句中的循環(huán)體也可以是復(fù)合語句,將Aa、Bb、Cc 視為一組即可找到規(guī)律:
練習(xí)3 難度再次增加,循環(huán)體是分支語句,這是循環(huán)語句與分支語句的簡(jiǎn)單混合應(yīng)用。
再比如,循環(huán)嵌套是學(xué)習(xí)的一個(gè)難點(diǎn),通過對(duì)已有案例的升級(jí)改造,可以讓學(xué)生在已有知識(shí)基礎(chǔ)上,輕松接受循環(huán)嵌套。
案例1:已知如何輸出1 到10,思考如何輸出10 行的1 到10。
由該案例引出雙重循環(huán),此處要重點(diǎn)分析內(nèi)層循環(huán)變量和外層循環(huán)變量的變化規(guī)律。同時(shí)可讓學(xué)生練習(xí)如何輸出九九乘法表、三角圖形等。
案例2:已知如何計(jì)算n!,思考如何計(jì)算1+2!+3!+…+n!。
在該案例中,要著重注意變量初值及其所在位置問題。存儲(chǔ)求和結(jié)果的變量初值應(yīng)為0,放在外層循環(huán)之前。內(nèi)層循環(huán)用于求階乘,那么存儲(chǔ)求階乘的結(jié)果,初值為1,應(yīng)放在內(nèi)層循環(huán)之前外層循環(huán)之內(nèi)。素?cái)?shù)問題是循環(huán)結(jié)構(gòu)的典型問題,也是枚舉算法的一個(gè)典型應(yīng)用。在講解素?cái)?shù)問題之后,可給出以下兩個(gè)案例,繼續(xù)學(xué)習(xí)循環(huán)的嵌套用法,也可讓學(xué)生進(jìn)一步了解枚舉算法的基本思想。
案例3:已知如何判斷一個(gè)數(shù)是否是素?cái)?shù),思考如何輸出100 到1 000 之間的素?cái)?shù)。
案例4:通過講解雞兔同籠問題,讓學(xué)生練習(xí)百錢買百雞、搬磚等問題。同時(shí),還可讓學(xué)生思考有無多種解法,如雞兔同籠問題的常規(guī)解法是二重循環(huán),思考是否可用一重循環(huán)解決。
素?cái)?shù)問題對(duì)于非計(jì)算機(jī)專業(yè)的學(xué)生來說,問題簡(jiǎn)單,但實(shí)現(xiàn)時(shí)容易出錯(cuò)。關(guān)鍵點(diǎn)在于什么時(shí)候給出判定結(jié)果,很多同學(xué)往往在循環(huán)中直接給出判定結(jié)果,如:
教師在講解時(shí)不用立即否定學(xué)生想法,可運(yùn)行程序進(jìn)行測(cè)試,通過運(yùn)行結(jié)果學(xué)生會(huì)逐漸意識(shí)到問題所在。這時(shí)教師和學(xué)生再一起思考解決方法,在這樣不斷嘗試不斷修改的過程中逐步理清思路,達(dá)到求解問題的目的。這個(gè)過程會(huì)讓學(xué)生有種成就感。
同一問題往往有多種解法,在練習(xí)素?cái)?shù)問題時(shí),會(huì)有不少學(xué)生的解法思路都很巧妙。教師可讓學(xué)生展示給大家,然后一起分析其優(yōu)劣。
方法一:
該方法定義了變量flag,表示能整除n 的個(gè)數(shù),循環(huán)結(jié)束后,如果flag 為零,表示n 為素?cái)?shù),否則n 不是素?cái)?shù)。
容易理解大于n/2 的數(shù)不會(huì)整除n,程序中循環(huán)條件為i<n/2,比i<n 減少了循環(huán)次數(shù),提高了運(yùn)行效率。
方法二:
方法二較方法一有3 點(diǎn)變化:①變量flag 的含義。flag 為1 表示n 是素?cái)?shù),flag 為0 表示n不是素?cái)?shù)。這種變量稱為邏輯型變量,常用于邏輯判斷問題,一般取值為1 或0,表示是或否、真或假。②可以證明,一個(gè)素?cái)?shù)的兩個(gè)因數(shù),至少有一個(gè)小于等于根號(hào)n。sqrt(n)是判斷素?cái)?shù)的最小臨界條件。因此該方法中循環(huán)條件是i<=sqrt(n),進(jìn)一步減少了循環(huán)次數(shù)。③break的應(yīng)用。只要某個(gè)i 可以整除n,則執(zhí)行break,跳出循環(huán),再次減少循環(huán)次數(shù)。對(duì)于復(fù)雜程序來說,減少循環(huán)次數(shù)會(huì)極大提高程序運(yùn)行效率,教師可以借此向?qū)W生介紹一下算法復(fù)雜度問題,讓學(xué)生認(rèn)識(shí)到算法在程序設(shè)計(jì)中的重要性。
方法三:
該程序非常簡(jiǎn)練,但不易理解,該程序思路可由方法二推出。方法二中使用了break 語句,如果滿足n%i==0,則結(jié)束循環(huán),也就是說n%i!=0 是循環(huán)條件之一。因此循環(huán)條件是n%i!=0&&i<=sqrt(n),循環(huán)結(jié)束表示這兩個(gè)條件至少有一個(gè)不滿足。如果不滿足n%i!=0,表示存在一個(gè)數(shù)可以整除n,則n 不是素?cái)?shù)。
2.4.1 將應(yīng)用問題分類,提高學(xué)生求解問題能力
編程的難點(diǎn)不在于語法格式,而是如何將實(shí)際問題的求解方法轉(zhuǎn)化為符合語法格式的程序語句。教師可以將應(yīng)用問題進(jìn)行分類,為學(xué)生求解問題提供思路,幫助學(xué)生逐步提高利用程序求解問題的能力。一般來說,可用循環(huán)結(jié)構(gòu)解決的應(yīng)用問題有如下幾種:①有規(guī)律輸出問題,如輸出Fibonacci 序列。②累加累乘問題,如求n!。③連續(xù)輸入并進(jìn)行計(jì)算的問題,如輸入班級(jí)學(xué)生成績(jī)并求平均分、最高分。④枚舉問題,如素?cái)?shù)、雞兔同籠問題。
每類問題可講解1~2 個(gè)案例,然后讓學(xué)生獨(dú)立求解類似問題加以練習(xí)。也可對(duì)案例進(jìn)行改編,如將問題:“根據(jù)公式,計(jì)算前n 項(xiàng)之和,求解π 的近似值”,改編為“根據(jù)公式,求解π 的近似值,直到最后一項(xiàng)的絕對(duì)值小于10-6”。
2.4.2 將求解步驟模式化,重復(fù)訓(xùn)練,培養(yǎng)學(xué)生計(jì)算思維能力
思維能力的培養(yǎng)離不開大量重復(fù)的訓(xùn)練。對(duì)每一個(gè)案例,均按照“問題描述、問題分析、算法描述、程序?qū)崿F(xiàn)、運(yùn)行結(jié)果、程序分析”6 個(gè)步驟[5],進(jìn)行問題求解,逐步引導(dǎo)學(xué)生掌握程序設(shè)計(jì)的基本方法,培養(yǎng)學(xué)生計(jì)算思維能力。
以位數(shù)分解問題為例。
(1)問題描述。
輸出1 至10 000 之間每位數(shù)的乘積小于每位數(shù)的和的數(shù)。
(2)問題分析。
類似解數(shù)學(xué)題,首先分析題意。該題最終要求輸出一些數(shù),這些數(shù)的范圍是1 到10 000。由此可知輸出是一個(gè)循環(huán),循環(huán)范圍是1 到10 000。該部分算法可描述如下:
再分析,輸出的數(shù)是要滿足一定條件的,即每位數(shù)的乘積小于每位數(shù)的和。算法修改如下:
最后分析如何求和、求乘積,題目要求的是i 的每位數(shù)的乘積與每位數(shù)的和。因此要求和與積,首先要分解i,得到它的每個(gè)位數(shù)。
如何分解一個(gè)數(shù)呢?在學(xué)習(xí)算術(shù)運(yùn)算時(shí),已經(jīng)學(xué)過如何分解位數(shù)確定的數(shù),如i 是三位數(shù),則i%10 即個(gè)位數(shù),(i/10)%10 即十位數(shù),(i/100)%10 即百位數(shù)。但是該題目中位數(shù)可能是1、2、3、4、5,該如何分解出它的每位數(shù)呢?分解操作何時(shí)結(jié)束呢?我們只能嘗試尋找有無規(guī)律可循。先用實(shí)際的數(shù)進(jìn)行嘗試,然后試著總結(jié)規(guī)律,見表1。
通過實(shí)例分析可知,分解位數(shù)可由循環(huán)實(shí)現(xiàn),重復(fù)的操作是:
什么時(shí)候停止重復(fù)操作?當(dāng)m 為0 時(shí)。
分解位數(shù)的目的是求其和與積,因此在分解的同時(shí)計(jì)算和與積。該部分算法描述如下:
表1 分解位數(shù)實(shí)例分析
(1)算法描述。
根據(jù)問題分析,求解問題的完整算法如下:
(2)程序?qū)崿F(xiàn)。
類似中英文翻譯,將算法轉(zhuǎn)換為C 語言代碼。
(3)程序分析。
該例的難點(diǎn)在于如何分解一個(gè)不確定位數(shù)的數(shù)。已知確定位數(shù)的分解方法,那么可以嘗試總結(jié)不定位數(shù)的求法是否與之有相同之處。容易知道,個(gè)位數(shù)為m%10,十位數(shù)對(duì)于m/10 來說也是個(gè)位數(shù),百位數(shù)對(duì)于(m/10)/10 也是個(gè)位數(shù),因此可以把問題歸結(jié)為求個(gè)位數(shù),問題就變得簡(jiǎn)單且有規(guī)律,通過幾個(gè)實(shí)例分析可得出求解規(guī)律。
另外要注意,該例程序中的m=i,為什么不直接用i 呢?原因在于m 是變化的,最終的m 會(huì)為0,而i 則是要輸出的數(shù),而且i 是外層循環(huán)的循環(huán)變量,不能輕易改變。初學(xué)者容易犯的錯(cuò)誤就是在循環(huán)中不小心改變了循環(huán)變量的值,而這種錯(cuò)誤屬于邏輯錯(cuò)誤,難于察覺,很難找到錯(cuò)誤所在。由此還可以給學(xué)生介紹一些調(diào)試程序的方法,比如在可疑語句前后加入輸出語句查看變量變化,或者直接使用編譯軟件提供的調(diào)試工具。
do-while 語句較為簡(jiǎn)單,可對(duì)比while 語句學(xué)習(xí)。與while 語句不同,do-while 語句是至少執(zhí)行一次循環(huán)體,而while 語句則可能一次都不執(zhí)行。
上述程序段中while 循環(huán)條件不滿足,不會(huì)進(jìn)入循環(huán),執(zhí)行之后,s=0,n=3。而下面程序段中do-while 語句會(huì)先執(zhí)行一次循環(huán)體,再退出循環(huán),執(zhí)行之后,s=3,n=4。
同樣,可以對(duì)比學(xué)習(xí)break 和continue。在循環(huán)中,break 是結(jié)束循環(huán),類似于游戲中的“Game over!”;continue 是結(jié)束本次循環(huán),類似于游戲中的“Try again!”。
上述程序段輸出1、2、3、4,隨后跳出循環(huán)。而下面的程序則會(huì)進(jìn)入死循環(huán),因?yàn)閤 會(huì)一直停留在5,循環(huán)條件一直未能打破。
對(duì)于實(shí)踐性較強(qiáng)的課程來說,課堂教學(xué)安排在教室上課,非常不利于學(xué)生實(shí)踐能力的培養(yǎng)。我校從2010 年開始,將C 語言程序設(shè)計(jì)等計(jì)算機(jī)公共基礎(chǔ)課程安排在機(jī)房上課,授課模式由講練分離變?yōu)檫呏v邊練,在學(xué)習(xí)一個(gè)知識(shí)點(diǎn)之后即刻讓學(xué)生進(jìn)行練習(xí)。由近幾年的教學(xué)評(píng)價(jià)來看,這種模式有助于激發(fā)學(xué)生學(xué)習(xí)興趣,培養(yǎng)學(xué)生實(shí)踐能力,提高教學(xué)效果。
循環(huán)結(jié)構(gòu)是C 語言程序設(shè)計(jì)的重點(diǎn)和難點(diǎn)內(nèi)容,基于建構(gòu)主義的教學(xué)方法可以讓學(xué)生在原有知識(shí)基礎(chǔ)上,由易到難、由淺入深逐步引導(dǎo)學(xué)生主動(dòng)去分析問題、解決問題。多年教學(xué)實(shí)踐證明,該方法有助于培養(yǎng)學(xué)生的計(jì)算思維能力,有助于激發(fā)學(xué)生的學(xué)習(xí)興趣,培養(yǎng)學(xué)生的自主學(xué)習(xí)能力。