樊新華,郭曉宇,陳洪軍,郭志
(東北大學計算機科學與工程學院,國家級計算機實驗教學示范中心,沈陽110819)
2012年,教育部等七部門聯合頒布《教育部等部門關于進一步加強高校實踐育人工作的若干意見》的文件,其中著重提出了強化實踐教學環節和深化實踐教學方法改革,要求制訂實踐教學標準,增加實踐教學比重,并重點推行基于問題、基于項目、基于案例的教學方法和學習方法,加強綜合性實踐科目設計和應用[1]。2016年,全球著名的Indeed和Glassdoor等門戶網站通過收集數據,以總結出全球最受歡迎的編程語言及行業內最需要的編程語言,發現C語言依然是編程人員最受大家歡迎的編程語言之一[2]。
《C程序設計》是大學的一門實踐性計算機基礎課程,實踐教學對學習具有重要作用,尤其是信息類專業。《C程序設計》對后續課程學習至關重要。徐一秋等將PBL教學法應用于程序設計實驗教學中,強調以“問題”為中心,以學生自學為主的教學改革[3];陳婷采用“階梯式”、“案例式”課堂教學方法,以“項目驅動式”實踐教學為核心,同時搭建多種自主學習平臺,采用更科學和完善的考核方式[4]。這一系列C程序設計實踐教學改革,對提高實踐教學效果,促進學生掌握程序設計知識,提高編程能力起到了一定促進作用。
因此,根據我校的工科程序設計的實際教學安排及多年的C程序設計實踐教學經驗和總結,提出了專題案例教學方法并應用實驗教學實踐中,對學生的思維能力和編程能力的培養有明顯的提高。
C程序設計的實踐教學,一直是教學工作者探索的一個問題。實驗題目的選擇和設計,對學生編程能力的培養起到了至關重的作用。其中,黃宏博在函數實驗教學中,設計了不同層次的不同問題,并根據學生的水平選取相應的題目[4]。盧瑾等根據學生的認知過程的階段性和實驗難易的層次性,提出了一種階段式分層實驗教學方案[5]。周靖將一個大項目分解成小項目的訓練題目,并應用在不同章節部分的實踐教學中[6]。但是,這些實驗題目內容之間相互獨立或題目難度過大,對大多數學生來說,不能激發學習的興趣,也不能培養學生思維能力。
因此,根據實驗性質和不同培訓目的,可將程序設計課程實驗分為基礎驗證型、設計開發型和研究創新型三個類型[5-6],并且要求學生熟練掌握基礎驗證型實驗,基本掌握設計開發型實驗,鼓勵掌握研究創新型實驗。設計實驗題目時,按照階梯式思路設計,一步一步地提出相關編程要求,引導學生思考和分析問題。題目前后相互關聯,功能進一步完善,以培養學生的邏輯思維能力,引導學會如何解決實際問題[7]。
在C程序設計實踐教學中,將緊密相關的知識,做成相應的專題案例,如有趣的整數、素數探索、猜數游戲、小學四則運算、數值計算、方程求解、學生成績管理等。每個案例所涉及的問題,按基礎驗證型、設計開發型和研究創新型進行設計,前后問題相關聯系,且難度一步步加深。
由于實驗課時有限,為使學生在有限的課堂時間掌握更多的內容,必須精心設計實驗案例。本文以“素數探索”為例,說明具體案例設計過程。
素(質)數不僅是小學所學數論中的最基本的、最重要的概念,也是信息學競賽(NOIP)和程序設計競賽(ACM)中常考的數論知識,而且在密碼學中的加密解密算法中,素數也被廣泛應用于公鑰和密鑰的產生。另外,企業招聘的程序設計面試和計算機等級考試中也有一部分很典型的考題就是素數問題的處理。在《C程序設計》教程中,都會有以素數為主題的例題和編程題目[8],但只是一些零散的知識。在此,以素數的概念為基礎,并依據學生認知的特點,從易到難的順序進行“素數探索”專題案例設計[9-10],具體內容如下:
所謂素數是指除了1和它本身以外,不能被任何整數整除的數,例如17就是素數,因為它不能被2~16的任一整數整除。
問題1:素數判斷
判斷一個正整數是否是素數。
問題2:區間素數
(1)判斷1-200之間有多少個素數,并輸出所有素數。
(2)求m 和 n之間(m<=n)的所有素數,并求所有素數和。
問題3:素數分解
(1)(哥德巴赫猜想)將任意一個大于6的正偶數分解為兩個素數之和。
(2)將一個正整數分解質因數。例如:輸入90,打印出 90=2×3×3×5。
問題4:特殊素數
(1)因為151既是一個素數,又是一個回文數(從左到右和從右到左是看一樣的),所以151是回文素數。寫一個程序來找出范圍[a,b](5<=a<=b<10000)間的所有回文素數。
(2)如果n和n+2都是素數,則稱它們是孿生素數。輸入m(5<=m<=10000),輸出2個均不超過 m的最大孿生素數。例如m=20時候,答案為17、19,m=1000的時候,答案等于881、883。
這些題目主要應用到邏輯結構和循環結構的相關知識,要求學生熟悉邏輯結構和循環結構的使用方法及程序測試方法,并掌握解決問題的一些常見算法。
在實驗教學過程中,應用實驗教學系統平臺對C程序設計實驗進行全程管理,主要包括實驗發布、預習測試、實驗指導和實驗報告遞交等。
(1)實驗預習
實驗預習是對實驗涉及的知識的復習,并深入了解實驗內容,學生必須注重這一環節。通過實驗教學系統發布實驗內容,學生可以根據實驗目的和要求,提前檢查自己對實驗所涉及的基本概念和基礎知識的掌握程度,并獨立完成所布置的相關測試,對錯題的知識點進行查漏補缺。同時,要求學生對于實驗內容中的題目進行分析、寫出解題思路并畫出流程圖,然后編寫出程序。
(2)實驗講解
在每次實驗課前,對于實驗中所用到的基礎知識和基本技巧進行講解,就上述專題案例講解如下:
首先,講解實驗過程中需要的基礎知識,主要包括:
①控制結構語句的格式及使用方法,及使用中的注意事項;
②數組的定義、初始化和輸入輸出方法;
③函數的定義方法、調用方法、參數說明以及返回值,掌握實參與形參的對應關系,以及參數之間的“值傳遞”的方式。
其次,學會分析問題的方法,并會使用流程圖表示算法;掌握一些常用算法,并在編程過程中體驗各種算法的編程技巧,進一步學習調試程序,掌握檢查語法錯誤和邏輯錯誤的方法;分析程序運行效率并進行優化程序。
(3)思路與要求
對于上述案例的實驗教學,對每個問題給出要求和提示,并一步步地提出相關問題,引導學生分析問題,最后完成編程和程序測試工作。具體教學過程如下:
問題1:
主要用到C語言中的分支和循環結構。首先輸入一個數,判斷輸入數是否為正整數。其次判斷一個正整數m是素數有多種方法:
①讓 m依次被2,3,…,m-1除,如果 m不能被2~m-1中的任何一個整數整除,則m是素數。
②讓m依次被2,3,…,m/2除,如果m不能被2~m/2中的任何一個整數整除,則m是素數。
③讓m依次被2,3,…,sqrt(m)除,如果m不能被2~sqrt(m)中的任意一個整數整除,則m為素數。sqrt(m)為m的平方根。
引導學生用不同的方法來實現素數的判斷,并提示用到了sqrt()函數時,別忘了引入頭文件#include<math.h>。
為了減少循環判斷的次數,提高程序的執行效率,因此,編程需要想辦法減少循環的檢查次數。通過比較這三種方法的執行次數的數量級,明白程序優化方法,第③種方法判斷速度最快,可以采用這種方法。
問題2:
(1)主要用到C語言中的分支、循環和循環嵌套結構的知識。提示學生應用問題1的方法進行素數的判斷。也可以要求在顯示輸出結果時,要求每行輸出5個素數,最后一行顯示總個數,等等。
(2)方法同問題2(1)。但要判斷輸入m和n值是否符合要求,并給出相應的提示信息。
問題3:
(1)設n為大于等于6的一個偶數,可將其分解為n1和n2兩個數,分別檢驗n1和n2是否為素數,若都是,則該數得到驗證。若n1不是素數,就不必再檢查n2是否為素數。先從n1=3開始,檢驗n1和n2(=nn1)是否為素數。然后使n1+2再檢驗n1,n2是否為素數……直到n1=n/2為止。
(2)從1到N先找出最小的質因數,如果等于本身,那么說明只有一個質因數,如果不是,那么將該質因數打印出來,并將N/該質因數作為新的N值進行運算。
對n進行分解質因數,應先找到一個最小的質數k,然后按下述步驟完成:
①如果這個質數恰等于n,則說明分解質因數的過程已經結束,打印出即可。
②如果n<>k,但n能被k整除,則應打印出k的值,并用n除以k的商,作為新的正整數n,重復執行第一步。
③如果n不能被k整除,則用k+1作為k的值,重復執行第一步。
改進:因為在所有的質數中只有2是偶數外,其他的質數都是奇數。所以i可以一次+2跳過所有的偶數。不過2要特別處理。
問題4:
(1)對于判斷一個正整數是否是回文數,應該首先要明白回文的概念,其次是如何將一個正整數進行反轉過來,最后是判斷是否是回文數。如何將一個正整數進行反轉有不同的方法,可以應用循環、取模、整除的知識;也可以轉換成字符串,可以使用字符串操作的進行反轉。求正整數反轉的方法很多,這里提供一個簡單的方法,代碼如下:
int m=0;
while(n>0)
{
m=m*10+n%10;
n=n/10;
}
就可以將n進行反轉數位,變為m。
(2)可以把所有滿足條件的孿生素數找出來再比較大小,但這樣過于繁瑣,所以,我們只需用一循環,從小于m的數開始倒序查找符合條件的孿生素數,一找到就輸出,那輸出的便是最大孿生素數了。
在實際編程過程中,考慮問題必須全面、嚴謹。例如這里討論的是素數,所以輸入條件時,一定要對其輸入值判斷,使其滿足實際和題目的要求。可以用不同方法實現,例如可使用篩選法(Eratosthenes)求出素數[10],并用數組保存整數。
當生成大量數據時,可以將數據保存到文件中,就涉及到文件的讀寫知識。可以將這些問題應用到不同章節中,在控制結構部分,練習分支、循環結構的知識;在數組部分,練習數組的定義、讀寫的知識;在函數部分,練習函數的定義、調用的知識;在文件部分,練習文件的創建、讀寫的知識。
在實際實驗教學中,對基礎不同的學生,設計不同的問題,實行分層實驗教學。通過這種分層案例可以讓學生掌握所學程序設計知識,更進一步訓練了學生分析實際問題能力和創新思維。
(4)實驗考核
為了真正從程序設計能力角度對學生進行評價,采用以下幾方面進行實驗課程的考核,并各項分配不同的權重,以期激發學生平時注重實踐和能力培養。
①現場驗收:通過學生講解、提問、答辯等方面的表現,了解學生對分析問題、編程技能、程序測試能力的水平。
②自主創新:在所實現程序的基礎上,進一步提出新的要求,以考核學生的自主思考與獨立實踐能力。
③實驗考試:通過一組編程題目,測試學生對解決實際問題的編程能力。
④實驗報告:實驗報告要求規范性與完整性,重點要寫清設計思路和程序清單。
C程序設計的實驗環節對學生實際動手能力和解決實際問題能力的培養有著重要作用。根據學生興趣和專業的實際情況,結合實驗教學的目標和要求,提出實驗專題案例教學方法。通過一個具體的“素數探索”專題案例,說明專題案例的設計、實驗教學的全過程。在專題案例設計中,所提問題的知識點前后相關、難度依次加強;在專題案例實驗教學中,對不同問題提出不同要求并實現編程。將專題案例教學法應用到《C程序設計》實驗課中,大大地提高了學習編程的興趣,激發了學生討論問題的熱情。同時,使學生掌握程序設計知識,培養了學生分析問題和編程能力,并養成嚴謹縝密思考問題的習慣。另外,要達更良好的教學效果,實驗教學環節還需要進一步重視對學生引導。專題案例實驗教學法對于其他語言程序設計(如C++、C#、Java、Python等)的實驗教學,也是一種有益的借鑒。