シェルスクリプトで採点を簡単に
必要な環境
- bash
- gcc
実現したいこと
先生目線で学生の提出した(.c)ファイルの採点を効率化したい。
.cファイルをコンパイルして一つ一つ実行していたら日が暮れそうなので、少し効率化出来ないかと考えた。
方法
- 学生の提出したファイルを一括ダウンロード(省略)
- コンパイルして実行しテキストファイルにリダイレクト
- 正しい出力が得られるテキストファイル(模範解答)と
diff
をと -
diff
したものを再びリダイレクトする -
diff
ファイルのバイト数を調べて0バイト
でないものを確認
少しややこしいので次のような問題を考える.
問題設定
"Hello World"と改行を出力する.cファイルを作成しなさい。
ただし、"は出力せず、ファイル名は [学籍番号].c としなさい。
例えば学籍番号9999の人は 9999.c とする。
この問題の模範解答となる出力は当然Hello World
である。
目標
例えば,Hello World!!!
と出力してしまった学生を簡単に検出できるようにしたい。
準備
模範回答の準備
模範解答のソースコードとして次を準備する。
#include <stdio.h>
int main(void)
{
printf("Hello World\n");
return 0;
}
これをコンパイルした後に実行してテキストファイルにリダイレクトする。
これをシェルスクリプトにすると、
$ gcc main.c
$ ./a.out > ans.txt
実際にans.txt
の中身は
$ cat ans.txt
Hello World
となる。
また授業履修者のリストをテキストファイルにしたものを用意する。
仮に,学籍番号1111
,2222
,3333
の3人が履修していて課題の提出が確認できていたとする。
$ cat id_list.txt
1111
2222
3333
これを元に繰り返し処理を行う。
## フォルダ構成
フォルダ構成を次のようにして実行してみる。
$ tree -a
.
├── diff # diffをとったファイルを格納するフォルダ
├── id_list.txt # 履修者のリスト
├── main.c # 模範回答を出力するためのソースコード
├── make_diff.sh # 採点するためのシェルスクリプト
└── src # 学生の提出したソースコードを格納するフォルダ
├── 1111.c
├── 2222.c
└── 3333.c
## 実行
make_diff.sh
の中身を次のようにする。
gcc main.c
./a.out > ans.txt # 模範解答をリダイレクト
for id in `cat id_list.txt` # 履修者リストを元に繰り返し処理
do
cd src
gcc $id.c -o $id
./$id > $id.txt
rm $id
cd ..
diff ./ans.txt ./src/$id.txt > ./diff/diff_$id.txt # 模範解答とdiffを取る
done
これを
./make_diff.sh
で実行してみる。
権限設定で怒られることがある。
permission denied: ./make_diff.sh
その時は,ターミナルで一度だけ
$ chmod 700 make_diff.sh
と実行してからもう一度./make_diff.sh
と実行してください。
正しく実行できている場合,実行後は次のようになります。
$ tree -a
.
├── a.out
├── ans.txt
├── diff # 欲しかった結果
│ ├── diff_1111.txt
│ ├── diff_2222.txt
│ └── diff_3333.txt
├── id_list.txt
├── main.c
├── make_diff.sh
└── src
├── 1111.c
├── 1111.txt
├── 2222.c
├── 2222.txt
├── 3333.c
└── 3333.txt
2 directories, 14 files
ここで,diff
ディレクトリでls -l
とかすると各ファイルのバイト数が一気に見れる。
$ ls -l
total 8 # ここ
-rw-r--r-- 1 kkml4220 staff 0 4 23 16:17 diff_1111.txt
-rw-r--r-- 1 kkml4220 staff 39 4 23 16:17 diff_2222.txt # この人の出力が誤り?
-rw-r--r-- 1 kkml4220 staff 0 4 23 16:17 diff_3333.txt
実行環境によってバイト数を表すカラムの場所が違うかもしれないが... 明らかに0でない数字がわかる箇所がある。
となり、学籍番号2222の学生の出力が誤りであると予想できる。
実際にcat
で中身を見てみると、
$ cat diff_2222.txt
1c1
< Hello World
---
> Hello World!!!
となっている.よって学籍番号2222の方がHello World!!!
と出力しているで誤りということがわかった。
感想
もっと効率化する方法はあるかもしれない。
というかこれはブラックボックステストでしかないため、出力しか見ていないという観点で問題がある。
なので、この方法の問題点を理解した上で実行する分には問題ないかと思う。
より良い方法があればコメントしていただけるとありがたいです。
Discussion