02 程序设计 - coursegrading/CourseGrading GitHub Wiki
编程题评判结果的含义,以及得分规则
CG评测结果给出每个测试数据的通过情况,题目得分=(题目分数 / 测试数据对数) * 通过数。CG教学平台的作业和考试不限制提交次数。
- 完全正确。用户程序的输出与期望输出匹配。
- 输出错误。用户程序的输出与期望输出不一致。如果是作业,点击“详细评判结果”,在动态测试中,会列出错误输出和期望输出,方便学生调试自己的程序。
- 格式错误。用户程序的输出结果中的不可见字符(例如空格、制表符等)与期望输出不一致,布置作业或者出试卷时,可以设置格式错误是否给分,如图1所示。
- 程序运行时间过长。程序运行的时间已经超出了这个题目的时间限制,一般是存在死循环。
运行时错误。程序运行期间崩溃,如果C/C++程序,常见的错误类型有:
- SIGFPE:零作为除数。
- SIGSEGV:非法内存访问,是最为常见的错误,一般这些问题在小规模测试的时候不会发现,而在大规模数据测试时候就容易暴露出来,所以请自行构造一些数据来调试程序。可能原因 (1)数组越界使用; (2)指针的错误使用, 一般是对非用户区的地址空间进行读或者写操作; (3)越权操作文件指针, 程序中却未捕捉该类错误; (4)栈溢出, 一般是因为过多的递归调用或者过大的临时变量导致; (5)程序使用的内存超过了题目设定的上限。
- SIGXFSZ:程序输出过多数据,有可能存在死循环。
- SIGABRT:程序中止运行,原因可能是 (1)由于严重的错误(例如内存重复释放double free或者heap corruption),库函数调用abort中 止程序运行; (2)断言(assert)使用abort实现,断言条件为false。
- 系统繁忙。提示服务器忙是系统忙于评判提交的程序,后台是个大进程池并行评判的,偶尔遭遇大量并发提交,而且同时出现了很多死循环的程序。系统做了并发控制,避免把Web服务器击垮,返回系统繁忙的提示,如果偶尔出现类似的评判结果,不用担心,再次提交即可。
评判结果中的编译警告是否可以忽略?
编译警告不会影响正确性评判和得分,如图2,编译警告中给出代码规范提示或者风险提醒,可能意味着程序中隐含的大错误,也可能确实没有问题。建议引导学生关注警告信息,尽量消灭警告信息,提升代码质量。
几种典型的编译警告示例以及处理办法:
- warning: `param' might be used uninitialized in this function。变量可能未初始化(或者未被赋值)就使用。此类错误有可能在某些时候能够通过正确性测试,有些时候错误,依赖于当时内存空间的初始值。
- warning: unused variable `param’。定义了一个变量,但未使用,可以删除。
- warning: control reaches end of non-void function。函数没有返回值,或者在某些分支条件下忘记返回值。
- warning: suggest parentheses around && within ||。代码里写了一个复杂的条件判断,例如:
''if ( no[i][7] >= 'A' && no[i][7] <= 'Z' || (no[i][7,] - '0') %2 == 0 )'' 最好改为: ''if ( ( (no[i][7] >= 'A') && (no[i][7] <= 'Z') ) || ( (no[i][7,] - '0') %2 == 0) )''增强代码的可读性和可移植性。
录入编程题有没有详细的手册或者文档?
进入教师端,右上角有“用户指南”,里面有如何录入题目的介绍。但是最快捷的掌握录题规则的方法是通过实际的例子, 用户QQ群文件内有各类题型的分享题库,跟负责维护系统的老师联系下载,然后导入,通过编辑题目查看录题规则。
为何使用源文件而不是文本框提交代码?
CG系统从2003年起一直坚持使用源文件代码提交方式,我们认为源文件提交有两个好处:
- 符合工程实际。训练学生使用IDE编写和调试代码,而不是在文本框内填写代码,不经过调试直接提交。
- 支持多源文件提交,复杂问题的源文件组织也是一种工程训练。特别是Java代码,一般一个类对应一个文件,如果使用文本框提交就会破坏Java的编程规范。
系统是否支持程序填空题?
“程序片段编程题”可以用作程序填空题,补充缺失的语句、函数。类似程序填空题。也可以插入调试打印语句,以打印的数据作为正确性评判依据,类似集成开发环境中的断点调试。QQ用户群文件内有程序片段编程题的示例,直接导入题库作为参考。
如何方便的测试自己录入的编程题?
编程题描述和测试数据录入完毕之后,在题目概览内打开该题目的“样例”链接,在新开的窗口内上传源程序,以此验证测试数据是否正确,此外上传的源程序也可以作为参考答案。提交的时候打开“详细评判结果”,能够辅助调试程序。
测试数据标准输入的换行符问题
录入测试数据时,标准输入(或者文件输入)的最后一行不加回车换行,结束符是EOF,而不是“\n”。对于c语言,使用getc来判断行结束的时候,需要特别注意。 平台早期会自动在输入的最后一行加入“\n”,后来就老师反映不是自己预期的结束方式,对题目描述造成困扰。所以目前最后一行格式交由教师自己来控制。需要最后一行有换行符,就在最后一行“回车”。
有关Java源文件的编码问题
务必不要使用Windows的记事本撰写代码。如果提交Java源文件,提示中文编码的问题,一般是使用Windows的记事本编辑过Java源文件,引入了Javac不支持的字符编码引起。具体原因可以参考知乎文章
c/c++语言提交之后,编译信息内有乱码如何解决?
源代码文件使用了比较生僻的编码导致的,例如UCS-2等,把源文件编码更改为UTF-8或者GBK就可以了,推荐使用nodepad++查看或者转换源文件的编码。
编程题的测试数据支不支持中文?
从4.3.0版本开始,编程题全面支持中文。 但一定要注意源文件的编码必须是UTF-8。 除了源文件必须是UTF-8编码,对于Java和Python语言,一定要注意:
- Java语言 : 由于Java默认并不是使用平台默认编码输出,所以输出必须转换为UTF-8编码,例如:
PrintStream out = new PrintStream(System.out, true, "UTF-8"); out.println("中文");
- Python语言 : 由于在Linux平台上,默认并不是按照UTF-8编码输出,提交代码之后会出现类似“UnicodeEncodeError: 'ascii' codec can't encode character… ”的错误,所以输入与输出必须转换为UTF-8编码,例如:
import io import sys sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8') sys.stdin = io.TextIOWrapper(sys.stdin.buffer,encoding='utf-8')
Python编程题-中文输入输出样例题目,如下所示。(下载先将题目压缩的rar文件解压成.tiku文件,然后再导入题库参考) Python编程题-中文输入输出样例.rar 使用中文作为测试数据,有可能引入全角字符和其它很多特殊字符,对于学生查错,会带来很多的麻烦,除非任课教师非常了解编码问题,否则不建议使用中文作为测试数据。
程序设计中如何修改样例参考代码?
具体修改方法,如图所示。
如何增加程序设计的测试用例?
增加测试用例方法,首先找到相应题目,如图5点击“编辑”。
进入编辑以后,如图6在页面的最后可以找到“评判规则”和“编辑测试数据”两个功能选项。先在修改“评判规则”中的测试数据对数,然后打开测试数据编辑器。
作业中详细评判有什么必要性?
作业和题目样例中,会有详细评判,如果输出错误,会告知与期望输出的差异。目的是降低初学者的挫折感,帮助学生调试程序。考试时不会有详细评判。
学生端如何看到作业的正确答案和得分?
如下图所示,作业过期以后打开“学生端成绩查询开关”,才会显示正确答案和得分,默认是关闭的。
学生提交过代码之后,代码行统计信息为什么没有更新?
学生提交过代码之后,系统会在夜间自动统计每道题的平均代码行、系统共提交的代码行、作业的平均代码行、考试的平均代码行等,所以第二天才会看到更新过的统计信息。
编程题有哪些结果比对策略,是否支持特殊情况的评测,例如一题多解、无关提示信息过滤、浮点数格式匹配等问题? 系统支持如下评判规则,精确匹配最为常用,其它根据题目的情形选用:
- 精确匹配
这是最为常用的匹配方式,要求学生程序输出与期望输出完全一致。
为了降低格式的影响,系统自动去掉了行首与行尾的空白字符、以及空白行,进行对比。行内的空白字符(空格、制表符等)与期望结果不一致,会判为格式错误。
- 模糊匹配
可以使用通配符 * 和 ? 表达期望输出,且大小写无关。 例如圆周率只需要保留3为小数, 期望输出为:3.141*;
“模糊匹配”也可以用于答案“多选一”的场景, 期望输出把所有可能的正确结果按行列出,用户程序的输出行,只要是期望输出的子集就判正确。
模糊匹配容易引起误判,可能把不正确的判为正确,请根据题目输出特点酌情考虑
应用案例1:正确答案可能是09中的任意一个或者几个数字,那么期望输出为:09按行列出。 应用案例2:地铁线路查询,只要找出一条就算结果正确,那么期望输出把所有的期望结果全部列出即可。
- LCS匹配
LCS(最长公共子序列)匹配方法,能够得出一个测试用例的部分正确分, 利用LCS算法找出学生输出与期望输出的最长子串,最长子串与(期望输出和学生程序输出的最大值)的长度比值,得到一个正确率,假设为 r。
题目得分 = Σ((题目分数 / 测试数据对数) * r)
应用案例:暂无。
- 编辑距离匹配(按 错误行 扣分)
基于编辑距离算法,按行对比学生输出与期望输出,假设不同的行数为 d, 错误一行扣分 r %
题目得分 = Σ((题目分数 / 测试数据对数) * MAX((1 - d * r%), 0) )
应用案例:在编译课程实验中的词法分析与语法分析,根据分析出来词法或者语法成分的比例得分。 避免精确匹配策略导致的完全零分的情况。
- 编辑距离匹配(按相似度得分)
计算学生输出与期望输出的编辑距离,假设为 d, 学生输出长度为S,期望输出长度为E
题目得分 = Σ((题目分数 / 测试数据对数) * (1.0 - d / MAX(S, E)) )
应用案例:在编译课程实验中的词法分析与语法分析,根据分析出来词法或者语法成分的比例得分。 避免精确匹配策略导致的完全零分的情况。
编程题中的性能评测有什么限定条件,适用于哪些课程?
- 如果要用性能评测,一定要注意测试数据量必须大(超过CPU Cache)或者时间复杂度比较高。在现代CPU上,执行时间太短的程序(运行时间在毫秒以下),评测误差和不确定性非常大。
- 一般应用于算法与数据结构课程(http://www.educg.net/ds.html),可以用于计算机组成原理和体系结构课程,让学生通过微架构优化,体验指令流水、寄存器、Cache等对程序性能的影响(参考《深入理解计算机系统》)。
学生提交编程题之后,“显示正在评判….,请稍等”,一直不出评判结果,这是为什么?
是因为这道编程题设置的最长运行时间过长(超过10秒),导致大家排队评测,而不是并行评测。在现代的CPU上运行超过2秒程序都是计算复杂度很高的算法了,一般不要修改,除非要做性能评测(参考上面的问题)。
在CG平台上有没有面向对象程序设计类课程的一些题库?
平台上的程序设计类题目和语言无关的,可以将其他语言的题目导入到您的课程中,布置作业时,编辑修改提交语言为您课程的语言,例如C++或者Java。老师们也可以使用接口编程题,直接考核面向对象的知识点。
系统支持工程项目评测吗?(可以提交多个源文件吗?)
支持项目评测或者多源文件评测,源文件打包上传就可以,系统自动编译执行。如图7所示:
有的学生程序在vs里调试都没有问题,也能得出正确的结果,在CG系统会出现调试不通过的情况?
如果是编译错误,请看下一条常见问题,可能是遇到了语言标准或者版本的问题。如果是运行错误或者结果不正确,首先这个时候不要怀疑是编译器出错了,对于学生提交的代码,复杂度远未达到触发编译器问题的程度。
最为常见的情形:c/c++语言变量未初始化,或者轻微越界引起的,在本机环境,内存区域可能正好被清零,但是换台机器运行,问题就有可能出现。甚至出现时对时错。 读取输入时发生错误。调试的时候没有太注意输入的格式,提交之后,系统是严格按照输入格式来的。例如下面的代码:
- 例1:测试数据中,输入是空格隔开,但是学生程序使用“逗号”,n读入一个随机值,最后结果不对。
- 例2:不规范的代码,严重依赖求值顺序的,不同的编译器结果会有不同,一般编译器会给出警告信息。
- 例3:不规范的代码:
学生程序在本地编译通过,为什么提交之后编译不通过?【如果更改编译器版本或者定制编译选项?】
最近几年C++程序特别容易出现此类问题,C++几乎每三年就出一个语言标准,编译器升级也非常快。系统默认使用服务器(CentOS或Ubuntu)自带的编译器,但提供了编译器版本和编译器的一键定制功能,如下图所示,任课教师确定好编译器版本之后联系系统管理员进行定制。
学生提交程序的次数有限制吗?
教学系统内编程题的提交次数没有限制,但后台会记录提交的次数。CG-OJ模块的提交规则与OJ系统类似。
编辑测试数据使用“本地文件上传”方式有关换行符的问题
使用本地文件上传方式,将会原封不动保留文件内的数据,特别是windows平台下的换行符:\r\n,不会自动转换为linux平台的换行符 \n。 如果依赖换行符处理输入,有三种处理方法供参考:
- 如果输入量不大,建议使用在线编辑填写测试数据。
- 使用类似NotePad++这样的工具统一把测试数据中的\r\n,转换为\n,再上传。
- 题目描述告知学生,换行符为\r\n,别用%c读取数据,%c是不处理换行的,使用%s,能够自动识别换行问题。如下图错误程序的32行,以为换行只有一个字符,其实有两个字符。32行改为:getchar();getchar();就正确了。
平台是否需要自动转换换行符,这个还需要进一步调研,因为平台自动转换会让很多老师出题的时候,如果需要使用二进制数据 或者 包含有\r\n文本文件,会导致这样的数据无法录入。
如何公开编程题的样例代码?
系统有公开样例代码的功能,作业过期之后,可以让学生参考。公开样例代码功能如图所示。注意勾选“公开样例代码”,由于公开样例代码这块,老师们存在争议,所以默认是不公开的。 下面两种情况,即使打开公开样例代码的开关,学生依然看不到样例代码。
- 该题目没有样例代码。
- 某道题目学生从未提交过。
编程题重新评判后,为什么部分学生的分数会变化?
这是一种正常现象,原因是部分学生的代码中可能存在未初始化或者越界类似的错误,导致动态测试时,跟当时的执行期间内存状态有关,呈现时对时错的现象。如果是考试,会标识出分数发生变化的学生。作业内暂时没有标记功能。