2013年08月21日の日記、再帰呼び出し
もお! 再帰呼び出しってば難しいんだから!!!

「続・初めてのPerl」の9章の練習問題4はそんな問題でした。
どんな言語でも一発ではうまく作れない。
この問題の場合は目安の時間は20分だったけど、なんだかんだ2時間くらいかかったw

再帰呼び出しって何かって説明します。
再帰呼び出しは、関数Aがあったとしてその中で関数Aを呼び出すような、呼び出しですw
具体例を挙げると、ディレクトリ構造とか。
会社の組織構造とか。
社長がいて、営業部があって、1課があって5人いて、2課があって3人いて、開発部があって10人いて、、、
なんか会社組織が詳しくないのであまり深くなりませんでしたが、「部」とか「課」がディレクトリ(フォルダ)で要員がファイルって感じです。
再帰呼び出しはディレクトリとファイルを列挙する例題がよく出されます。
同じ処理を繰り返してますよね。

社長のファイルがあるので表示、
営業部があるので営業部を掘る、
1課があるので1課を掘る、
5人のファイルがあるので5人表示、
上に処理が返されて、2課があるので2課を掘る、
3人のファイルが2人表示、
上に処理が返されて、(もう他にファイルorディレクトリがないので)上に処理が返されて、
開発部があるので開発部を掘る、
10人のファイルがあるので10人表示、
てな処理です。

自分なりにプログラムしたのが以下です。
#! /usr/bin/perl

use strict;
use warnings;

my $fh = *STDOUT;

&read_dir($fh, 0, ".");

sub read_dir {

my $fh = shift;
my $level = shift;
my $path = shift;

if (-f $path) {
print {$fh} " " x $level, $path, "\n";
}
if (-d $path) {

opendir my $dh, $path or die $!;
my @files = readdir $dh;
closedir $dh;

unless (@files) {
print {$fh} " " x $level, $path, ", empty directory.\n";
} else {
print {$fh} " " x $level, $path, " contains\n";
$level++;
for my $file (@files) {
next if ($file =~ /^(\.|\.\.)$/);
if (-d "$path/$file") {
&read_dir($fh, $level, "$path/$file");
} elsif (-f $file) {
print {$fh} " " x $level, $file, "\n";
}
}
}

}
}

なんだか、長ったらしくて恥ずかしいですが、いろいろ苦労して思う通りに出力できたので良しです!
【追記】
ちなみにハマったところは、「unless (@files)」の文です。
@filesをfalseとして判断するのはどうすればいいのかってところで。
unless以外もありますか?(あるだろうなあ。。。)
. contains
_template.pl
./alpaca_files contains
./alpaca_files/ch03 contains
./alpaca_files/ch04 contains
./alpaca_files/ch06 contains
./alpaca_files/ch11 contains
./backup contains
./backup/dir_ch08.06.02 contains
./backup/test1dir contains
./backup/test2dir contains
./backup/test3dir contains
_template.pl
ch09.07.pl
ch09.09.01.pl
ch09.09.02.pl
ch09.09.02_from.pl
ch09.09.02_to.pl
ch09.09.03.pl
ch09.09.03.pl~
ch09.09.04.pl
ch09.09.04.pl~


解答サンプルとしては、一度データを再帰的な構造に詰めて、そのデータを順次表示しています。
再帰的な構造とは、ハッシュでディレクトリ構造を表すことです。
データ取得とデータ表示で使い分けができるのでこちらのほうが先々便利そうですが、2回ループします。
僕は1回です!

(正直、解答サンプル見た時は「ずりぃ」と思いましたが。。。)

まあ、そんな感じで今日はあっという間に時間が過ぎてしまいました。
[PR]
by redchant | 2013-08-21 23:18 | 日記
<< Animelo Summer ... 2013年08月08日の日記、... >>