何凱
(黃驊市職業技術教育中心 河北省黃驊市 061100)
筆者在實際工作中,發現傳統的教學模式會讓C 語言初學者感覺學習很困難,教學質量很難保證。目前國內外已經研究并開發出了許多測評系統,但是總是因為某些原因不具有通用性。一方面因為有些系統不是開源的,我們無從加以利用;另一方面有些系統雖然開源,但是并不符合我們的自身需求,系統所針對的人群是有限制的,不滿足當前教學需求。為此,需要為特定的教學環境研究和設計一套合適的系統,以便提高學生的學習興趣和主動性,并及時反饋學生的學習情況,進而幫助教師改善教學過程,提高整個課程的教學質量。
程序評測系統的設計是有一定的目標群體作為基礎,所設置的題目也是針對這些群體的特定需求所設定的。此次教學模式改革和系統設計開發所針對的使用人群是中等職業學校的學生,學習的算法規模較小,學習的理論知識比較淺顯,程序比較簡單。因此每個題目都僅僅考察一個知識點,包括編程題,編程題的絕大部分代碼系統都會提供,僅僅需要學生寫很少的代碼,讓學生稍微一想就能成功,這樣才能激發他們的學習興趣與主動性。
對于系統的要求是方便攜帶,教師很方便地推送測試題目,學生通過簡單操作就能正常運行題目,通過動態測試判定正確與否。因此,我們對于每個題目只需要判定對與錯就可以,因為測試題目本身就沒有太多的步驟。
根據以上分析,我們對系統進行如下設計。
結合《C 語言程序設計》教學大綱,為每個知識點制定相應配套的選擇題和編程題,適合中職生的題目,形成題庫,保存在數據庫中。系統采用ACCESS 數據庫,ACCESS 數據庫小巧、方便,便于攜帶,但是對于并發訪問的控制不理想,那么該系統如何提高ACCESS 數據庫的并發訪問數量呢。
系統采用了簡單而有效的方法:對數據庫文件的讀寫訪問分開,讀寫互不影響;所有的讀進程使用互斥,將讀進程線性化,所有的寫進程使用互斥,將所有的寫進程線性化,這樣同時訪問該數據庫文件的進程最多只有兩個,這樣就不會因為并發訪問量大而報錯,通常情況10 多個并發訪問,Access 數據庫就可能報錯,經過這樣處理后,同時幾百個客戶端訪問都不成問題。
服務器與客戶端使用datasnap 三層架構,當客戶端連接服務器時,服務器會創建一個新的線程,該線程中對數據庫文件進行打開和查詢。多個客戶端連接服務器時,服務器就會創建多個線程,那么這些線程都會對數據庫文件進行打開和查詢,并且在服務器內存中保存了相應的數據。除了采用上面互斥的方法外,當線程讀取數據后,客戶端要關閉自己的鏈接,這樣會引起服務器將相應的線程關閉,包括關閉數據庫文件,釋放服務器內存中的數據,這樣能保證服務器內存夠用,數據庫文件不會因為并發而報錯。
將題目的自動化評測放在學生機上運行。當客戶端得到題目的同時,也得到了測試題目的字符串,客戶端自身使用測試字符串測試學生編寫的程序,將測試結果提交服務器。服務器與客戶端對應的線程將測試結果,使用消息發給服務器主線程,服務器主線程負責寫數據庫文件。教師檢查學生的答題情況。
(1)當客戶端查詢數據時,服務器的線程fdquery2 查詢到數據題目,將數據傳遞給clientdataset1,隨后關閉線程與數據庫文件的連接,服務器通過DataSetProvider2 將clientdataset1 中的數據提供給客戶端。代碼如下:

(2)當客戶端把學生作答情況提交給服務器時,服務器線程通過消息報告給服務器主線程,由主線程寫入數據庫文件,代碼如下:

(3)當學生交卷時,服務器線程將信息做成消息發送給服務器主線程處理,將考生信息寫入消息里,使用SendMessage 發送消息,操作如下:

(4)服務器主線程接收到消息后,將學生作答情況寫入數據庫,由于是寫數據庫,所以要使用臨界區,保證寫數據庫這個操作的原子性,代碼如下:

在系統啟動時,進行臨界區的初始化,代碼如下:

(1)客戶端下載下載試題,clientdataset2.Open 時下載數據,如果數據量比較大,則會出現假死的情況,卡在那里,特別是對于廣域網的時候,可能需要點時間,所以我們增加了線程的處理機制。把下載數據放到了線程里。并且通過myThread.Finished 來判斷數據是否下載完畢,期間可以更新界面。代碼如下:

(2)數據下載完畢后,通知服務器已經下載完畢,服務器作相應的標記,而后客戶端通過SQLconnection1.Close 關閉整個鏈路,以便服務器釋放內存、數據庫、線程池等資源。代碼如下:


(3)客戶端提交學生作答,提交后,通過sqlconnection2.Close 關閉這條與服務器的鏈路,也就是說每次提交作答,客戶端都要先連接服務器,提交作答后再關閉鏈接,釋放資源,這個過程相對于我們審題做題的過程來說,用時很少。特別是對于使用了花生殼一類的軟件來說,我們局域網的服務器可以作為廣域網的服務器來使用,但是花生殼限制了鏈接數,該系統現在的設計正好滿足花生殼的這個限制,同一時刻只有少量的TCP 鏈路存在,其他鏈路都及時關閉了。相關代碼如下:

(4)對于選擇題和填空題,客戶端直接將學生作答信息發送給服務器;而對于編程題,該系統在客戶端進行分析。服務器的數據庫中事先準備好以下材料:編程題題目,測試用字符串,測試用結果。客戶端接收到編程題目的同時,也得到了測試用字符串。舉例說明,以下編程題目要求實現功能:通過鍵盤輸入n、m,統計n 到m 的累加和,m 和n 計算在內,sum 用于輸出累加和。

編制題目時,在題目中設置標志,如上程序所示的注釋部分,只能在標志范圍內編寫學生自己的程序,其他地方不可以編輯,客戶端會對各部分做校驗。學生嘗試編寫程序完成既定功能,當學生點擊提交的時候,客戶端利用命令行argc 和argv 將測試用字符串輸入到程序中,對學生作答的程序進行測試運行,并將產生的運行結果作為作答提交給服務器,服務器進行判斷。
由于本方案是特定的服務器,使用了用戶自定義的用戶網絡協議,因此業界通用的一些測試程序不能很好的完成測試。鑒于此,筆者自己設計了測試方案。模擬多用戶鏈接服務器,進而模擬大量用戶連接服務器,服務器都能穩定的運行,并且符合項目各項要求。