トップページ⇒tech
993コメント368KB

Perlについての質問箱 33箱目

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん2007/10/16(火) 00:59:57
"The duct tape of the Internet" こと、Perlについての質問箱です。
"There's more than one way to do it" ということで、Perlの奥深さについて皆で語り合い、追求してまいりましょう。

CGIについての質問は板違いです。WEBプログラミング板でどうぞ。
CGIとPerlの区別がつかない人もWEBプログラミング板に行ってください。
(WEBプログラミング板 http://pc11.2ch.net/php/ )

CGIの質問は答えがPerlと全然関係ない話に帰着する場合が多かったりするのでWEBプログラミング板に行って聞いたほうが得ですよ。
このスレでは(CGI以外の)純粋にPerlのみに関係する質問を取り扱っていこうと思います。
スレ違いの質問にはスルーか、速やかな誘導をお願いします。

http://www.perl.org/get.html
● 2007/10/12現在の最新版: 5.8.8
● 2007/10/12現在の開発版: 5.9.5

前スレ
Perlについての質問箱 32箱目
http://pc11.2ch.net/test/read.cgi/tech/1186995713/

リンク集は>>2-3
過去スレは>>4 あたり
0232デフォルトの名無しさん2007/11/02(金) 10:40:37
>>231 が変なコードを量産しませんように
0233デフォルトの名無しさん2007/11/02(金) 12:20:18
KENTのコードは間違ってはいないのだが、
Perlっぽくない気がする。
C臭さがプンプンしていて、どうも違和感が。
0234デフォルトの名無しさん2007/11/02(金) 22:12:17
だったら自分で「Perlっぽいコード」を書いて公開すればイイジャン!
文句言うだけなら子供でも言える。
0235デフォルトの名無しさん2007/11/02(金) 22:14:55
>>233-234
KENTの自作自演か?
言ってることがでたらめすぎるぞ。
0236デフォルトの名無しさん2007/11/02(金) 22:28:12
で?キミはいったい、どんな「Perlらしいコード」を書けると言いたいんだい?
おや、見せられないのかい?恥ずかしくて他人には見せられないの?
へぇ。そう。
だったら他人のコードを批判する資格はまったく無いね。
0237デフォルトの名無しさん2007/11/02(金) 22:49:56
Perl4時代ならいざ知らず現在kentが垂れ流してるコードがうんこなのは周知の事実
Perlらしいとかそんな次元の話じゃないだろ
0238デフォルトの名無しさん2007/11/02(金) 23:03:28
で?
早く「Perlらしいコード」とやらを見せてくれよ。
0239デフォルトの名無しさん2007/11/02(金) 23:07:38

       /ニYニヽ
   (ヽ   /( ゚ )( ゚ )ヽ   /)
  (((i ) /::::⌒`´⌒::::\  ( i)))  でっていうwwwwwwwww
 /∠_| ,-)___(-, |_ゝ \
( ___、  |-┬-|    ,__ )
    |    `ー'´   /´
    |         /
0240デフォルトの名無しさん2007/11/02(金) 23:15:27
自分じゃ鋭い追求してるつもりなんだろうが、
哀れなほど孤軍奮闘だなw
0241デフォルトの名無しさん2007/11/02(金) 23:36:41
久しぶりにKENTのコード見てみたら
&jcode'convert(*line, 'sjis') でなく &jcode::convert(\$line, 'sjis') な記述になってるし
flock(FH, 2) してるし、もうびっくりですよ。
0242デフォルトの名無しさん2007/11/02(金) 23:46:09
perlらしいコードってあれだろ?
カートゥーンのキャラクターがぼやいてるようなやつ
0243デフォルトの名無しさん2007/11/03(土) 00:14:12
マウスの付いたパソコンしか触ったことの無いヤツが必死でほざいてるよ〜
0244デフォルトの名無しさん2007/11/03(土) 00:24:24
KENTってハゲオヤジだよ
0245デフォルトの名無しさん2007/11/03(土) 00:51:44
>>244
へ〜〜〜知らなかった〜〜〜!
そうなの、初めて知ったよ。
よく知ってるね、キミって情報ツウ?。すごいよ物知り博士だよ。
ネ申!ホトケ!天神まさ!ダイバダッタ!尊氏さまだよ!
0246デフォルトの名無しさん2007/11/03(土) 01:09:40
なんか浮いてる奴がいるな
0247デフォルトの名無しさん2007/11/03(土) 01:22:25
>>244の名字は足利w
0248デフォルトの名無しさん2007/11/03(土) 01:27:35
KENT=ハゲオヤジのソースは日経ソフトウェア
誰かと対談してて顔写真が載ってた
0249デフォルトの名無しさん2007/11/03(土) 01:43:01
>>248
へ〜〜〜すご〜い!
何でも知ってるんだね、物知りだね。
日系ソフトウエア読んでるだけでも自慢できるよ。
こんなクソスレにネ申が現れようとは!
0250デフォルトの名無しさん2007/11/03(土) 03:12:45
何事かと思ったらまたお前か
0251デフォルトの名無しさん2007/11/03(土) 08:22:35
天神まさ
0252デフォルトの名無しさん2007/11/03(土) 12:19:16
社労士だから、本業ついでに営業できていいよね。
あたまいいねー。
0253デフォルトの名無しさん2007/11/03(土) 16:08:09
>>228

なるほど、とてもシンプルで分かりやすい方法ですね。
ぜひ試してみようと思います、ありがとうございます。

>>229

ソースまで書いていただいてありがとうございます。
とても参考になりました。
一つ質問なのですが

$co->look_down(_tag => "div");

この部分はtrタグの中の一つ目のdiv(225 BUY)しか抽出できないんですよね?

for my $attr ( $co->look_down("div") ){
@data = $attr->as_text."\n";
}

という感じで全てのデータ(225 BUY,225 SELL〜)を抽出しようと思ったのですが、
エラーになってしまいました。
良い方法があれば教えていただけると幸いです。
0254デフォルトの名無しさん2007/11/03(土) 16:11:15
C言語で言う #ifdef WINDOWS のようなものはあるでしょうか?

WindowsとLinuxで共通に動くプログラムを作ろうと思っています。
fork()周りがOS依存になってしまうので、Windows/Linuxで処理を分けたいです。
0255 ◆TWARamEjuA NGNG?2BP(6825)
$^Oみたいな?
0256perl 修行中2007/11/03(土) 20:14:38
2007-10-16 21:55:38 という日付のフォーマットを
Sat, 03 Nov 2007 18:40:13 +0900 というフォーマットに変換したいと
思っているのですが見つかりません。
便利なパッケージとかないのでしょうか
0257デフォルトの名無しさん2007/11/03(土) 20:20:06
標準パッケージ
0258デフォルトの名無しさんNGNG?2BP(7951)
use DateTime::Format::HTTP;
my $dt = DateTime::Format::HTTP->parse_datetime("2007-10-16 21:55:38");
print DateTime::Format::HTTP->format_datetime($dt);
02592542007/11/03(土) 20:40:42
>>255
まさにこれです!
Linuxで実行:linux
WinXPで実行:MSWin32
となりました。ありがとうございました!
0260デフォルトの名無しさん2007/11/04(日) 02:16:21
\(^O^)/
0261デフォルトの名無しさん2007/11/05(月) 00:24:36
>>253
リストコンテキストなら同一ノード内の全div要素、スカラーコンテキストなら最初の要素のみ。
要素が見つからないなら、as_textメソッドを呼び出したときにエラーが出るだろうな。
0262デフォルトの名無しさん2007/11/05(月) 16:59:02
>>256
俺は日付の変換には Time::Piece を愛用している。
http://perldoc.jp/docs/modules/Time-Piece-1.08/Piece.pod

フォーマットを変えたいなら
Time::Piece->strptime(STRING, FORMAT)
でTime::Pieceのインスタンスを作って、

$t->strftime(FORMAT)
でフォーマットを指定して出力すればいい。

でもこのモジュール、2038年問題だったっけ?
未来の日付を拒絶するんで、使う場面には注意が必要。
0263デフォルトの名無しさん2007/11/05(月) 18:11:04
for文を回して連続した数字を表示するときに、
桁の数をそろえる方法ってありませんか?

具体的に言うと
0 1 2 … 10 … 100
ではなく、
000 001 002 … 010 … 100
のようにしたいのですが。
0264デフォルトの名無しさん2007/11/05(月) 18:15:15
>>263
sprintf
0265デフォルトの名無しさん2007/11/05(月) 18:16:46
HTTP::Dateでいいじゃん
0266デフォルトの名無しさん2007/11/05(月) 19:41:42
>>263
'001' .. '100'
とかできたような気がする。
0267デフォルトの名無しさん2007/11/05(月) 20:30:42
>>263
foreach (0 .. 100) {
printf qq(%0.3d\n), $_; # 数字を他の文字列等とコンカチしたいときはsprintfで
}
0268デフォルトの名無しさん2007/11/05(月) 21:19:20
すでに回答が出て解決してるのに、なんでダラダラ引っ張るんだ?
やっぱ Perl 使いはアホばっかだな。
0269デフォルトの名無しさん2007/11/05(月) 21:29:16
またお前・・・じゃないみたいだな
0270デフォルトの名無しさん2007/11/05(月) 22:26:51
sort {
$a->[3] cmp $b->[3]
or
$a->[5] <=> $b->[5]
or
$a->[8] cmp $b->[8]
} @array
こんな文があったとします。
これをユーザの入力によって
$a->[8] cmp $b->[8]を一番先に持ってきたり(
sort {
$a->[8] cmp $b->[8]
or
$a->[3] cmp $b->[3]
or
$a->[5] <=> $b->[5]
} @array
)、$a->[5] <=> $b->[5]を一番先に持ってきたりしたいのですが
どのようにすればいいでしょうか?
0271デフォルトの名無しさん2007/11/05(月) 22:28:22
すみません。PerlのVerは5.00503で、
モジュールは使えません。
0272デフォルトの名無しさん2007/11/05(月) 22:55:38
>>270
sort block はその名の通りblockなんだから、条件式埋め込めばいいだけじゃん?

手抜きの例を書くと
my $i = 1 ; # $i を他の数字にしてみる。
my @arr = sort {
if ( $i == 1 ){ $a->[0] <=> $b->[0] or $a->[1] <=> $b->[1] }
else { $a->[1] <=> $b->[1] or $a->[0] <=> $b->[0] }
} ( [1,2],[2,3],[2,1] ) ;
0273デフォルトの名無しさん2007/11/05(月) 22:58:53
>>270
各々の順序関数を @funcs に格納して、
評価する順序を変えたいときは @funcs を並び替えればいいんじゃね?

@funcs = (
  sub { $a = shift ; $b = shift ; $a->[3] cmp $b->[3] },
  sub { $a = shift ; $b = shift ; $a->[5] <=> $b->[5] },
  sub { $a = shift ; $b = shift ; $a->[8] cmp $b->[8] }
) ;

@array =
sort {

&{ $funcs[0] }($a, $b)
or
&{ $funcs[1] }($a, $b)
or
&{ $funcs[2] }($a, $b)

} @array ;
0274 ◆TWARamEjuA 2007/11/05(月) 23:16:51
おいらの頭では、比較演算子がorで繋がっている趣旨がわかんない(´・ω・`)
入力によってsortを選択(択一)にするのなら判るけれども。。。
0275デフォルトの名無しさん2007/11/06(火) 00:14:53
>>274
a or b は aが偽のときにbを返す。
即ち、一個目のcmpが0を返したときに、次の評価が行われるようになる。
0276デフォルトの名無しさん2007/11/06(火) 00:32:11
#!/usr/bin/perl -w
use strict;
my @order = @ARGV;
my @data; chomp, push @data, [ split /\|/ ] while <DATA>;
my %cmp = (
  by_title => '$a->[0] cmp $b->[0]',
  by_author => '$a->[1] cmp $b->[1]',
  by_year_asc => '$a->[2] <=> $b->[2]',
  by_year_desc => '$b->[2] <=> $a->[2]',
  by_price_asc => '$a->[3] <=> $b->[3]',
  by_price_desc => '$b->[3] <=> $a->[3]',
);
my $code = join ' or ', @cmp{@order};
local $" = '|';
print map "@$_\n", eval "sort { $code } \@data";
__DATA__
Regular Expression Pocket Reference, Second Edition|Tony Stubblebine|2007|14.99
Mastering Perl|brian d foy|2007|39.99
SQL Injection Defenses|Martin Nystrom|2007|9.99
Mastering Regular Expressions, Third Edition|Jeffrey E. F. Friedl|2006|44.99
Building Tag Clouds in Perl and PHP|Jim Bumgardner|2006|9.99
Perl Hacks|chromatic, Damian Conway, Curtis Poe|2006|29.99
Intermediate Perl|Randal L. Schwartz, brian d foy, Tom Phoenix|2006|39.99
Wicked Cool Perl Scripts|Steve Oualline|2006|29.95
Perl Testing: A Developer's Notebook|Ian Langworth, chromatic|2005|29.95
Learning Perl, Fourth Edition|Randal L. Schwartz, brian d foy, Tom Phoenix|2005|39.95
0277デフォルトの名無しさん2007/11/06(火) 02:15:10
>>263です
>>264-268 ありがとうございます
sprintf を使うことにします
0278デフォルトの名無しさん2007/11/06(火) 07:16:04
なぜか>>263に礼言われてる>>265宛て。

お題は>>256のとおり JST(+0900) で吐きたい、みたいなのよね。
HTTP::Date::time2str() は GMT でしか吐いてくれなかった気がする。

最近は Date::Format 使ってる。
過去に書いたコードを発掘したら use POSIX qw(strftime); と書いてるのもあると思う。
0279perler2007/11/06(火) 12:15:22
DBIについての質問です。
perl + MySQLを使用しています。
MySQLにinsertする際にこれまではMyISAMを使用していましたが、
都合によりInnoDBを使用することになりました。

そうした場合、MyISAMでinsertできていたソースがInnoDBに変更したら使用できなくなってしまいました。
何か違いがあるのでしょうか。
以下ソース。

my $sth = $dbh->prepare("INSERT user SET USER_NAME='ドコモ', MAIL='docomo', PASS='1234567';");

$sth->execute();
0280デフォルトの名無しさん2007/11/06(火) 12:21:41
>>279
Perlの問題というよりも、MySQLの設定がマズイような気がしますが。
Perl-DBI以外のクライアントでMySQLに接続して、INSERTできてます?

それとexecuteの後に、エラーが発生するんだと思いますが、
エラーメッセージには何と書かれているのでしょうか?
0281デフォルトの名無しさん2007/11/06(火) 13:37:31
プレースホルダくらい使って欲しいなぁ。
0282perler2007/11/06(火) 13:46:07
申し訳ありません。
自己解決しました。

コネクションを取得時にオートコミットをオフにしていて、
コミットをしていなかった為でした。
皆様ありがとうございました。
0283デフォルトの名無しさん2007/11/06(火) 14:50:35
>>281
キチガイ?
0284デフォルトの名無しさん2007/11/06(火) 18:16:15
上げて書き込む奴は大抵馬鹿だからすぐ分かるな
02859412007/11/06(火) 22:55:41
perlでバイナリーファイル→画像ってできますか?
指定したURLからjpgをbinmodeでファイルに書き込むまでは出来たんですが
それを.jpgになおせません・・・何を言ってるか自分でもわかりませんが
いい方法は無いでしょうか?
0286デフォルトの名無しさん2007/11/06(火) 22:56:33
941は関係ないです・・ごめんなさい
0287デフォルトの名無しさん2007/11/06(火) 23:05:24
>>285
私にも意味が分かりません。
0288デフォルトの名無しさん2007/11/06(火) 23:09:14
意味が分からんけどどうやってjpgのデータを取ってきてどうやって書き込んだのさ
ただ単にネット経由で画像とってきて保存したいだけなら
my $ua = LWP::UserAgent->new;
$ua->mirror($url, $filename)
だけでもできるよ
0289デフォルトの名無しさん2007/11/06(火) 23:22:32
ほんとに意味わからなくてごめんなさい
とりあえず自分で作ったソースの一部なんですがこんな感じで画像は
やはり取れないんでしょうか・・
print $client_socket "GET http://7art-screensavers.com/screenshots/animals/lion-and-the-lamb.jpg HTTP/1.0\r\n";
print $client_socket "Host: www.clinko.com\r\n";
print $client_socket "\r\n";

while (<$client_socket>){
print $_;
m/^\r\n$/ and last;
}


$file="sample.jpg";
while (<$client_socket>){
binmode(STDOUT);
$all=join("",<$client_socket>);
open(FILE, "> $file");
binmode(FILE);
syswrite(FILE,$all,length($all));
close(FILE);
}
0290デフォルトの名無しさん2007/11/06(火) 23:25:31
最終的にはイメージ検索のAPIでもってきたXMLからXML::Simpleモジュール
とかつかってjpg画像を指定した落としていきたいんです・・説明へたくそ
でごめんなさい
0291デフォルトの名無しさん2007/11/06(火) 23:28:09
>>289
バイナリデータをreadlineで読むなよ
0292デフォルトの名無しさん2007/11/06(火) 23:33:45
readlineってなんですか?無知でごめんなさい
0293デフォルトの名無しさん2007/11/06(火) 23:34:16
LWP::UserAgent使えよ
0294デフォルトの名無しさん2007/11/07(水) 01:05:19
デバッグくらいしろよ
0295デフォルトの名無しさん2007/11/07(水) 01:14:31
ActivePerlいれたら起動しなくなりました。
どうしたらいいんでしょうか
0296デフォルトの名無しさん2007/11/07(水) 01:17:40
何が?何が起動しないんだよ。人にものを話すときは、
主語述語きちんと言いなさい。学校で習わなかったかな?5W1Hって。
0297デフォルトの名無しさん2007/11/07(水) 01:23:34
ActivePerlをインストールしたら
OSが起動しなくなりました。
Windwosロゴまでは表示されますが
その後真っ暗です。
セーフモードでの起動は出来ます。
復元でActivePerlインストール前にもどれば起動は出来ましたが
ActivePerlを使いたいのです、
0298デフォルトの名無しさん2007/11/07(水) 01:24:48
use Encode;
use Encode::Guess qw/ gbk euc-jp shiftjis/;
opendir (DIR, '.');
@files = readdir DIR;
foreach $dir(@files)
{
print $dir;

open (IN, "<$dir");
open (OUT, ">$dir-2");
while (<IN>)
{
Encode::from_to($_, 'guess', 'Shiftjis');
print OUT;
}
close IN;
close OUT;
}
opendir (DIR, '.');
@files = readdir DIR;
foreach $_(@files)
{
$old = $_;
s/-2//;
rename ($old,$_);
}
初心者なもので無駄が多すぎてお恥ずかしいのですが。。。
フォルダ内にあるテキストファイルの文字コード(EUC・Shiftjis・BGなどバラバラ)を自動判別して全てshiftjisに変換したいのですが
shiftjis or euc-jp or cp936 at C:/Perl/lib/Encode.pm line 186 とエラーがでます。
'guess'の部分を''gbk'とかに指定すればちゃんと変換されるのですが、それだと他コードのファイルが文字化けします。
どうすればいいでしょうか・・・?
0299デフォルトの名無しさん2007/11/07(水) 03:37:57
>>292
http://perldoc.jp/docs/perl/5.8.4/perlfunc.pod#item_readline_EXPR

>>298
http://www.kt.rim.or.jp/~kbk/perl-5.8/guess.html
0300デフォルトの名無しさん2007/11/07(水) 04:08:16
>>297
インストールオプションで、Perl 本体と PPM ”だけ” インストールしてみてはどうだろう。
ISAPI とか PerlEX とか PerlScript とか、(必要が無ければ) チェックをははずしてみる。
うまくいくかどうかわわからんが、成功を祈る。
0301デフォルトの名無しさん2007/11/07(水) 12:17:51
>>297
OSって Windows の何?XP?Vista?
サービスパックのバージョンは?
0302デフォルトの名無しさん2007/11/07(水) 13:09:44
>>300
だめでした。
なんとか復元3回やってまた戻しました。

OSはXPのSp2です。
一応復元する前にPerlのファイルを別途保存してみたので
それを使って目的のことが出来ないかやって見ます。
0303デフォルトの名無しさん2007/11/07(水) 22:48:10
Solaris10のsyslog(ログローテートしている)で
そのsyslogの作成日が本日だった場合にはsyslogに任意の文字列を記述し、
本日でなかった場合には何もしない、という処理をさせたいのですが
どうしたらよいでしょうか?
0304デフォルトの名無しさん2007/11/07(水) 23:40:27
>>302
基本的にさ、perl のファイルさえあればOKなんよ。
あとは環境変数 PATH に perl のディレクトリを加えたり、
拡張子 .pl を perl.exe に関連付けしてるだけだから、
もし Active Perl のインストーラでうまくいかないんだったら
これらを手動でやっちゃえばOK・・・なハズ。
PATH とか 拡張子の関連付けとか、具体的なやりかたが分からなかったら
また質問してね。
0305デフォルトの名無しさん2007/11/07(水) 23:44:24
>>303
ファイルの日付は stat 関数、
ファイル名変更は rename 関数を使う。
それぞれの使い方は google で調べてね。
0306デフォルトの名無しさん2007/11/08(木) 04:27:04
456,657,787,455,…

のように数字が横に並んだファイルがあるのですが
456−657,657-787,787-455,…というような前後の差分を
とったファイルを出力するにはどうしたらいいでしょうか?

ファイルを読み込んで、そのデータをfor文で差分をとっていけばいいと思うのですが
例えば456や657をどのように指定するかがわかりません。
指定する方法がわかればそれをひとつずつずらしていけばいいと思うのですが・・・
お手数ですが、どなたかヒントをお願いいたします。
0307デフォルトの名無しさん2007/11/08(木) 06:06:03
@nums = (456,657,787,455);

for $i (0..$#nums-1) {
print $nums[$i] - $nums[++$i];
}
03083062007/11/08(木) 06:22:40
>>307さんわかりやすいプログラムをありがとうございます。

まずリスト変数にその数字をいれて指定できるようにして
そしてそのリスト値を最後のから一つ前まで代入して差分できるようにするということですね。
回答していただき感謝しております。

それと今回はその要素(456、657など)が一万個くらいあるのですが
その場合は直接リスト変数の要素として入れるわけには行きませんよね?

よろしければその場合もお教え願えませんか?
その一万個の数字のファイルを読み込んだあとにどのようにして
一万個の数字を指定して差分を求めればいいかがわからないのです・・・
0309デフォルトの名無しさん2007/11/08(木) 06:31:46
>>307も「そこから」だとは思ってなかったと思う。

my $data = '456,657,787,455';
my @nums = split(/,/, $data);
0310デフォルトの名無しさん2007/11/08(木) 06:32:39
ファイルからリストに読み込む方法が分からないってこと?
なんかメモリ上に1万個の要素を入れるのがマズいとも読み取れるけど・・・。

open my $in, "UNKO";
my @nums = split(/,/, do { local $/ ; <$in> });
close $in;

とでもすれば。
0311デフォルトの名無しさん2007/11/08(木) 06:34:43
do {local $/=","; <$in>}
これでいいか。
03123062007/11/08(木) 06:46:29
>>309
丁寧にありがとうございます。

>>310
その通りです。一万個の数値を直接プログラムに入力するのはまずいかなと思いまして。
日本語に至らないところがあり申し訳ありませんでした。

ありがとうございます!
,に対応してそれぞれの値が区切られてリスト変数の要素としてとして
認識されていくというわけですね。
丁寧な指導ありがとうございます。おかげでリストに読み込む方法がわかりました。
03132982007/11/09(金) 00:44:58
>>299
リンク先読んで試行錯誤しましたが、できませんでした・・・
どなたか直接手直ししていただけませんか
0314デフォルトの名無しさん2007/11/09(金) 00:49:28
>>313
条件とか謝礼とか書かないと。
0315デフォルトの名無しさん2007/11/09(金) 01:19:03
もしかしたら文字コードの自動認識って
「失敗」することがあるもんだって、
知らないで使っているのでは。
03163062007/11/09(金) 03:58:26
質問ばかりで申し訳ないんですが

11,22,33,44,55,66 というリストを

11,33,55
22,44,66

というように二つのリストに分けるという作業はどうしたらいいのでしょうか・・・
substrとfor文で一つ置きに抽出しようとも思ったんですが++ではなく一個置きに
するというプログラムがわからなくて・・・
そもそもここでsubstrを使おうとすること自体間違っている可能性が高そうですが。
0317デフォルトの名無しさん2007/11/09(金) 04:31:20
substrじゃなくてsplitすれば?
1個置きはループカウンタが奇数か偶数で分岐すればおk
0318デフォルトの名無しさん2007/11/09(金) 04:37:04
http://www.aoky.net/articles/steve_yegge/tour_de_babel.htm
Perlもまた、間もなくなくなる。
0319デフォルトの名無しさん2007/11/09(金) 05:28:50
(・∀・)ニヤニヤ
03203062007/11/09(金) 06:31:59
なるほど、また一つわかりました。ありがとうございます。
つまり

@data = (11,22,33,44,55,66);
for($i=0;$i<=$#data;$i++ ){
if ($i % 2 == 0){
push @kisuu,"$i";
}
elsif ($i % 2 == 1){
push @guusuu,"$i";
}
}
print @kisuu;
print @guusuu;
のようにすれば奇数グループと偶数グループを分けることができるというわけですね。
03213062007/11/09(金) 06:32:38
すいません、>>317さんへです。
0322デフォルトの名無しさん2007/11/09(金) 06:43:34
>>316
リストの先頭から1個ずつ取り出して出力先のリストにかわりばんこに
プッシュすれば良い。
03233062007/11/09(金) 08:08:19
>>322
ありがとうございます。おかげさまでデータを分けることができました!
あと
2,3,2,3,2,3,2,3,…と並んでいるdata.txtがありその差分を
出したいために以下のプログラムを作ったんですが
本来なら結果が
-1,1,-1,1,-1,1,-1,…という風に1番目から2番目を引いた結果、2番目から3番目を引いた結果を
出力するつもりだったのが
1,1,1,1,1,1,1,…という風に1番目から2番目を引いた結果、3番目から4番目を引いた結果と出力されてしまいます。
どこがおかしいのでしょうか?
open IN, "data.txt";
open OUT, ">sabun.txt";
while (<IN>) {
@all = split(/\,/,$_);

for($i=0;$i<=$#all-1;$i++ ){
$kekka = $all[$i] - $all[++$i];

print OUT $kekka,"\n";
}
}
close IN;

close OUT;

03243062007/11/09(金) 08:24:44
すいません、自己解決しました!
for($i=0;$i<=$#all-1;$i++ ) を
for $i (0..$#all-1) にしたらうまくできました。

しかしこの二つの文は僕には同じようにしか見えないんですがどこが違うんでしょうか。。。
0325デフォルトの名無しさん2007/11/09(金) 08:30:34
同じです
03263062007/11/09(金) 08:49:01
>>325
でもなぜか
for($i=0;$i<=$#all-1;$i++ ) だと
(2-3),(2-3),(2-3),(2-3),…となって一個飛ばしの差分にしまったんです。

for $i (0..$#all-1) だとちゃんと
(2-3),(3-2),(2-3),(3-2),(2-3),…となりできるんですが。
0327デフォルトの名無しさん2007/11/09(金) 08:54:08
>>326
だって、まず
$kekka = $all[$i] - $all[++$i];
のケツの部分で一回インクリメントされて、そのあと
for($i=0;$i<=$#all-1;$i++){
のケツの部分でもう一回インクリメントされてるわけだから。
0328デフォルトの名無しさん2007/11/09(金) 09:38:55
>>324
数をカウントアップしてるのと、数列を順に入れてる という違いだが
基本的に同じ。 ってかカウンター変数触んなよ。バグの元凶だ。
03293062007/11/09(金) 10:17:35
>>327 二重にカウントされてるようなものってことですね。ありがとうございます。
>>328 for文の後ろの方いじるとまずいんですね、知りませんでした。
if文などでなんとかしたほうがいいということですか?

皆さんあと一つだけ知恵をお貸しください… suuji.txt というファイルがありまして中身が
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,  ←ここで改行してある
21,22,23,24,25,26,27,28,29,30

というものなんですが、これを偶数と奇数に分けたくて、まず偶数を出力するために以下のプログラムを
作ったんですが、出力結果が
0,2,4,6,8,10,12,14,16,18,20,0,2,4,6,8,10,12,14,16,18,20,21,23,25,27,29,
となってしまい
「1行目が2重に含まれている」
「2行目からずれてしまっている」という二つのわからない点が出てしまいました。
何度もしつこいですが、どうか考え方をお教えください・・・
open IN, "suuji.txt";
open OUT, ">guusuu.txt";
while (<IN>) {
@all = split(/\,/,$_);
for $i (0..$#all){
if ($i % 2 == 0){
push @guusuu,"@all[$i]",",";
}
elsif ($i % 2 == 1){
push @kisuu,"@all[$i]",",";
}
}
print OUT @guusuu;
}
close IN;
close OUT;
0330デフォルトの名無しさん2007/11/09(金) 10:39:03
>>329
> 二重にカウントされてるようなものってことですね。
ようなもの、じゃなくて、二重にカウントされてるんだよ。
言葉尻を捉えた突っ込みに思うかもしれないけど、ここで曖昧さを排除することは凄く重要だよ。
君の目と意識が、ハッキリ「二重にカウントしてる」のを捉えるまで、わかった気になっちゃダメ。

> for文の後ろの方いじるとまずいんですね
よくわからないうちに相手の意見を「自分流に言い換える」のも危険だよ。
カウンター変数ってのはこの場合$iのことで、この$iの中身を「ループ内部で」書き換えるのは混乱の元だ、という話。
ループの内部でこの値を変更するというのは、「ループ内部から見ると、$iは毎回1ずつ増えて降ってくる
絶対的なものに感じられる」というある種の信頼を崩すということで、これは本当に混乱する。
事実、君はその信頼に囚われて、たった2行なのに原因を見つけられなかったでしょ?
だから、君の解釈であるところの「for文の後ろの方いじるとまずい」は正反対だ。for文の後ろでしかいじっちゃいけない。
これも、「よくわかんないけど、とにかくカウンター変数はfor分の最後でいじれということですね」とか
曖昧な解釈で終わっちゃダメだからね。何故そうすべきなのか、納得するまで考え込むように。
0331デフォルトの名無しさん2007/11/09(金) 11:04:37
> 出力結果が
> 0,2,4,6,8,10,12,14,16,18,20,0,2,4,6,8,10,12,14,16,18,20,21,23,25,27,29,
> となってしまい
いや、なってないから(*1)。

突っ込むところは複数あるんで、書くのが面倒だな・・・。とりあえず、
(1) suuji.txtの1行目の終わりに","が付いていて、且つ、末尾の改行を除去していないので、
  @allに最初に入るのは、1から20までと「空白+改行」の、全21要素である。
(2) だから2行目に入ると、奇数偶数が入れ替わる。
  *1 というか、$add[n]の中身がn + 1なので(ややこしい)、君の言うようには出力されない。
(3) push関数は「@allの後ろにどんどん要素を追加していく」だけでクリアなんかしないわけだから、
  1行目の処理の時に詰め込んだものが2行目の処理の時に残っているのは当然。
  前のカウンター変数の時もそうだけど、君自身は毎回のループ処理を独立させて捉えているのに、
  君の書くコードは「次のループに影響する何か」をいちいち残していってる。それが混乱を生んでる。
(4) @all[$i]という書き方は「配列スライス」といって、この場合たまたまスカラーを取り出してるような
  結果になってるだけ。$all[$i]と書くべき。「スライス」をキーワードにして調べるように。
あたりは絶対に直さないとダメ。他にも「よりよい方法に変えるべき」点はあるけど、書ききれない。
■ このスレッドは過去ログ倉庫に格納されています