2

我正在使用基于 Web 的应用程序对学生提交的 C 程序进行评分。对于一些问题,我希望学生在函数中填写代码。以下是学生将看到的示例屏幕。

go() {
---------------------------------
|                               |
|                               |
|                               |
---------------------------------
}

main() {
  go() 
}

学生应该在一个盒子里填写一些代码。但是,我不希望学生创建这样的新函数:

go() {
---------------------------------
|  go_help();                   |
| }                             |
| go_help() { printf("hi"); }   |
---------------------------------
}

main() {
  go() 
}

如何防止学生创建新功能?代码模板连同学生填写的代码一起发送到等待服务器编译运行的队列中。我无法更改或检查该队列中的代码。我唯一能做的就是更改代码模板。

4

3 回答 3

2

你能在你的模板中放入不会在网页中显示的代码吗?

如果用户看到这个:

void go() {
---------------------------------
|                               |
|                               |
|                               |
---------------------------------
}

int main() {
  go(); 
}

但是他们的代码实际上被替换为:

void go() {
    int some_name_the_user_will_never_guess_123axpk = 1;
---------------------------------
|                               |
|                               |
|                               |
---------------------------------
    (void) some_name_the_user_will_never_guess_123axpk;
}

int main() {
  go();
}

go然后在用户关闭函数并打开另一个函数的情况下它不会编译。不过,请确保它没有使用嵌套函数的 GNU 扩展进行编译,或者用户可以定义其中之一。

您还必须向用户隐藏编译器错误消息,因为它将包含秘密名称。

[编辑:总而言之,如果您使用除g模板开头之外的每个可能的 1 字符名称定义函数,然后调用用户编写的函数g而不是go,您可以静态断言sizeof(__func__) == 2. 这意味着您不能使用不同的函数,因为用户无法通过 1 个字符的名称调用它。]

[另一个编辑:老鼠,这不起作用,因为用户可以用#define sizeof(X) (X, 2), 或#define __func__ "g"或类似的东西结束他们的代码。这不是合法的 C,但实际上它允许用户在几乎任何编译器上作弊。预处理器往往不会检查您使用的标记是否是未保留的名称。也许如果你做静态断言,并且做一堆检查你在那个断言中使用的标记都没有被定义为宏。]

于 2012-04-27T11:00:07.743 回答
1

当学生创建一个新函数时,您将在填充区域内有不平衡的花括号:(至少)一个额外的关闭一个(关闭当前函数体)和(至少)一个额外的打开一个(启动新功能体)。要确定是否是这种情况,您需要检查花括号是否在填充区域内平衡,您只能通过解析提交的文本来做到这一点。

于 2012-04-27T10:21:18.327 回答
1

我认为在编译时捕捉到这一点将非常困难(如果不是不可能的话)。但是,我愿意解决运行时错误,以下可能有效(在 GCC 上测试):

void go() {
---------------------------------
|                               |
|                               |
|                               |
---------------------------------
    //make sure nobody redefines __func__ ...
    #undef __func__
    //... and __builtin_strcmp
    #undef __builtin_strcmp
    //check if we're still inside go()
    assert(__builtin_strcmp(__func__, "go") == 0);
}

int main() {
    go(); 
}
于 2012-04-27T12:00:38.583 回答