舒新峰,賈敬霞,何孝敏,付穩(wěn)穩(wěn)
(西安郵電大學(xué) 計(jì)算機(jī)學(xué)院,陜西 西安 710121)
隨著互聯(lián)網(wǎng)技術(shù)在“C程序設(shè)計(jì)”教學(xué)過程中的應(yīng)用,一些高校引入C程序在線考試系統(tǒng)實(shí)現(xiàn)自動(dòng)閱卷[1-3],而現(xiàn)有的考試系統(tǒng)主要采用動(dòng)態(tài)評(píng)測(cè)和靜態(tài)分析兩類技術(shù)。動(dòng)態(tài)評(píng)測(cè)通過編譯運(yùn)行待判定程序并輸入測(cè)試用例集,根據(jù)程序輸出結(jié)果與預(yù)期結(jié)果是否一致來評(píng)分[4-6]。當(dāng)程序存在語法錯(cuò)誤而無法運(yùn)行時(shí),此類系統(tǒng)會(huì)給予0分成績,評(píng)分結(jié)果較為粗糙,不符合實(shí)際教學(xué)需求。
靜態(tài)分析方法通過分析待判定程序的結(jié)構(gòu)及語義特征獲取評(píng)分結(jié)果,主要分為兩種。一種通過統(tǒng)計(jì)程序代碼行數(shù)、函數(shù)、循環(huán)結(jié)構(gòu)等程序?qū)傩蕴卣鞯臄?shù)量給出評(píng)分[7],但因沒有考慮程序語義而導(dǎo)致評(píng)分結(jié)果比較粗糙。另一種將學(xué)生程序和答案程序轉(zhuǎn)化為中間形式,如控制流圖[8,9]、抽象語法樹[10,11]、系統(tǒng)依賴圖[12,13]等,然后比較兩者的相似度進(jìn)行評(píng)分,但現(xiàn)有的中間表示形式不能準(zhǔn)確表達(dá)程序結(jié)構(gòu)及語句依賴關(guān)系,降低了評(píng)分的準(zhǔn)確性。
針對(duì)上述問題,本文提出面向語句分值的C程序靜態(tài)評(píng)分方法,通過在答案程序中標(biāo)注描述評(píng)分細(xì)則的語句分值,引入能夠準(zhǔn)確描述語句控制、數(shù)據(jù)依賴關(guān)系的程序語句依賴圖作為中間表示結(jié)構(gòu)。評(píng)分過程如圖1所示,首先對(duì)待判定C程序進(jìn)行標(biāo)準(zhǔn)化,消除表達(dá)多樣性問題,具體策略見參考文獻(xiàn)[10];其次構(gòu)造帶有語句分值的程序語句依賴圖;最后匹配待判定程序和答案程序間路徑片段集合實(shí)現(xiàn)程序評(píng)分。

圖1 靜態(tài)評(píng)分過程
為支持命題教師準(zhǔn)確描述評(píng)分細(xì)則,根據(jù)知識(shí)點(diǎn)、語句的重要性對(duì)答案程序中的語句片段設(shè)置不同分值,即對(duì)答案程序中的單行、多行語句設(shè)定不同注釋方式來描述考察的知識(shí)點(diǎn)及分值權(quán)重。當(dāng)一個(gè)分值表示多行語句時(shí),在這些語句的第一條源碼后面標(biāo)注/*ktype_symbol- -score*/表示分值的開始,最后一條語句標(biāo)注/*ktype_symbol*/表示該分值所表示語句范圍結(jié)束;而分值表示一條語句時(shí),則在這條語句后標(biāo)注/*- -score*/表示;此外用/*sum- -score*/表示整個(gè)答案程序的分值。其中ktype_symbol表示知識(shí)點(diǎn)符號(hào),具體取值見表1,score為分值。例如,“求π值問題”答案程序中語句分值的標(biāo)注情況如圖2所示。

圖2 “求π值問題”的答案程序
針對(duì)現(xiàn)有的評(píng)分方法不能精確表示程序語句間執(zhí)行次序及依賴關(guān)系、選擇/循環(huán)的語法結(jié)構(gòu),對(duì)系統(tǒng)依賴圖[12,13]進(jìn)行改進(jìn),引入了程序語句依賴圖(program statement dependency graph,PSDG)來描述待判定程序的語法結(jié)構(gòu)。
PSDG基本策略是將C程序遞歸描述為復(fù)合語句的集合,每個(gè)復(fù)合語句由復(fù)合語句名稱和復(fù)合語句體構(gòu)成,復(fù)合語句體為語句及其數(shù)據(jù)/控制依賴關(guān)系構(gòu)成的有向圖,圖3為PSDG的結(jié)構(gòu)。第一層為函數(shù)復(fù)合語句,復(fù)合語句名稱(圓形頂點(diǎn))為函數(shù)名,復(fù)合語句體為函數(shù)體語句(方形頂點(diǎn))構(gòu)成的有向圖,圖中的弧

圖3 程序語句依賴
根據(jù)上述策略,PSDG的形式化定義如圖4所示。PSDG 定義為復(fù)合語句集合ComStmtSet;每個(gè)復(fù)合語句ComStmt為一個(gè)有向圖,其中nameNode為復(fù)合語句名稱頂點(diǎn),varRefSet、nodeSet、arcSet分別表示復(fù)合語句中的變量集、頂點(diǎn)集和弧集。nameNode中的name為復(fù)合語句名稱。頂點(diǎn)Node中的NodeType標(biāo)識(shí)語句類型,取值type_Var、type_Expr、type_If、type_Loop、type_InOut、type_Return分別表示變量聲明、賦值、分支、循環(huán)、輸入/輸出、返回;expTree為語法子樹表示的語句內(nèi)容;若Node為if/while語句時(shí),Yes/No分支對(duì)應(yīng)的復(fù)合語句存儲(chǔ)在subComStmtSet。變量VarRef的dataType和varName分別表示變量類型和名稱,而refNode表示最近一次引用變量的語句頂點(diǎn)。

圖4 PSDG的形式化定義
為了描述程序中包含的語句分值,給PSDG每個(gè)頂點(diǎn)設(shè)置flag、weight、gather、fchange屬性。其中flag表示語句分值所指的范圍,取值為1表示該頂點(diǎn)所代表的語句為分值的起始位置,為0表示語句為分值結(jié)束位置,其余頂點(diǎn)的flag值為2;weight表示分值的大小,在flag=1的頂點(diǎn)位置時(shí)weight值為score,否則為0;用gather表示分值所屬范圍,同屬于一個(gè)分值的頂點(diǎn)gather值相同;特別地,當(dāng)一個(gè)分值所包含的語句范圍內(nèi)另嵌套分值時(shí),則用屬性fchange記錄分值間的嵌套關(guān)系。另外給每個(gè)為main的復(fù)合語句名稱頂點(diǎn)設(shè)置“sum”屬性用于記錄程序的總分。nameNode、Node中的pathSet存放下節(jié)評(píng)分過程中與該頂點(diǎn)相關(guān)的路徑片段集合。
根據(jù)PSDG的遞歸定義,PSDG的構(gòu)造算法CreatePSDG如圖5所示。算法以C程序源代碼Source_Code作為入口參數(shù),首先初始化圖G,遞歸遍歷Source_Code的每一個(gè)函數(shù)源代碼建立復(fù)合語句的有向圖,函數(shù)名為復(fù)合語句名稱頂點(diǎn)nameNode,函數(shù)體使用算法CreatComStmt構(gòu)造為復(fù)合語句體子圖并將子圖添加到G中,算法結(jié)束后返回Source_Code的PSDG。

圖5 程序語句依賴圖構(gòu)造算法
構(gòu)造復(fù)合語句體子圖的算法CreatComStmt以復(fù)合語句體ComStmt_Code以及復(fù)合語句體子圖ComStmt作為入口參數(shù),遞歸遍歷ComStmt_Code的每一條語句,根據(jù)語句類型及語句間的數(shù)據(jù)/控制依賴關(guān)系建立ComStmt。其構(gòu)造過程如下所示:
(1)如果語句為變量聲明類型時(shí),新建一個(gè)圖頂點(diǎn)node,將語句類型、內(nèi)容存入node,使用AddNode函數(shù)將語句頂點(diǎn)添加到復(fù)合語句體子圖中,使用AddArc建立nameNode和語句間的弧連接,新建一個(gè)varRef,獲取該語句中的變量類型及名稱存入varRef中,并將node存入varRef的reFnode中作為最近一次使用node中所包含變量的頂點(diǎn)。最后將varRef加入到變量集varRefSet中。
(2)如果語句為變量賦值類型時(shí),將語句存入新建的一個(gè)圖頂點(diǎn)node中,并將該頂點(diǎn)添加到ComStmt中。使用GetVarSet獲取語句中的變量集合varSet;遍歷varSet獲取每一個(gè)變量名varName,使用GetRefNode函數(shù)獲取varRefSet中最近一次使用varName的頂點(diǎn),即refNode中的存放頂點(diǎn),建立該頂點(diǎn)與node的弧連接。獲取node中被賦值的變量,并用node替換最近一次使用被賦值的變量的頂點(diǎn)即使用UpdateRefNode,將node存入varRefSet的reFnode中,實(shí)現(xiàn)varRefSet的更新。
(3)特別地,if/while結(jié)構(gòu)需作為一個(gè)整體處理。將if條件表達(dá)式作為一個(gè)語句頂點(diǎn)node;遞歸建立if結(jié)構(gòu)中Yes分支、No分支復(fù)合語句的子圖存入subComStmtSet。獲得子圖中使用的變量集合,在varRefSet中獲取最近一次使用變量集合的頂點(diǎn),添加這些頂點(diǎn)與node的連接;獲取子圖中被更改的變量集合,用node替換最近一次使用這些變量的頂點(diǎn),完后varSet更新。while結(jié)構(gòu)采用同樣的方法處理。
(4)如果語句為輸入/輸出類型時(shí),將語句存放在新建的圖頂點(diǎn)node中,獲取該語句中的變量,添加node與最近使用該變量的頂點(diǎn)間弧連接,并用node替換該變量的reFnode存放的結(jié)點(diǎn)。
(5)如果語句為返回類型,將語句存入新建的node中,獲取varRefSet的refond中所有頂點(diǎn)集合staNodeSet;建立node與staNodeSet中頂點(diǎn)的弧連接,然后用node替換staNodeSet中的頂點(diǎn)完后varRefSet更新。
在獲得源程序Source_Code的程序語句依賴圖G后,遞歸遍歷Source_Code的每一個(gè)函數(shù)及函數(shù)中的每條語句code,在獲取語句分值s后,根據(jù)語句及G中頂點(diǎn)間的對(duì)應(yīng)關(guān)系,將語句分值標(biāo)注在表示code的頂點(diǎn)屬性中。此外在每個(gè)函數(shù)內(nèi)部,一個(gè)語句分值會(huì)對(duì)應(yīng)一個(gè)集合gather,不在任一語句分值區(qū)域的code歸為一個(gè)gather(需更改首尾句flag值),這時(shí)一個(gè)函數(shù)劃分為若干個(gè)集合,多個(gè)函數(shù)形成多個(gè)集合。具體步驟如下所示:
(1)如果程序中包含s,即“/*sum- -score*/”,則將name為main頂點(diǎn)的屬性sum設(shè)置為score。
(2)如果s為“/*ktype_symbol- -score*/”,需將語句所對(duì)應(yīng)頂點(diǎn)node的flag置1,weight的值為score,gather為當(dāng)前所屬集合,fchange為當(dāng)前所嵌套gather的集合。
(3)如果s為“/*ktype_symbol*/”,此時(shí)node為所屬分值的最后一行,故flag、weight為0,而gather、fchange保持不變。
(4)如果頂點(diǎn)node屬于語句分值范圍內(nèi),node的flag為2、weight為0,而gather、fchange保持不變。若s為“/*- -score*/”采用同樣的方法處理,但node的weight值需變?yōu)閟中的score。
(5)特別地,一些語句并不在“/*ktype_ symbol--score*/”和“/*ktype_symbol*/”范圍內(nèi),需變更gather、fchange的值,并將這些語句的gather、fchange保持一致,并設(shè)置這些語句頂點(diǎn)的flag值,令weight為0。
圖6給出圖2所描述題目的PSDG表示,而部分帶有分值的語句在PSDG中的表示見表2。

表2 語句分值在PSDG每個(gè)頂點(diǎn)中的表示

圖6 “求π的值”程序語句依賴
在獲得標(biāo)有語句分值的PSDG后,首先標(biāo)準(zhǔn)化程序語句依賴圖的標(biāo)識(shí)符命名;其次依據(jù)語句分值的位置、程序中語句依賴關(guān)系將PSDG劃分為由路徑片段構(gòu)成的集合;最后遍歷每個(gè)集合,依據(jù)待判定、答案程序間同集合路徑相匹配原則,計(jì)算待判定程序路徑片段的相似度,完成待判定程序評(píng)分。
3.1.1 答案程序路徑片段集合劃分
在獲得答案程序的PSDG后,依據(jù)PSDG中每個(gè)頂點(diǎn)的gather值及頂點(diǎn)間的偏序依賴關(guān)系劃分路徑片段集合,算法如圖7所示。具體說明如下:

圖7 劃分答案程序路徑片段集合算法
從起始頂點(diǎn)出發(fā),遍歷PSDG的每個(gè)頂點(diǎn),尋找其直接后繼頂點(diǎn)。若兩個(gè)頂點(diǎn)的gather值相同,則尋找直接后繼頂點(diǎn)的后繼頂點(diǎn),直至直接后繼頂點(diǎn)gather值為另一個(gè)集合值(gather值不相等),此時(shí)獲得從起始頂點(diǎn)出發(fā)的一條路徑片段;然后從起始頂點(diǎn)出發(fā)遍歷其余直接后繼頂點(diǎn),獲取其余后繼頂點(diǎn)所在的路徑片段;這些路徑片段存儲(chǔ)在一個(gè)集合中。然后從未訪問頂點(diǎn)出發(fā)按照上述思路尋找其余集合,這樣PSDG就會(huì)被劃分為由路徑片段構(gòu)成的集合。
3.1.2 計(jì)算答案程序中集合分值
答案程序中存在一個(gè)語句分值Wi包含另一個(gè)語句分值Wj的情況(被包含的分值Wj屬于Wi的一部分),而在集合劃分時(shí)Wi并沒有包含Wj中的語句,因此需更改Wi的分值。即依據(jù)分值注釋間的嵌套關(guān)系,從最外層出發(fā),用嵌套集合的分值減去所有直接被嵌套集合的分值,即父集合Wi的分值weight為其減去所有子集合Wj的分值后剩余的分值。其算法如圖8所示。

圖8 計(jì)算答案程序集合分值算法
在完成上步計(jì)算后,有些集合因教師未設(shè)置語句分值導(dǎo)致該類集合沒有分值,其計(jì)算方法如式(1)所示,其中題目總分為sum、已知分值的集合分值為score(共m個(gè))、未給分值的集合數(shù)量Mnum、未給分值的集合分值為Nscore
(1)
由于答案程序中語句分值間存在嵌套關(guān)系,故需從答案程序被嵌套的路徑集合出發(fā),依據(jù)待判定、答案程序的頂點(diǎn)間相似度標(biāo)注待判定程序PSDG中每個(gè)頂點(diǎn)所屬集合值,直至每個(gè)頂點(diǎn)被訪問過一遍,然后按照上述方法從答案程序的嵌套集合出發(fā)標(biāo)注剩余頂點(diǎn)的gather值,算法如圖9所示,其中Zhangshasha為頂點(diǎn)間相似度計(jì)算函數(shù),具體算法見文獻(xiàn)[14]。

圖9 劃分待判定程序路徑片段集合
首先將待判定程序每個(gè)頂點(diǎn)與答案程序路徑集合中每個(gè)路徑片段的起始頂點(diǎn)對(duì)比,若兩個(gè)頂點(diǎn)相似度為1,則兩個(gè)頂點(diǎn)屬性gather值相同,此時(shí)該頂點(diǎn)為待判定程序PSDG某一集合內(nèi)路徑起始頂點(diǎn);遍歷該頂點(diǎn)的直接后繼頂點(diǎn),對(duì)比直接后繼頂點(diǎn)與上述答案程序相應(yīng)路徑片段中的結(jié)束頂點(diǎn)(無后繼頂點(diǎn))直至相似度為1,此時(shí)獲取的頂點(diǎn)為待判定程序路徑的結(jié)束頂點(diǎn),此時(shí)一條路徑片段形成(過程中設(shè)置兩個(gè)頂點(diǎn)屬性gather值相同),否則繼續(xù)對(duì)比該后繼頂點(diǎn)的直接后繼頂點(diǎn)直至該頂點(diǎn)為PSDG結(jié)束頂點(diǎn)(即無后繼頂點(diǎn)的頂點(diǎn)),也沒有找到相似度為1的頂點(diǎn),則該條路徑放棄。
此時(shí)繼續(xù)對(duì)比頂點(diǎn)的其余直接后繼頂點(diǎn)劃分路徑片段,形成集合中的其余路徑片段,直至每個(gè)頂點(diǎn)都被訪問過,此時(shí)待判定程序的第一個(gè)路徑片段集合尋找完畢;然后從未被訪問的頂點(diǎn)出發(fā)按照上述思路尋找其余路徑片段集合。上述步驟形成的所有集合為待判定程序PSDG的路徑片段集合。
(1)路徑相似度及頂點(diǎn)分值計(jì)算:一條路徑上所有頂點(diǎn)的相似度之和與該條路徑上頂點(diǎn)數(shù)量的比值為路徑的相似度。特別地,若待判定程序的一個(gè)頂點(diǎn)i與答案程序的頂點(diǎn)j匹配時(shí),頂點(diǎn)間相似度為Psimilar,且j有分值score,此時(shí)需用式(2)計(jì)算i的分值Pscore,否則不單獨(dú)計(jì)算頂點(diǎn)分值
Pscore=Psimilar*score
(2)
(2)匹配路徑/集合:答案程序S與待判定程序路徑片段集合T對(duì)比時(shí),采用同集合(集合名相同)路徑相匹配的策略選擇待匹配的路徑,而集合中路徑匹配時(shí)則采用KM算法[15]找到每條路徑的匹配路徑。
集合M的一條路徑Mi與T中路徑相匹配時(shí),先找到使Mi有相似度最大的路徑Tj(相似度為maxij),然后對(duì)比M中每條路徑與Tj的路徑匹配結(jié)果,若存在使Tj相似度最大的路徑Mk則比較maxij和maxkj的大小,若maxij≥maxkj則將Tj作為Mi的匹配路徑,否則Tj不作為Mi的匹配路徑并繼續(xù)尋找使Mi有相似度次N大的路徑Tn直至滿足maxin≥maxnn,此時(shí)將Tn作為Mi的匹配路徑。按照上述算法遞歸尋找M和T中路徑的匹配對(duì)直至M或T中的每條路徑都找到匹配路徑,同時(shí)匹配對(duì)的頂點(diǎn)相似度作為待判定答案的頂點(diǎn)相似度。
(3)待判定集合分值計(jì)算:在獲取待判定程序每個(gè)集合內(nèi)路徑的匹配路徑后,運(yùn)用式(3)計(jì)算每個(gè)集合的分值Gscore,其中每個(gè)頂點(diǎn)的相似度為Psimilar、Num為一個(gè)集合內(nèi)總的頂點(diǎn)數(shù)量、Tscore為答案程序中匹配集合的分值
(3)
若集合內(nèi)一些頂點(diǎn)已獲得分值,需通過式(4)計(jì)算該集合的分值:即已知頂點(diǎn)的分值和與未知頂點(diǎn)分?jǐn)?shù)之和相加即為集合分值Gscore

(4)
其中,n代表已獲得分值的頂點(diǎn)總數(shù),m代表未獲得分值的頂點(diǎn)總數(shù)、頂點(diǎn)的相似度為Psimilar、答案程序中集合和頂點(diǎn)的分值分別為Tscore和TPscore。
從2017屆本校200位大一學(xué)生C語言課程的課后作業(yè)中,選取5道編程題作為檢測(cè)本文方法的實(shí)驗(yàn)題目。編程題目1~5分別為“求π的值”、“猴子吃桃問題”、“求1!+2!+…100!”、“求圓環(huán)的面積”和“漢諾塔問題”,每題滿分均為25分,其中題目1考察的知識(shí)點(diǎn)為函數(shù)、表達(dá)式、循環(huán)結(jié)構(gòu),題目2考察的知識(shí)點(diǎn)為函數(shù)、循環(huán)結(jié)構(gòu),題目3考察的知識(shí)點(diǎn)為函數(shù)、表達(dá)式、循環(huán)結(jié)構(gòu),題目4考察的知識(shí)點(diǎn)為函數(shù)、輸入、輸出結(jié)構(gòu),題目5考察的知識(shí)點(diǎn)為函數(shù)、選擇結(jié)構(gòu)。題目1的答案程序賦予表達(dá)式和循環(huán)結(jié)構(gòu)知識(shí)點(diǎn)權(quán)重分別為8分和14分;題目2、題目3每個(gè)語句平分題目分值;題目4賦予函數(shù)、輸入/輸出知識(shí)點(diǎn)權(quán)重分別為15分、5分;題目5賦予函數(shù)、選擇結(jié)構(gòu)知識(shí)點(diǎn)權(quán)重分別為10分、13分。
從200位學(xué)生中隨機(jī)抽取50名學(xué)生提交的程序作為實(shí)驗(yàn)對(duì)象,通過搜集運(yùn)用動(dòng)態(tài)評(píng)分、統(tǒng)計(jì)屬性特征的結(jié)構(gòu)規(guī)模評(píng)分、使用LCS算法[16]獲得語句相似度的程序靜態(tài)評(píng)分、采用本文策略的自動(dòng)評(píng)分、人工評(píng)分5種方式對(duì)5道實(shí)驗(yàn)題目評(píng)分點(diǎn)及評(píng)分的結(jié)果進(jìn)行對(duì)比,驗(yàn)證本文方法的有效性。
首先以“求π的值”(圖2)為例,結(jié)合人工評(píng)分方式、結(jié)構(gòu)評(píng)分策略,使用式(5)計(jì)算50個(gè)學(xué)生采用結(jié)構(gòu)規(guī)模、LCS、自動(dòng)評(píng)分方式,找到知識(shí)點(diǎn)、語句被準(zhǔn)確評(píng)分的誤差率。該題考察知識(shí)點(diǎn)為1個(gè)函數(shù)、4個(gè)表達(dá)式、1個(gè)while結(jié)構(gòu),并設(shè)置4個(gè)標(biāo)有語句分值的區(qū)域。其中SeR表示誤差率、Psum表示人工評(píng)分時(shí)統(tǒng)計(jì)的數(shù)量、Ssum代表某種評(píng)分方式統(tǒng)計(jì)結(jié)果。由于動(dòng)態(tài)評(píng)分是通過程序的運(yùn)行結(jié)果評(píng)分,所以這里不對(duì)其進(jìn)行誤差率計(jì)算。誤差率計(jì)算結(jié)果見表3

表3 知識(shí)點(diǎn)及語句被準(zhǔn)確評(píng)分的誤差率計(jì)算結(jié)果/%
SeR=(|Psum-Ssum|)/Psum*100%
(5)
由表3可知,基于LCS的靜態(tài)評(píng)分采用LCS算法,匹配語句間相似度來判斷知識(shí)點(diǎn)正確性,因此會(huì)產(chǎn)生較高誤差率;結(jié)構(gòu)規(guī)模評(píng)分則是考慮整個(gè)程序中包含的知識(shí)點(diǎn)數(shù)量與題目考查知識(shí)點(diǎn)的差距,該方法會(huì)計(jì)算注釋區(qū)域之外的知識(shí)點(diǎn)數(shù)量,且其并不考慮語句的內(nèi)容,因此存在誤差;而自動(dòng)評(píng)分是在語句分值范圍內(nèi)獲取知識(shí)點(diǎn),通過匹配路徑片段相似度獲取評(píng)分,所以其總體誤差率要優(yōu)于其它兩種評(píng)分方式。
其次,采用式(6)計(jì)算4種評(píng)分結(jié)果與人工評(píng)分之間的誤差率,結(jié)果見表4。其中ER表示評(píng)分的誤差率、Pscore表示人工評(píng)分結(jié)果、Sscore代表某種評(píng)分方式獲得的結(jié)果

表4 各種方式的評(píng)分結(jié)果對(duì)比/%
ER=(|Pscore-Score|)/Pscore*100%
(6)
由表4可知:LCS評(píng)分和自動(dòng)評(píng)分誤差率接近,但該方法評(píng)分時(shí)采用LCS算法計(jì)算語句相似度,且沒有按照教師標(biāo)注的語句分值進(jìn)行評(píng)分,故其整體誤差率高于自動(dòng)評(píng)分;而結(jié)構(gòu)規(guī)模評(píng)分由于沒有考慮待判定程序的語句內(nèi)容是否符合答案程序,使得誤差率高于自動(dòng)評(píng)分;動(dòng)態(tài)評(píng)分因其在待判定程序編寫錯(cuò)誤,導(dǎo)致不能運(yùn)行時(shí)會(huì)給予0分,故其誤差率高于自動(dòng)評(píng)分。另外,在題目編號(hào)為2、3,設(shè)置語句平分答案程序分值時(shí),自動(dòng)評(píng)分和其余3種評(píng)分誤差率存在較小差距;題目編號(hào)為1、4、5,設(shè)置語句不同分值權(quán)重時(shí),自動(dòng)評(píng)分和其余3種評(píng)分誤差率存在的差距總體變大,故本文依據(jù)答案程序中設(shè)置的語句分值及PSDG實(shí)現(xiàn)的評(píng)分方法相比于其它方法明顯提升了評(píng)分準(zhǔn)確度,更接近人工評(píng)分結(jié)果。
另外,通過實(shí)驗(yàn)結(jié)果可以看到本文方法的評(píng)測(cè)結(jié)果和人工評(píng)測(cè)之間還存在一些差異。為尋找原因,對(duì)學(xué)生提交的程序進(jìn)行了進(jìn)一步檢查分析,發(fā)現(xiàn)凡是人工評(píng)判正確解答得滿分的程序,本文方法也為滿分;而對(duì)于存在一些錯(cuò)誤的程序,本文方法評(píng)測(cè)結(jié)果和人工方法部分結(jié)果存在1-2分內(nèi)的差異。究其原因,主要是當(dāng)人工評(píng)測(cè)存在主觀性因素,當(dāng)評(píng)分規(guī)則粒度較粗時(shí)評(píng)分尺度不是完全一致,另外對(duì)于多處類似細(xì)微錯(cuò)誤按同一個(gè)錯(cuò)誤扣分,而本文算法則是按照評(píng)分規(guī)則固定計(jì)算。
針對(duì)現(xiàn)有C程序靜態(tài)評(píng)分方法存在的缺陷,本文提出一種面向語句分值的C程序靜態(tài)評(píng)分方法,通過運(yùn)用程序語句依賴圖描述源程序及程序中教師標(biāo)注的語句分值,根據(jù)語句間的依賴關(guān)系和語句分值將答案及待判定程序劃分為路徑片段集合,對(duì)比兩者集合相似度完成待判定程序評(píng)分,評(píng)測(cè)結(jié)果接近人工評(píng)分,能更好滿足實(shí)際教學(xué)需要。但本文方法會(huì)受到答案程序的影響,當(dāng)學(xué)生采用答案程序中不包含的正確解題思路時(shí),不能夠正確識(shí)別和評(píng)分;另外,人工評(píng)分時(shí)對(duì)于程序中的多處類似錯(cuò)誤一般僅扣除一次分值,而本文方法按實(shí)際出現(xiàn)次數(shù)進(jìn)行扣分。這些問題需要在未來的研究中進(jìn)行解決。