王猛,赵军富
摘要:C语言程序设计在评分过程中,大多数的考试系统只能按照结果评分,这就导致学生考试成绩要么满分要么零分,不能够真实反映学生的学习水平,利用正则表达式对C语言的程序进行知识点的过程评分,并通过预设输入值,让学生运行自己的程序,得出结果与预设结果值进行匹配,得出结果分,最终结合是否编译,得出总分。
关键词:C语言程序设计;过程评分;正则表达式
中图分类号:G642 文献标识码:A
文章编号:1009-3044(2022)35-0037-03
1 引言
C语言程序设计是大学本科工科类专业所开设的必修课程,对于程序设计题目,在平时的作业及考试都需要对程序设计题目进行评分,有些院校对于程序设计题还是人工评分,尤其是作业;有些院校采购了考试系统,但大多数的考试系统或网络评测系统中,评测都是以运行结果作为评分依据。并不查看学生的编程过程,其评分原则并不能体现学生对知识的掌握程度,有其局限性。对于程序设计题这种间于自然语言和程序语言之间的主观题,可部分摆脱语言的约束和限制[1-2],具有较高研究价值。本方法在对过程评分主要通过正则表达式进行评定,因为正则表达式不仅能够处理传统的文本匹配,更重要的是正则表达式具有强大的结构描述能力,同时能够描述文本深层次的特征,可以通过简单有效的方式对文本进行的复杂控制[3-4]。根据正则表达式的特点,其特别适用于程序类代码的匹配评测。
2 C语言过程评分实现
C语言程序题在评分由三个部分构成:结果分值、编译分值、过程分值[5]。结果分值通过评判数据库中预设的结果来评定;编译分值通过是否编译评定;过程分值由事先设定的多个正则表达式评定,其中正则表达式由参考代码中的关键代码构成,然后利用ckstr函数对参考代码进行匹配,得出过程分。C语言整体评测过程如图 1所示:
对于正则表达式,常用的替换字符包括:.*可以匹配单行任意字符;[\s\S].*可以匹配多行任意字符;[ ].*可以匹配零个或多个空格;[ ]+可以匹配一个或多个空格。利用正则表达式的这些特点,我们可以对常用的C语言结构及部分带代码,用正则表达式去表示。
例如选择结构单分支结构语法如下:
if(条件)
{
表达式;
}
转换为正则表达式如下:if[ ]*\(.*\)[ ]*\{[\s\S]*\}
对于数据库中题目表的部分主要字段设置如表 1:
最终分值计算的公式如下:
$fz_cfd=100*($bl_cfd/($bl_da+$bl_by+$bl_cfd))*($cfd/$sum)
$zf=$fz_da+$fz_by+$fz_cfd;
说明如下:
$sum为所有正则表达式的分值
$cfd为考生获取正确正则表达式的值
$fz_cfd为过程分值
$fz_da为结果分值
$fz_by为编译分值
以下为程序评定过程中的部分代码:
$sum=0;
$cfd=0; //用于统计各个正则表达式采分点的和
while($row=mysqli_fetch_array($result_zz))
{
$sum=$sum+$row[1]; //row数组为数据库中正则表达式
$str1="/".$row[0]."/";
$str2=$content; //$content为参考代码
if(ckstr($str1,$str2)==1)
{
$cfd=$cfd+$row[1];
}
}
if($sum==0)
$fz_cfd=0;
else
$fz_cfd=round(100*(1.0*$r_tm->bl_cfd/($r_tm->bl_da+$r_tm->bl_by+$r_tm->bl_cfd))*(1.0*round($cfd,2)/$sum),2);
$zf=$fz_da+$fz_by+$fz_cfd;
3 實例分析
1) 题目内容:
实现功能:请编写一个函数fun,该函数的功能是:计算正整数n以内(包括n),能被5或9整除的所有自然数的倒数的和,并将计算结果作为函数值返回在主函数中保留两个小数位输出。
例如:若输入n的值为20,则输出结果为0.58.
注意:
① 所写代码中,不得定义其他变量;
② 本题必须使用for循环,if语句;
③ 不允许改动预编译命令行及主程序,且必须运行程序;
④ 程序代码编写在****BEGIN*****与****END****之间;
⑤*********BEGIN**********和*********
END**********不可删除。
⑥ 其中函数void bky( )为自动评分函数,禁止修改、删除
2)给出代码如下:
#include<stdio.h>
void bky( );
float fun( int n)
{
int i;
float sum=0;
/***********BEGIN*********/
/***********END*********/
}
void main()
{
float fun( int n);
int m;
float s;
printf("\n 請输入一个正整数:");
scanf("%d",&m);
s=fun(m);
printf("\n the result is:%.2f",s);
bky();
}
void bky()
{
FILE *IN,*OUT;
float s ;
int t;
float o;
IN=fopen("in.dat","r");
if(IN==NULL)
{
printf("Read FILE Error");
}
OUT=fopen("out.dat","w");
if(OUT==NULL)
{
printf("Write FILE Error");
}
fscanf(IN,"%d",&t);
o=fun(t);
fprintf(OUT,"%.2f\n",o);
fclose(IN);
fclose(OUT);
}
3) 题目内容设置如图 2所示,设置答案、编译及过程的采分比例如图 3所示:
4) 设置的正则表达式采分点如所表 2示:
5) 参考答案如下:
for(i=1;i<=n;i++)
if(i%5==0 || i%9==0)
sum=sum+1.0/i;
return sum;
6) 分别找cs和cs2两位测试同学进行测试,学生代码如图 4下:
根据前面题目分值比例的设置:本题的结果分为50分;编译分为10分;过程分为40分。cs这位同学的结果、编译、正则表达式所有的采分点全部正确,得分100;而cs2这位同学的结果错误,结果分为:0分、编译过,编译分为:10分,过程分共40分,但正则表达式中,其中第5项和第8项不正确,只能拿到6/8的过程分,故总分=0+10+40*6/8=40分,具体评分结果如表 3 :
4 结语
本文提出了一种可以实现C语言程序自动评分的方案。在C语言程序中,评分过程无非三个方面:结果是否正确,是否进行编译,代码准确率三个方面,本方法不仅可以评判结果,更重要的是可以评判代码的准确率,使得C语言程序的评判更加客观和准确,减轻了教师的负担。
但在评判代码准确率的时候,通过前文可知道,需要对给定程序做出很多限定,例如:功能实现时,限定代码必须用for循环结构实现;还有代码中限定不得再定义其他变量;还有些较复杂代码,限定变量的含义等缺陷。但是鉴于目前人工智能、信息技术的发展水平,目前这种评判方法是一种高效、客观、准确率高的方法,而且本方法也可适用于其他类编程语言的自动评分,具有较高的推广价值。
参考文献:
[1] 曹亚妮.C语言在线考试系统开发及关键技术的研究[D].西安:西安理工大学,2016.
[2] 吴艳玲.基于WEB的C语言编程题自动阅卷系统的设计与实现[D].成都:电子科技大学,2011.
[3] 姜英杰.支持正则表达式的文本匹配优化算法[D].沈阳:东北大学,2012.
[4] 张雪英.基于机器学习的文本自动分类研究进展[J].情报学报,2006(6):730-739.
[5] 刁善会.C程序设计考试系统设计与实现[D].重庆:重庆大学,2009.
【通联编辑:王力】