• ベストアンサー

ファイルオープンのサブルーチンを作っているのですが

ファイルオープンのサブルーチンを作っているのですが、二つ目の「sub Open_DB_plus」が動作してくれません。 一つ目の「sub Open_DB」はとりあえずうまく動作したのですが、このルーチンを使ったファイルオープンを前後して使用すると以前に読み込んだファイルにより、ここで読まれるべき「@indata」が上書きされてしまうことに気づき、配列名まで指定できるよう二つ目の「sub Open_DB_plus」を作り始めたのですが、こちらは配列名を受ける「$list_name」に値が入りません。 ふたつめの「sub Open_DB_plus」を動作可能な状態にするにはどうしたらよいでしょうか? # EX:&Open_DB("$Dir","$Name",'.txt'); sub Open_DB{ my ($path,$pickfile,$type) = @_; $file_name = "$path/$pickfile"."$type"; open (FILE, "< $file_name"); @indata = <FILE>; close(FILE); }#-----END # EX:&Open_DB_plus('@indata',"$Dir","$Name",'.txt'); sub Open_DB_2{ my ($listname,$path,$pickfile,$type) = @_; $file_name = "$path/$pickfile"."$type"; $list_name = "$listname"; open (FILE, "< $file_name"); $list_name = <FILE>; close(FILE); }#-----END:

質問者が選んだベストアンサー

  • ベストアンサー
  • Werner
  • ベストアンサー率53% (395/735)
回答No.1

> こちらは配列名を受ける「$list_name」に値が入りません。 値は入っていると思いますよ。 > &Open_DB_plus('@indata',"$Dir","$Name",'.txt'); この引数で呼び出したなら、 > my ($listname,$path,$pickfile,$type) = @_; この行で $listname に文字列 '@indata' が入って、 > $list_name = <FILE>; この行で $list_name に<FILE>の1行目が入ります。(もともと入っていた文字列 '@indata'は上書きされます。) まあ、このサブルーチン内で$list_nameを書き換えたところで、 サブルーチン外の配列@indataには全く影響しませんが。 ファイルを読んで、指定した配列に内容を格納したいなら、 配列をreturnするか、配列へのリファレンスを引数で渡してみてはどうですか? (evalを駆使する手もあるけど、お勧めできない。) 以下はサンプル。 -------------------------------------------------- use strict; sub read_file1($){   my ($file_name)= @_;   open (FILE, "< $file_name");   my @list = <FILE>;   close(FILE);   return @list; } my @data1; @data1 = &read_file1("data.dat"); print @data1; sub read_file2(\@$){   my ($ref_list, $file_name) = @_;   open (FILE, "< $file_name");   @$ref_list = <FILE>;   close(FILE); } my @data2; &read_file2(\@data2, "data.dat"); # read_file2(@data2, "data.dat"); #としても良い。 print @data2;

perlerz10
質問者

お礼

教えていただいたルーチンを使ってみたのですが、状況変わらずでした。やはり上記補足に記載してあるように、&header;ルーチン内でも「&Open_DB」で@indata)を作ってるのがトラブルの原因のようです。

perlerz10
質問者

補足

ご返答ありがとうございます。 教えていただいた方法を勉強させていただいているところなのですが、トラブル発生状況を追記しておきます。 ひとつめの「&Open_DB」でトラブルが発生したのは以下のようなソースの場合です。 &headerにおいても、「&Open_DB」で別のファイルを読み込んでいます。 これですと、「#ここ」で指定したファイルハンドルの先のファイルをサブルーチン内で読むには読むのですが、開いたファイルの内容が「@db_array」に入らないといった状況です。ですからテストに「@indata」の要素数を出力させても本来10と出るはずがそうならないのです。 &Open_DB("$Dir","$Name",'.txt');#ここ if(@indata){ $count = @indata;#for test &header; print "$count"; print "<ul>"; foreach $item(@indata){ @db_array = split(/\,/, $item); print "<li>$db_array[0] / $db_array[1]</li> "; } print "</ul>"; } else{ &header; print "$checktodayは空です。<br />\n"; } &footer; exit;

その他の回答 (1)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

ん~, 1つ目をベースに ・@indata を my でレキシカルにして, ・close したあとこの @indata を返す ようにするのが安全かなぁ? メモリが気になるなら配列のリファレンスをもらうようにする.

perlerz10
質問者

お礼

Tacosanさん、Wernerさん、ありがとうございました。 Wernerさんに示していただいた2つめのルーチンで問題ありませんでした。Tacosanさんの「配列のリファレンスをもらう」案も今後に備えて用意してみたいと思います。 NTT回線工事の時間帯に追われ、ばたついたお礼で申し訳ございません。 ありがとうございました。

perlerz10
質問者

補足

ご返答ありがとうございます。 「配列のリファレンスをもらう」という方法もやってみます。 ひとつめの「sub Open_DB」をつかったときのトラブル発生状況を追記してみました。