1

私は Perl プログラミングのクラスを取っていますが、先生は私たちに最初の課題を与え、実際に perl をプログラミングする方法についてはほとんど話しませんでした。これがまさに私たちの先生が割り当てたものです:

「引数として3つのファイル名を受け入れるスクリプトを作成する必要があります(スクリプトに適切と思われる名前を付けることができます)。最初のファイル名は、C ++で記述されたプログラムソースコードに対応します。2番目のファイル名は、使用される入力ファイルに対応します最初のファイル名としてリストされている C++ プログラムによって. 3 番目のファイル名は、問題のプログラムの予想される正しい出力を含むテキスト ファイルに対応します. ディレクトリ パスは、任意のファイル名で指定できます.

プログラムが入力ファイルを必要としない場合、コマンド ラインの 2 番目のパラメータはファイル名 "/dev/null" にする必要があります。

元のファイルがテストによって変更される可能性がほとんどないように、すべてのファイル (プログラム ソース、入力ファイル、および予想される出力ファイル) をスクリプトで使用する前に、スクラッチ テスト ディレクトリにコピーする必要があります。手順。スクラッチ ディレクトリが存在しない場合は、スクリプトで現在の作業ディレクトリのサブディレクトリとして作成する必要があります。

スクリプトは、GNU g++ コンパイラを使用して、ソースのスクラッチ コピーをコンパイルおよびリンクする必要があります。その後、スクリプトはプログラムを実行する必要があります。出力は、スクラッチ テスト ディレクトリに保存されている一時ファイルに保存されます。

プログラムを実行した後、スクリプトは UNIX コマンド diff を使用して、前の手順で生成された実際の出力を予想される出力ファイルと比較し、出力が仕様に準拠していることを報告するか、diff プログラムによって報告された相違点を報告する必要があります。

完了後、スクリプトはすべての一時コピーとスクラッチ ファイルを削除する必要があります。元のプログラム、元の入力ファイル、元の予期される出力ファイル、またはスクラッチ ディレクトリ自体を削除しないでください。」

私はこれまでのところこれを持っています:

#!/usr/bin/perl -w

use strict;

my ($line, $program, $input, $output);

print "Give the program, input, and standart output for testing. ";

$line = <>;
chomp $line;

($program, $input, $output) = split/\s+/, $line; # split/\s+/ is to separate spaces from the input

my($o_test) = $output + "_test";

print "$program ";
print "$input ";
print "$output ";

system("mkdir test_scratch") == 0
or die "failed to create test_scratch. exiting...."

system("cp $program, /test_scratch/"); # error
system("cp $input, /test_scratch/");
system("cp $output, /test_scratch/");

system("cd test_scratch");

system("g++ $program");
system("chmod +x a.out");

system("./a.out < $input > $o_test");

my($DIFF) = system("diff $output $o_test") # error

if[ $DIFF != ""]
    print ("Output conforms to specifications."); # error
then
    print ("$DIFF");
system("cd ..");

コード内の # でエラーが発生します。「/dev/null」の実行方法すらわかりません。私はオンラインで物事を調べたり、stackoverflow を検索したりするのに多くの時間を費やしましたが、他に何をすべきかわかりません。これは非常に長い質問だと思いますが、他に何をすべきかわかりません。あなたが私に与えることができるどんな助けにも感謝します.

4

2 に答える 2

1

ここで役立つモジュールがいくつかあります。私が最初にお勧めするのは、ビルドプロセスを管理できるExtUtils::CBuilderです。次に、File :: Copyを使用して一時フォルダーに移動したり、File::chdirを使用して作業ディレクトリを管理したりすることもできます。教授はおそらくあなたがすべきだと指定しているので、diffそのタスクを実行するモジュールがあります。または、Test :: Moreを使用して、出力が期待どおりであることを確認できます。


将来の参考のために、これは私が同様のタスクを実行する方法です(temp dirを保持しないでください、必要ありませんdiff):

#!/usr/bin/env perl

use strict;
use warnings;

use File::chdir;
use File::Temp;
use File::Copy;
use File::Basename;
use File::Slurp;

use ExtUtils::CBuilder;
use Test::More tests => 1;

die "Not enough inputs\n" unless @ARGV >= 3;

# create a temporary directory
my $temp = File::Temp->newdir;

# copy all arguments to that temporary directory
copy $_, $temp for @ARGV;

# store only the filename (not path) of each argument
my ($cpp_file, $in_file, $expected_file) = map { scalar basename $_ } @ARGV;

# change working directory to temporary one (via File::chdir)
local $CWD = $temp;

# build the executable
my $builder = ExtUtils::CBuilder->new(config => {cc => 'g++'});

my $obj = $builder->compile( source => $cpp_file, 'C++' => 1 );
my $exe = $builder->link_executable( objects => 'hello.o' );

# run the executable
my $output = `./$exe $in_file`;

# read in the expected file
my $expected = read_file $expected_file; 

# test the resulting output
is $output, $expected, 'Got expected output from executable';

出力ファイルと予想されるファイルの改行に注意する必要がある場合があることに注意してください。

于 2012-10-06T22:13:30.937 に答える
0

コード内の # でエラーが発生します。

このエラーの簡単な修正は、カンマを削除することです。標準の Linux cp コマンドでは、送信元と送信先の間にコンマは必要ありません。Perl でファイルをコピーするためにFile::Copyを検討することもできます。

「/dev/null」の実行方法すらわかりません。

/dev/null は、空を指す標準の Linux ファイル (*) です。このファイルにバイトを書き込むと、それらは消えます。このファイルからバイトを読み取ろうとすることができますが、そこには何もありません。

これにより、次の 2 つのオプションが残ります。

  1. /dev/null を直接使用するだけで、プログラムは空のバイト ストリームから何も読み取ることができなくなります。
  2. 入力ファイルが /dev/null と等しいかどうかを確認し、入力が /dev/null の場合は C++ プログラムに入力値を渡さないでください。

どちらの方法でも機能します。/dev/null をディレクトリにコピーすると、「null」と呼ばれる長さゼロの新しいファイルが作成されます。これは、C++ プログラムにとって完全に有効な空の入力ファイルです。

(*) いいえ、/dev/null は、Windows の世界から来た場合に慣れている意味でのファイルではありません。ディスク上には存在しません。しかし、古典的な Unix の哲学は、たとえそのファイルがディスク上に存在しなくても、すべてのデータ ソースをファイルにすることです。例として、Linux の /proc ファイルシステムを参照してください。これにより、ディレクトリ ツリー構造で CPU、プロセスなどに関する情報を確認できます。その哲学は、ソケット API がまったく別のルートを取るまで、多少は持ちこたえました。ネットワーク接続や画面など、基本的にすべてをファイルにするオペレーティング システムを探している場合は、 Plan 9を調べてください。ただし、宿題をPlan 9で行い、Linuxで動作することを期待することはお勧めしません.


system注: g++ が C++ プログラムのコンパイルに失敗した場合、存在しないコンパイル済みプログラムを実行する方法がないため、 からの戻りコードを確認することを忘れないでください。

于 2012-10-06T21:56:41.480 に答える