婁自婷
(云南國土資源職業學院 云南省昆明市 652501)
現在的期末考試中,很多大中專院校都使用了在線考試系統進行考試,該系統不僅可以提高學生實踐操作能力,做到將理論與實踐相結合;同時,通過該系統老師也可以更便捷、高效、快速地對學生的考試成績進行匯總、整理及分析。但是大多數在線考試系統都只是基于選擇題、判斷題、填空題等客觀題目,很少有主觀題目。而《JAVA 程序設計》課程是高職院校計算機專業的必修基礎課程,該課程主要培養學生動手編寫程序的能力,因此,編程題在期末考試中占了很大的比例。但由于現階段對主觀編程題的技術還不成熟,所以該課程大部分采用的還是人工閱卷。因此,研究如何用計算機實現主觀題自動評分具有較大的現實意義[1]。
早在1966年,就有外國學者Ellis Pagc 對文本相似度檢測進行了研究,提出了讓計算機同人工閱卷一樣對主觀題如作文進行評閱。在對自然語言的文本分析處理方法的研究同時,隨著計算機教育的普及,程序代碼的檢測也在逐漸興起。目前使用比較廣泛的是Online Judge(OJ)在線判題系統,該系統通過對用戶提交的代碼進行編譯和運行,對于能夠運行的程序通過預先設定的測試集來檢測代碼運行的結果,以及運行時間是否在規定范圍之內。該系統采用的是動態評分方式,返回結果有七種:答案不完全正確,運行超出時間限制,超出內存限制,輸出超出限制,運行時出錯,編譯出錯,程序通過,根據不同結果給予分值。
國內學者對主觀編程題自動評分技術也做了大量的研究,并取得了很好的效果。2010年,婁不夜提出了一種基于反射機制、以class 文件為判斷對象的java 編程題自動評分技術[1]。2013年,鄭燕娥融合了程序查錯及局部糾錯技術、基于反射機制的黑盒測試技術、知識要點的正則表達式匹配評分技術,實現了Java 編程題自動評分[2]。2016年,曹亞妮針對C 語言設計了動態測試方法和靜態分析方法相結合的編程題自動評分模型,其中動態測試方法采用黑盒測試對程序運行結果進行檢查,并對程序結構的可信度進行判定,靜態分析在代碼規范化及代碼預處理的基礎上使用基于字符串相似度算法進行自動評分[3][4]。2018年,蔣慧勇提出了一種基于Java 反射機制的自動評分模型,該技術首先讀取考試題中考生寫的程序源代碼,然后調用Java 反射機制對程序進行編譯執行,并將執行結果讀取放入內存,參考答案保存在XML 文檔中,不同答案的組合分數不同,實現需要確定組合類型和對應分數,然后將規則寫成正則表達式[5]。2019年,李震等人提出了通過比較運行結果、Findbugs 分析、文本相似度分析、關鍵詞分析四個評分模塊對代碼進行評價。同樣分為動態測試與靜態分析,首先通過編譯運行代碼,將結果與參考答案進行比較,然后采用Findbugs 對代碼進行靜態分析,找出其中的潛在錯誤和不規范的編程習慣引起的警告,根據問題個數和錯誤等級給出分值。同時配合文本相似度分析,關鍵詞分析得出一個綜合評分。靜態分析工具Findbugs 的引入對發現潛在問題,減少人工預置答案的局限性,提高了系統可用性[6]。
基于上述研究,本文提出一種使用靜態分析與動態模擬執行代碼相結合,適用于簡單的主觀編程題的自動評分技術,并就此設計并實現了完整的自動評分考試系統,為高職院校其他語言的編程題考試系統設計也提供了參考與借鑒。
在程序設計語言考試中,對于編程題而言,要實現某個功能方法可能存在很多種,因為很難用一個簡單的 文本作為標準答案給分。如果指定特定的解題方法,則會存在局限性,限制考生思維,自動評分與人工評閱的誤差也會增大。而是用正則表達式可以描述多種解題方法,既簡單有方便,且正則表達式在文本匹配方面的功能強大、靈活而且高效[2]。
正則表達式是對某種字符串模式規則的描述,是由普通字符(英文字母及數字等)以及元字符組成的文字模式。它是一種可以用于字符串模式匹配和替換的強有力的工具[2]。在Java 中,正則表達式的字符串匹配需要通過java.util.regex 包中的Pattern 和Matcher 兩個類來實現,其中Pattern 類是編譯一個正則表達式的模式對象,Matcher 類是搜索是否匹配的匹配器對象[5]。元字符在正則表達式中的作用非常重要,其構造的準確性主要取決于元字符的應用是否合理。Java 正則表達式常用的元字符如表1所示。

表1:正則表達式常用的元字符
在Java 程序中,“”表示轉義字符,“\”意味著正在插入一個正則表達式斜杠,那么隨后的字符具有特殊意義。比如,“d”表示數字字符,那么在Java 中“\d”就表示正則表達式中的“d”[2]。
為了驗證自動評分技術的合理性和準確性,本人構建了一個原型系統。該系統開發使用了Eclipse 平臺和MySQL 數據庫。系統前端采用jsp + JavaScript + css 的組合技術開發,使用了jQuery 和bootstrap 框架,后端采用SpringBoot 框架實現。
系統分為學生端與管理員端,學生端功能有:注冊、登錄、開始考試、查看成績;管理員端有登錄、學生管理(新增、修改、刪除、查詢)、學生試卷管理(查詢、閱卷)、學生成績管理(查詢、刪除)。數據庫包括管理員表admin、學生成績表performance、學生信息表student、學生試卷回答表student_answer。
學生考卷包括單選題、判斷題、填空題和編程題四個部分。系統核心功能是使用靜態分析與動態模擬執行代碼相結合,完成編程題自動評分。其主要思想是:首先采用動態模擬執行代碼,將考生答案轉換為java 文件進行編譯,能通過編譯運行的結果與參考答案匹配,如果匹配成功或部分數據正確,使用正則表達式對核心代碼進行再次匹配,根據二次匹配的結果給出分值;若編譯運行的結果與參考答案不匹配,將源代碼中的類、主方法、核心代碼進行正則匹配,根據二次匹配的結果給出分值。
學生提交試卷后,管理員在“學生考試管理”界面可查看到所有提交試卷學生名單,如圖1所示。點擊操作下“詳情”按鈕,可進入該生試卷詳情界面,如圖2所示。考試詳情界面由試題、每道試題自動評分結果、參考答案和學生答案,各模塊總分及總得分、提交按鈕組成。該系統保留了修改分數的功能。
下面以一個for 循環輸出1~100 之間的所有偶數程序為例。參考答案如下所示:

該考生程序存在一個語法錯誤,輸出語句、變量名稱與參考答案有細微區別但無誤,系統首先采用動態模擬執行代碼,無法得到運行結果,因此進行靜態分析,使用正則表達式進行二次匹配。該題滿分為10 分,知識要點分為5 個得分點,for 循環中三個表達式每個為2 分,if 語句為3 分,輸出語句為1 分。用正則表達式對這5 個得分點進行描述,具體如下:
第一個得分點:[\s\S]*int [a-zA-Z]+\s*=\s*1;[\s\S]*
第二個得分點:[\s\S]*[a-zA-Z]+\s*<=\s*100;[\s\S]*
第三個得分點:[\s\S]*[a-zA-Z]+\s*\+\+[\s\S]*
第四個得分點:[\s\S]*if\s*\([a-zA-Z]+\s*%\s*2\s*==\s*0\)\s*\{[\s\S]*
第五個得分點:
[\s\S]*System\.out\.print(ln)?\([a-zA-Z]+\s*(\+\s*\"\W+\")?\);[\s\S]*
根據學生結果,語法應扣3 分。經過自動評分,得到學生評分結果為7 分,符合人工評閱結果。系統評分界面如圖3所示。
試題詳情界面可以針對自動評分結果進行二次人工閱卷,也可直接點擊提交。提交之后管理員可進入“學生成績管理”中查看總分數及各模塊得分,如圖4所示。此時學生也可再次進入考生系統查看考試分數。
考慮到學生答案存在多樣性和差異性,本文針對以上編程題抽取了一個班級共50 份考卷,除正確答案外,有11 個存在明顯語法錯誤和差異語句的考生答案。現對這11 個考生答案進行系統評分與人工評分比較,結果見表2,其中與人工評閱的誤差指的是系統評分結果與人工評閱結果的差值。

表2:系統評分與人工評分結果及誤差值
通過上述實驗結果可以看出,系統評分結果與人工評閱結果存在一定的誤差值,但是誤差都在1 分以內,誤差均值控制在0.545,符合自動評分標準。其余編程題通過系統的實現,也滿足實用性、合理性、高效性原則。該系統不僅能減輕教師負擔,還使系統計算的學生答案得分更具公平性和合理性,也為學生及時得到反饋結果提供可能。
本文提出了一種基于Java 語言的主觀編程題自動評分技術,采用動態模擬與靜態分析相結合的方法,首先將考生答案保存為可編譯的java 文件,判斷程序是否可以編譯運行,如果運行成功則返回運行結果,并與參考答案匹配,如果匹配成功或部分數據正確,使用正則表達式對核心代碼進行再次匹配,根據二次匹配的結果給出分值,二次匹配的目的是檢查考生的功能語句是否符合題目要求;若編譯運行的結果與參考答案不匹配或無法運行,將源代碼中的類、主方法、核心代碼進行正則匹配,根據二次匹配的結果給出分值,這樣做可以減少系統自動評分與人工評分的誤差值,但也增加了正則表達式的設計難度。實驗表明,該考試系統運行良好,自動評分結果與人工評閱結果誤差較小,具有較高的準確率。且該系統保留了人工修改分數的功能,對實現上機考試具有一定的參考價值。

圖1:學生考試管理界面

圖2:試卷詳情界面

圖3:xx 學生編程題評分界面

圖4:學生成績管理界面