トップページ⇒php
1001コメント404KB

Perlコーディング初心者質問スレ Part 60

■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん2009/09/03(木) 23:51:12ID:???
Perlのコーディングで困ってる人のスレです。

【投稿する際の注意】
質問するときは内容をよく吟味してから投稿してください。
「コマンドの意味がわかんない」とかはマニュアル見ましょう。
回答者さんは何でも屋じゃありません。

1: 自分はこういう事がしたい。
2: それでこんな風にやってみたが・・・
3: こんなエラーが出て上手く行かなかった。

最低でも1と3が無いと誰も答えられないよ。
良い回答は良い質問から。一緒に勉強しましょう。

お勧めサイトは >2 以降

前スレ http://pc11.2ch.net/test/read.cgi/php/1234752149/
0266nobodyさん2009/11/23(月) 07:58:49ID:???
三項演算子使え。
$a =(条件1) ? 'x'
  :(条件2) ? 'y'
  :      'z'
  ;
0267nobodyさん2009/11/23(月) 09:00:29ID:???
三項演算子って二者択一の時はよく使うけど、
長い式になると優先順位がわかりづらくて使いづらい。。。
0268nobodyさん2009/11/23(月) 09:19:12ID:???
>>263
5.10未満ならSwitchモジュールを

switch文
http://www2u.biglobe.ne.jp/~MAS/perl/waza/switch.html
0269nobodyさん2009/11/23(月) 09:35:35ID:XYWla5BP
連想配列に呼ぶべき関数へのリファレンスぶち込んじゃってる
ただこれをやると関数への引数は連想配列へのリファレンスにならざるを得ないから、あまりやらないけど・・・
0270nobodyさん2009/11/23(月) 10:26:54ID:???
>>269
こんな感じ?

my %func = ( foo => \&foo, bar => \&bar );

$func{foo}(1, 2); #=> 1 2 in foo

sub foo {
print "@_ in foo";
}

sub bar {
print "@_ in bar";
}

>関数への引数は連想配列へのリファレンスにならざるを得ない
これはどういう意味ですか?
0271nobodyさん2009/11/27(金) 23:39:39ID:???
情報オリンピックの
http://www.ioi-jp.org/joi/2008/2009-yo-prob_and_sol/2009-yo-t2/review/2009-yo-t2-review.html
の問題なのですが、
open(A,">a.txt");
$a=36;$b=20;$c=38;$d=54;$e=42;$f=25;@a={$a,$b,$c,$d,$e,$f}
foreach(@a)
{$one=0;
$two=0;
$thr=0;
if( $_ >= $one){
$one=@a;
$two=$one;
$thr=$two;
}elsif( $_ >= $two )
{$two=@a;
$thr=$two;
}elsif( $_ >= $thr )
{$thr=@a;}}
$total=$one+$two+$thr;
print A"$total";
何がいけないのでしょうか?
perlを勉強初めて数日の私にもわかるように教えていただけないでしょうか

あと、情報オリンピック予選にperlで出てみたいのですが、入力ファイルのtxtファイルを読み込んで、出力ファイルを作るということですよね?
出力するのは、
open(A,">a.txt");
print A "〜";
みたいなので良いんですよね?どうやったらtxtファイルを読み込めるんですか?たとえばtxtファイルの三行目の数をhと定義したりすることはどうすればいいんですか?
0272nobodyさん2009/11/28(土) 00:15:26ID:???
その問題は、20個の数字がいるんじゃないの?
0273nobodyさん2009/11/28(土) 00:25:39ID:???
どこもかしこも間違いだらけで、訂正する気にならん。

=== hoge.pl ===
sub calc { eval join '+', ( sort {$b <=> $a } @_ )[0 .. 2] ; }
my @data = <> ;
printf "%d %d\n", ( calc @data[0..9] ), ( calc @data[10..19] ) ;
======
perl hoge.pl INPUT.txt > OUTPUT.txt


0274nobodyさん2009/11/28(土) 00:41:49ID:BdimRB/2
>>271の問題が見たいんだけどどこかにないの?
解説だけでどういう問題化わからん。リンクもないし
0275nobodyさん2009/11/28(土) 00:46:47ID:???
ttp://www.ioi-jp.org/joi/2008/2009-yo-prob_and_sol/2009-yo-t2/2009-yo-t2.html
0276nobodyさん2009/11/28(土) 01:55:55ID:BdimRB/2
>>271
その問題を解くように変えようとするとなると>>273の言う通り一から書き直した方がいいので、
とりあえずそのプログラムで書きたいと思われることを最大限書き直してみた。
use strict; // 初心者ならなおさらstrictとwarningsは入れた方がいい
use warnings;

my($a, $b, $c, $d, $e, $f)
  = (36, 20, 38, 54, 42, 25);
my @data = ($a, $b, $c, $d, $e, $f); // 配列は{}じゃなく()。

my($one, $two, $thr) = (0, 0, 0); // foreachの外で使うならforeachの外で初期化しないと毎回0で上書きされる
foreach my $num (@data) { // わかりやすいように$_じゃなくて名前付けておいた方がいい
// ホントは=ない方が処理少ないので=ない方がいいと思う
  if ($num >= $one) {
    $two = $one;
    $thr = $two;
    $one = $num; // 初めに$oneに代入したらその後$twoにも$thrにもコピーされるから最後で。
  } elsif ($num >= $two) {
    $thr = $two;
    $two = $num; // 上と同じ理由
  } elsif ($num >= $thr) {
    $thr = $num;
  }
}

my $total = $one + $two + $thr;

open my $wfh, ">", "a.txt" or die "$!"; // 3引数のopen使った方がいいのと、なるべく開いたらすぐ閉じた方がいいのでまとめるべき。
print $wfh $total;
close $wfh; // open したら closeしないとダメ
こんな感じかな。問題解くならPerlの前にアルゴリズムも勉強しないといけない気がするな
0277nobodyさん2009/11/28(土) 02:14:34ID:???
Perlでも//コメントって使えたっけ
0278nobodyさん2009/11/28(土) 04:02:22ID:BdimRB/2
あ。ごめん、レスする時にコメント付けたから間違えた
0279nobodyさん2009/11/28(土) 13:14:18ID:???
$thrと略すのはやめようぜ。
文脈から分かるとはいえ、一見だと$thresholdや$throttleかも?と思うだろ。
0280nobodyさん2009/11/28(土) 14:37:12ID:???
みなさん分かりやすい解説ありがとうございます。
>>275さんの問題の通りこのような入力例が与えられて、出力しないといけないのですが、
my($a, $b, $c, $d, $e, $f)
  = (36, 20, 38, 54, 42, 25);
のように自分で打たずに、txtファイルから読み込む方法を教えていただけないでしょうか。
0281nobodyさん2009/11/28(土) 14:41:24ID:???
foreach my $num(<ファイルハンドル>){
#一行ずつ$numに代入する。
}

こんな感じかな?
0282nobodyさん2009/11/28(土) 14:55:14ID:???
open(A,">a.txt");
my($one, $two, $thr) = (0, 0, 0);
foreach my $num (b.txt)
{
if( $num >= $one)
{
$two=$one;
$thr=$two;
$one=$num;
}elsif( $num >= $two )
{
$thr=$two;
$two=$num;
}elsif( $num >= $thr )
{
$thr=$num;
}
}
$total=$one+$two+$thr;
print A"$total";
こういうことではないのですか?
これでは0になってしまったのですが
0283nobodyさん2009/11/28(土) 15:30:00ID:???
おまえら初心者にやさしいなw
0284nobodyさん2009/11/28(土) 15:32:33ID:???
おまえら初心者にやさしいなw(by プログラム組めない>>283)
0285nobodyさん2009/11/28(土) 15:35:37ID:???
>>283
流石に組めますよ。
二種はCOBOLで取った世代ですw
0286nobodyさん2009/11/28(土) 15:37:19ID:???
>>283じゃなく>>284だった(; ´Д`)
0287nobodyさん2009/11/28(土) 15:41:19ID:BdimRB/2
>>281を見た段階で>>282の結果が予測できたなw

>>271
初心者スレとはいえ、最低限の文法をググるか本読んだ方がいい
サンプルコードたくさん落ちてるじゃん
ファイルへの書き込みがopen my $wfh, ">", "a.txt"ってのと同じように
読み込みはopen my $rfh, "<", "b.txt"だよ
0288nobodyさん2009/11/28(土) 15:45:27ID:???
>>282
open FH, "<hoge.txt";
foreach(my $line = <FH>){ … }
close FH;


入門書読んだ?
0289nobodyさん2009/11/28(土) 15:47:29ID:???
間違えた
foreach → while

@hoge = <FH>;
でも入力は取れる
0290nobodyさん2009/11/28(土) 16:18:26ID:???
すいません。学校で習っただけで…
あとレファレンスとか見てもどこに載っているのかわからないので…
02912812009/11/28(土) 18:03:02ID:???
あ・・・ごめん
ファイルハンドルはファイルの名前の事だよ
普通はファイルの入出力のところに載ってると思うけど
02922912009/11/28(土) 18:04:34ID:???
ごめん、修正
ファイルハンドルはファイルを識別するための任意の文字列の事だよ
でした
0293nobodyさん2009/11/28(土) 18:06:13ID:???
こういうのって普通は>>273みたいに標準入力から取るんじゃないの?
0294nobodyさん2009/11/28(土) 18:15:00ID:???
問題の趣旨から考えたら、標準入力から取ると思う
02952932009/11/28(土) 18:16:33ID:???
ああ標準入力じゃないや、ダイヤモンド演算子使ってファイル入力でってことね
0296nobodyさん2009/11/28(土) 21:24:20ID:???
みなさんの言っていることが高度すぎて意味不明です…
こういうことではないんですか?
open(A,">a.txt");
my($one, $two, $thr) = (0, 0, 0);
open FH, "<b.txt";
foreach(my $line = <FH>)
{
if( $num >= $one)
{
$two=$one;
$thr=$two;
$one=$num;
}elsif( $num >= $two )
{
$thr=$two;
$two=$num;
}elsif( $num >= $thr )
{
$thr=$num;
}
}
$total=$one+$two+$thr;
print A"$total";
02972962009/11/28(土) 21:38:36ID:???
line4 $line -> $num
追加 -> close FH;
02982962009/11/28(土) 22:12:32ID:???
use strict;
use warnings;
open(A,">a.txt");
my($one, $two, $thr) = (0, 0, 0);
open FH, "<b.txt";
foreach my $num (<FH>)
{
if( $num >= $one)
{
$two=$one;
$thr=$two;
$one=$num;
}elsif( $num >= $two )
{
$thr=$two;
$two=$num;
}elsif( $num >= $thr )
{
$thr=$num;
}
}
my $total = $one + $two + $thr;
close FH;
print A"$total";

これで何とかできているようです。が、
argument "\n" isn't numeric in numeric gt at 〜.pl line8, <FH> line8.
と出るのは何なのでしょう
あと、一行ごと読みこむ場合は分かったのですが、
http://www.ioi-jp.org/joi/2008/2009-yo-prob_and_sol/2009-yo-t1/2009-yo-t1.html
のような場合はどうやって読み込むのでしょう
0299nobodyさん2009/11/28(土) 22:25:29ID:???
過去問全てここの人間に教わろうってのか?w
03002962009/11/28(土) 22:32:47ID:???
>>299
いえ、別にそういうわけではありません。
とりあえず、読み込み方は自分には見つからなかったので、教わりたいなと思ったので…
すいません
0301nobodyさん2009/11/28(土) 22:34:31ID:???
>>271の質問に対しては>>273は答えになってますよ。わざとeval使ったりしてますけど、
perlだとこんなに短く書けるよということで面白い。本人が理解できなきゃ意味ないか。

>>298
foreach my $num (<FH>) はやめれ。これだとファイルの中身をすべてメモリに読み込むので、
今回はいいけど、このファイルが数百万行あったらどうする。普段から
while (my $num = <FH>) {
chomp $num; # 各行のデータには改行コードがくっついたままなので取り除く
# 処理
}
としておくのが吉。
argument "\n" isn't numeric in numeric gt at 〜.pl line8, <FH> line8.
は、改行コードがくっついている値を数値比較したから。
こういうのもuse warningsを付けているから出るわけです。

> http://www.ioi-jp.org/joi/2008/2009-yo-prob_and_sol/2009-yo-t1/2009-yo-t1.html
> のような場合はどうやって読み込むのでしょう
結局何もかも分からないわけですね。
いくら初心者スレとはいっても、少しはわかるようになるまで学習してから取り組んだらいかが。
03023012009/11/28(土) 22:42:45ID:???
書き忘れたが、
>>298
のコードだと、2つの大学全体の上位3つの合計になってしまうよ。問題の要件を満たしていない。
あと、普通こういうので入力/出力といったら標準入力/標準出力ではないかと思います。
その点でも>>273は満たしてくれている。
0303nobodyさん2009/11/29(日) 00:50:13ID:???
こんなひどいのは久々に見た
新鮮だなぁ
0304nobodyさん2009/11/29(日) 01:42:21ID:1LHj/rCz
とはいえ、がんばろうとしてる姿勢が見えるのはいいなぁ
学校で習ってすぐの覚えたてで何か問題解こうとここに聞きにくるのとかポジティブだよねw

最近の書き方だと下のが結構まとまってると思う。
ttp://d.hatena.ne.jp/perlcodesample/20091120/1246679588
あと、標準入力とかダイヤモンド演算子の話はもっと簡単なサンプルコードを書くところから始めた方が理解できると思う
0305nobodyさん2009/11/29(日) 10:19:40ID:???
初心者というのは「本を一冊読みました。今始めてプログラムを書いています。
こういう処理したいんだけど、読んだ本だといまいちわかりません」
というレベルじゃないのか?
文法すら知らないのは初心者ではなく教えてちゃんだ。
0306nobodyさん2009/11/29(日) 10:40:54ID:???
>>304
「最近の書き方」じゃねーよ、単なる個人の趣味じゃねえか
悪くは無いが。

で、ここの最近のレスも合せてどうしても突っ込みたくなったから書くが、
× while( my $line = <FH> ){}
◯ while( defined ( my $line = <FH>) ){}
perldoc perlsyn にも書かれてる。
0307nobodyさん2009/11/29(日) 11:07:16ID:???
>単なる個人の趣味じゃねえか
「リンク先の内容が、リンク先の書いた奴の」って意味ね。
03082962009/11/29(日) 11:57:19ID:???
いろいろ調べて>>273の意味が分かりました。ありがとうございました。
で、朝
http://books.yahoo.co.jp/book_detail/AAY78372/
この本を買って今読んでいるのですが、read関数の使い方がよく分かりません
どなたか教えていただけないでしょうか
0309nobodyさん2009/11/29(日) 12:28:14ID:???
整数である第二引数のバイト分を第一引数のファイルハンドルから読み込んで返す関数だっけ?
0310nobodyさん2009/11/29(日) 12:30:07ID:???
整数である第三引数のバイト分を第一引数のファイルハンドルから読み込んで第二引数に入れる関数だった
0311 ◆CB400SBcg9B9 2009/11/29(日) 13:10:34ID:???
>>304
「聞きに来る」時点で全然ポジティブでも何でもないです。
所謂「クレクレ」でしかないです。

例え「車輪の再発明」と云われても自分で調べ、自分で考えてその結果をここに書き連ねてこそポジティブっていうもんです。

世知辛いこの世の中、ただただ「速さ」だけを求められて、こういった「クレクレ君」が憚っているのが現状だと思うと悲しいんだけれどもね。。。
0312nobodyさん2009/11/29(日) 13:53:22ID:???
>>311
スレ違い
03132962009/11/29(日) 16:04:52ID:???
>>309,310
空白は1バイトですか?
あと、何文字目から何文字目までということはできますか?
0314nobodyさん2009/11/29(日) 16:11:18ID:???
>>312
バイトがなんなのか理解してないの?
ここで聞く前にもっと勉強した方がいいと思うよ
検索すれば出る内容なんだから
0315nobodyさん2009/11/29(日) 16:12:07ID:???
>>313だった
>>312スマソ
0316nobodyさん2009/11/29(日) 21:02:25ID:???
#最近perlを勉強し始めたのですが、サブルーチンが呼び出せなくて困っております・・・
#GCDの計算です。

print "input number 1\n";
$a = <STDIN>;
chomp($a);

print "input number 2\n";
$b = <STDIN>;
chomp($b);

$n = &gcd($a,$b);


sub gcd{
if($c != 0){
$c = $_[0] % $_[1];

$n = &gcd($gcd[1],$c);

}else{
print "G.C.D is $_[0]";
}

}
#よろしくおねがいします。
0317nobodyさん2009/11/29(日) 21:16:37ID:???
ifの中の$cはどこから来てんだよ
0318nobodyさん2009/11/29(日) 21:38:42ID:???
アルゴリズムおかしいけどサブルーチンは呼び出せてるよ?
input number 1
18
input number 2
32
G.C.D is 18%
0319nobodyさん2009/11/29(日) 21:48:48ID:aDLivjg2
STDIN からの入力って改行入ってなかったっけ?
0320nobodyさん2009/11/29(日) 21:49:22ID:???
>>319
chomp見逃すなよ……
0321nobodyさん2009/11/29(日) 21:55:47ID:???
永久機関みたいなサブルーチンだ。
0322nobodyさん2009/11/29(日) 21:57:26ID:???
アルゴリズムが崩壊してるな
これはひどい
03233162009/11/29(日) 22:02:31ID:???
>>317
これも引数にしないとだめだったんですか?
$cをメインルーチンに追加して試してみましたがだめでした・・・

>>318
サブルーチンは呼び出せているのですが、ifの中身がうまく処理できずにelseの処理にうつってしまいます

GCDのアルゴリズムは
_[0]と_[1]を割って余りを$cに代入
$cが0でなければ_[1]を_[0]に、$cを_[1]に代入
$cが0になるまでこれを繰り返す
$cが0なら[0]を出力

間違ってましたかね

0324nobodyさん2009/11/29(日) 22:04:07ID:???
>>318
だから$cがどこから来てんのかって話だよ
後半の問題も$cが何処から来てんのかって問題
0325nobodyさん2009/11/29(日) 22:11:31ID:???
やりたいのはこういうことじゃないの?
sub gcd {
  my($a, $b) = @_;
  if ($a < $b) { # $bの方が大きければ逆にする
    ($a, $b) = ($b, $a);
  }

  if ($b != 0) {
    gcd($b, ($a % $b));
  }
  else {
    print "G.C.D is $a";
  }
}
$_[0]とか$_[1]を使い回さない方がいい。
色んな場所で使うなら最初に違う文字に置き換えた方が無難
$nも使わないならわざわざいらないでしょ
>>323の順番に処理して行ったらif文が割り算の前に出てくるのもおかしいよね
0326nobodyさん2009/11/29(日) 22:15:22ID:???
>>325
それ、ユークリッドの互除法になって無いぞ。
$_[0], $_[1] を使い回す方が、 $a, $b を my するよか千倍マシだ。
0327nobodyさん2009/11/29(日) 22:21:39ID:???
>>326
あれ?ちがうんだっけ。昔の記憶のまんま書いてみて答えあってたからいいかと思った

つか、普通$_[0]とか使い回すもん?
実際、何の値入ってるかわかんなくなって>>316みたいなコード書く元になるから使い回すなら置き換えた方がいいと思うんだけど。
0328nobodyさん2009/11/29(日) 22:33:53ID:???
書き換えた方が良いのは同意だが、$a, $b はソートブロック内で使用
される特殊変数だ。
それを他の場所で使うくらいなら、 @_ を使う方がましだと言っている。
my $. = 'hoge' ;
↑これをするのと同じくらい変態行為。

>>325
>if ($b != 0) {
これ常に真だが?
0329nobodyさん2009/11/29(日) 22:40:51ID:???
>>328
あぁ、なるほど。$a,$bは特殊変数で使われるんだっけ。
普段$aとか$bは使わないけど>>316のコードをなるべく生かそうと思って失敗したわ。

>>if ($b != 0) {
>これ常に真だが?
最終的に余りゼロになるでしょ?
0330nobodyさん2009/11/29(日) 22:47:49ID:???
だから $b がどうして、$a % $b の値になんのよ?
ここまで説明しなきゃ解らんのか?
03313262009/11/29(日) 22:55:42ID:???
ゴメン、お前が正しかった。吊ってくる。
03323162009/11/29(日) 23:06:02ID:???
>>325のアルゴリズムですっきりできました
この程度もわからなかっただなんてしにたい

print "input number 1\n";
$a = <STDIN>;
chomp($a);

print "input number 2\n";
$b = <STDIN>;
chomp($b);

&gcd($a,$b);

sub gcd{
if($_[1]>$_[0]){
($_[1],$_[0])=($_[0],$_[1]);
}
if($_[1] != 0){
&gcd($_[1],($_[0] % $_[1]));
}
else{
print "G.C.D is $_[0]";
}
}
0333nobodyさん2009/11/29(日) 23:23:23ID:???
>>332
えっと、そう書くことになるから「$_[0]と$_[1]に何が入るかわからなくなるので、使う初めに置き換えた方がいいよ」って話ね

例えば、今回とは別の例としてそのsubが30行くらいあったとして、君が1週間後にメンテナンスするとするでしょ?
ぱっと一番下のprintを見た時に「あぁ、$_[0]だから引数の一番目の値を出力してるな」とか思っちゃうわけだけど、
その前に入れ替えやってるからそうとは限らない。

そうするとメンテする時に変数の代入をしている所を確認する作業が増えて面倒。
少なくとも「$_[番号]は引数の順番通りに入ってる」って思ってる人は多いから入れ替えとかしない方がいいよ
0334nobodyさん2009/11/29(日) 23:28:53ID:???
>>332
use strict;
をスクリプトの2行目に書くのをオススメする
変数のスコープを理解すべし
死ぬのはそれからだ
0335nobodyさん2009/11/30(月) 00:16:25ID:???
$a $bを使うんじゃねえ
03363322009/11/30(月) 00:49:26ID:???
>>333
サブルーチンの外で入れ替える、ということですね。気をつけます。。

>>334
わかりました。
perlは今までやってきたCやJavaと比べて書きやすいのですが、
やっぱりある程度の制約を強要したほうがエラーが起こりにくいということがよくわかりました。
0337nobodyさん2009/11/30(月) 01:26:09ID:???
>>336
> サブルーチンの外で入れ替える
まあそれでも動くっちゃあ動くが違うだろ

普通に考えれば関数の先頭で
my($num1, $num2) = @_;
($num1, $num2) = ($num2, $num1) if $num2 > $num1;
などとして、以後$_[X]の代わりに$numXを使うという意味だ
0338nobodyさん2009/11/30(月) 02:19:08ID:HMASs2oD
DBIのデータベースハンドルを属性に擁するクラスを作っています。
このクラスのオブジェクトを使用してDBIのメソッドを呼ぶとき、
$obj->dbh->prepare(@args); #データベースハンドルのゲッタを介した呼び出しではなく
$obj->prepare(@args)    #こう呼びたいと思っています。
そこでAUTOLOADを定義して委譲するように書いたのですが、ここで不明な点があるのです。

sub AUTOLOAD {
 my $self = shift; my @args = @_;
 our $AUTOLOAD;                #呼ばれたメソッドの完全修飾名
 my $method_name = (split '::',$AUTOLOAD)[-1]; #メソッド名部分を切り出し
 if ($self->dbh->can($method_name)) {     #メソッドがDBIにあれば
  return $self->dbh->$method_name(@args);   #DBIのメソッド呼び出し(ここが疑問)
 }
}

例のようにprepareを呼べばステートメントハンドルが返り、つまり正しく動いてるのですけど、
$method_nameは(多分)文字列なのに、どうしてメソッド呼び出しがおこなわれるのかわかりません。

経緯としては、試しに書いてみたら動いてしまい、
後追いで理屈の裏づけをとりたいと思ったら答えが見つからない、という状況です・・。
(use strict環境なのでシンボリック参照ではないですよね。)
説明つく方いましたらお願いしますm(_ _)m
0339nobodyさん2009/11/30(月) 03:57:11ID:???
仕様
0340nobodyさん2009/11/30(月) 04:00:49ID:???
ム板のPerlスレで聞いた方がいいな
0341nobodyさん2009/11/30(月) 04:53:13ID:???
>>338
気持ち悪いならこういう風に書き換えることができたはず

if (my $ref = $self->dbh->can($method_name)) {
  return $ref->(@args);
}
0342nobodyさん2009/11/30(月) 05:29:57ID:???
>>341
dbhの返り値を第1引数に入れなくてもいいの?
03433382009/11/30(月) 07:20:28ID:HMASs2oD
>>341
なるほど!ありがたいヒントをいただきました。
canはメソッドの参照を返しているんですね。こちらは納得です!
自分のケースでは次のコードで結果を得ることができました。

if (my $method_ref = $self->dbh->can($method_name)) {
 my $sth = $self->dbh->$method_ref(@args);
 return $sth;
}

この際>>338の疑問はなかったことにしようと思いますw
0344nobodyさん2009/11/30(月) 09:31:48ID:???
>>343
AUTOLOAD呼び出しのコストを1回だけにするのは、あんまり意味ないかな?

404 Blog Not Found:Perl Monger の質問 - AUTOLOADって他でどうやるの?
http://blog.livedoor.jp/dankogai/archives/50491359.html


if (my $method_ref = $self->dbh->can($method_name)) {
 no strict 'refs';
 *{$method_name} = sub { shift->dbh->$method_ref(@_) };
 unshift @_, $self;
 goto &$method_name;
}
0345nobodyさん2009/11/30(月) 11:18:10ID:???
>>344
この goto は普通に関数呼び出しじゃダメなのかな…
0346nobodyさん2009/11/30(月) 18:34:17ID:???
->の先って文字列でもコード参照でもよかったんだな
自由すぎる
03473382009/11/30(月) 18:49:13ID:???
>>344
ありがとうございます。
自分が事前に得ていたのも>>344のようなコードでした。
$AUTOLOADに渡ってきた名前のメソッドを、型グロブを使って現在のパッケージに動的に追加し
そのメソッドに処理を転送、という意味だと思うのですが、
自分もちょっと大げさだなと思って・・・
(ちなみに今、手元にオライリー本を数冊置いてるのですが、いずれも類した手法を紹介してるんです)

しかし「AUTOLOAD呼び出しを減らす」メリットには気がつきませんでした。
以降は新しいメソッドが呼ばれるから逐次AUTOLOADが呼ばれるコストが削減できるということなんですね。
(AUTOLOADはクラス階層を全部探した最後に呼ばれるから高コスト)

自分の場合はCGIなので、アクセスごとにメソッド生成がおこなわれてしまうこともあるのですが、
複数のクエリを発行する状況ではメリットあるかもしれないです。
クラスの使用状況を見ながら適宜判断してみようと思います。

CGIなら普通に、使う分だけラップしたメソッド書いとけって話もあると思いますが^^;
たいへん参考になりました!
0348nobodyさん2009/12/02(水) 03:41:18ID:0CcBOFc0
コンソールでデータの処理とかに Perl を使ってるのですが、実行中に Uninitialized value とかの
Warning が出た時点でスクリプトの実行を一時停止させるには、怪しいところを eval でトラップさせるしかないのでしょうか?

それともデバッグに役立つようなモジュールとかあるのでしょうか?
0349nobodyさん2009/12/02(水) 06:42:16ID:???
>>348
% perl -d hoge.pl

ここに色々書いてあるから見てみるといい
http://www.ibm.com/developerworks/jp/linux/library/l-pl-deb/
0350nobodyさん2009/12/02(水) 09:26:53ID:???
>>348
$SIG{__WARN__} = sub { die @_ };
などとやってしまうとか。
0351nobodyさん2009/12/02(水) 12:21:29ID:???
Perl勉強中の者です。
XPでActivePerl5.8.9を使っています。

http://perl-users.jp/articles/advent-calendar/2008/08.html
上のURLを見て、クリップボードのURL→fenrir(ランチャ)で出来たらと思い、やってみました。
#!/usr/bin/perl
use strict;
use warnings;
use LWP::Simple;
use File::Basename;
use Win32::Clipboard;

my $dir = "$ENV{'USERPROFILE'}/jpgDL";
chdir $dir;

my $clip = Win32::Clipboard();
my $url = $clip->Get();
my @contents = get($url) =~ m{<a.*?href="(http://[^"]+\.jpg)"}gi;

foreach my $jpg(@contents) {
mirror($url, basename($jpg));
}
上記URLのワンライナー通りだとうまくいくのですが、このコードではjpgは落ちてくるけど、
ファイルが壊れているようです(ファイルサイズが全て同じになっている)。
FTPみたいにバイナリ指定する方法もないようで、どうしてよいか分かりません。
このコードの何処が間違っているのでしょうか?
ご指摘お願いします。
0352nobodyさん2009/12/02(水) 12:32:46ID:???
> クリップボードのURL
> my @contents = get($url) =~ m{<a.*?href="(http://[^"]+\.jpg)"}gi;
これは……
0353nobodyさん2009/12/02(水) 13:53:24ID:???
>>352
Windowsのブラウザ上でコピーしたURL(my $url = $clip->Get(); )に対して
LWPのgeでコンテンツを取得しています。

・・・と書き込みながらあれこれやって1時間、自己解決致しました。

誤) mirror($url, basename($jpg));
正) mirror($jpg, basename($jpg));

jpgじゃなくてURLのhtmlを落としてました・・・orz
0354nobodyさん2009/12/03(木) 01:29:27ID:???
perlを使い、DBに接続してselectする処理を作ろうとしております。
htmlを使い、cgiを読み込むような↓の簡単な処理をまず作りました。
※db.cgiは単体で動作確認済みで、こちらに不備があることはありません。

<html>
<body>
<form action="db.cgi" method="post">
<input type="submit" name="exec" value="データベースの表示">
</form>
</body>
</html>

ところがこれで呼び出すとcgi(上のソース上で言うdb.cgi)がうまく動作しません。
具体的に言うと、ファイルのダウンロード画面が開かれ、開くとcgiのソースが開かれてしまいます。
エラーメッセージは表示されません。

ネットでダウンロードすると出るダウンロード画面はお馴染みの物です。
このファイルを開くか、または保存しますか?
名前:db.cgi
種類:不明なファイル
発信元:

これはアパッチの環境設定面でヘマをしてしまったのでしょうか?情報少なくてすみません。
0355nobodyさん2009/12/03(木) 02:11:50ID:???
OS、CPU、メモリ、年齢、スリーサイズ、Apacheのインストール場所、Perlのインストール場所、httpd.confの内容
全て書け
0356nobodyさん2009/12/03(木) 09:01:03ID:???
>>354
Content-Type の不備と見た
0357nobodyさん2009/12/03(木) 09:13:01ID:???
cgiのソースが出てくると言うんだからapacheの設定だな。
cgiだと思われてないよ。
0358nobodyさん2009/12/03(木) 11:50:21ID:???
AddHandler cgi-script .cgi の設定が欠けてるとか。
03593542009/12/03(木) 23:52:45ID:aPQfU5cA
>>355>>356>>357>>358
ありがとうございました。
やはりApacheの設定だったようです。

詳細の原因はわかりませんでしたが、
confファイルの色々直したら表示できるようになりました。
ありがとうございました。
0360nobodyさん2009/12/05(土) 16:36:46ID:???
----------input.txt-
1 2 3
4 5 6
7 8 9
-------------------
---------------output.txt-
6
15
24
---------------
input.txt->output.txt(行ごとに三つずつある数字の和を一行ずつ表示させるプログラム)の書き方を教えてください
0361nobodyさん2009/12/05(土) 16:51:05ID:???
>>360
こんな感じかな。違ったら誰か突っ込んでくれると思う。わからないところどこ?
use strict;
use warnings;

my $input_file = shift || 'input.txt'; # 引数もしくはinput.txt
my $output_file = shift || 'output.txt'; # 引数もしくはoutput.txt

# 読み込み処理
open my $rfh, '<', $input_file  or die "$!"; # ファイルの読み込み
my @results;
while (defined(my $line = <$rfh>)) { # 1行ずつ処理
  chomp $line;           # 改行は削除
  my @nums = split /\s+/, $line;  # 空白で分割

  my $sum;
  for my $num (@nums) {
    $sum += $num;
  }
  push @results, $sum;
}
close $rfh;

# 書き込み処理
open my $wfh, '>', $output_file  or die "$!";
for my $result (@results) {
  print {$wfh} "$result\n";
}
close $wfh;
0362nobodyさん2009/12/05(土) 17:16:59ID:???
perl -lpe'y/ /+/;$_=eval' input.txt>output.txt

perl -alpe'$_=$F[0]+$F[1]+$F[2]' input.txt>output.txt

perl -MList::Util=sum -alpe'$_=sum@F' input.txt>output.txt
0363nobodyさん2009/12/06(日) 04:07:59ID:gPKy+f2T
>>362
4つ目が合ったら・・・

>>360
use strict;
use warnings;

open(INFH, '<', 'in.txt');
open(OUTFH, '>', 'out.txt');
while(my $line = <INFH>){
  chomp $line; # 改行削除
  my $sum = 0; # ゼロで初期化
  map { $sum += $_ } split(/\s+/, $line); # 空白で分割し、要素を足し算
  print OUTFH "$sum\n"; # 出力
}
close(OUTFH);
close(INFH);

0364nobodyさん2009/12/06(日) 07:36:02ID:???
>>361
いつも思うのですがこのwhile文の中のdefinedって必要なんですかね?
空文字が来るこってあるのでしょうか?
0365nobodyさん2009/12/06(日) 08:26:49ID:???
>>364
特殊変数によっちゃあえりるとかじゃなかったっけか。
0366nobodyさん2009/12/06(日) 11:00:15ID:???
>>364
0が来たらどうすんだって話じゃないか?
この場面に限らず0の評価を回避するためにdefined書かなきゃいけないことが多すぎる
■ このスレッドは過去ログ倉庫に格納されています