2

Web ベースのアプリケーションを使用して、学生が提出した C プログラムを採点しています。いくつかの質問について、生徒に関数にコードを入力してもらいたいと思います。以下は、学生に表示される画面の例です。

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

main() {
  go() 
}

生徒はボックス内にコードを入力する必要があります。ただし、学生に次のような新しい関数を作成してほしくありません。

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

main() {
  go() 
}

学生が新しい関数を作成できないようにするにはどうすればよいですか? コード テンプレートは、学生が入力したコードと一緒にキューに送信され、サーバーによってコンパイルおよび実行されるのを待ちます。そのキューのコードを変更または確認できません。私にできる唯一のことは、コード テンプレートを変更することです。

4

3 に答える 3

2

Web ページに表示されないコードをテンプレートに入れることはできますか?

ユーザーにこれが表示された場合:

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 拡張でコンパイルされていないことを確認してください。そうしないと、ユーザーがそれらのいずれかを定義できます。

また、シークレット名が含まれるため、コンパイラ エラー メッセージをユーザーから隠す必要があります。

[編集: 完全なボッジとして、テンプレートの先頭を除いて可能なすべての 1 文字の名前で関数を定義しg、ユーザーが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 に答える