ハッシュのeach関数を使って「猫はcat犬はdogお茶tea」と表示させるプログラムの主要部分です。

%list = ("猫"=>"cat" , "犬"=>"dog" , "お茶"=>"tea");
while( ($key,$val) = each( %list ) ){
  print "$keyは$val";
}

whileの条件部分の意味が分かりません。
・なんで条件部分なのに代入みたいな式が入るのか?
・$keyと$valというのは普通のスカラー変数とは違うのか?
良く分からないので質問の仕方もおぼつかないですが、どなたか分かりやすく説明して頂けないでしょうか?

このQ&Aに関連する最新のQ&A

A 回答 (2件)

 はいはい、補足です(笑)



>each(%list) が返すのは (猫,cat) という
 その通りです。
 「猫」と「cat」がそれぞれ配列変数の値として入ります。

>print each(%list); と書く
 print 文における配列の扱いは例外で、「中身をセパレータなしで並べて表示する」という動きをします。(セパレータを入れたい場合はシステム変数に設定)
 ですのでこの場合、print 文は、each(%list) が返した('猫','cat')という配列の中身を、セパレータなしでつなげて「猫cat」と表示したわけです。

>この中にある、$list{$key} という部分ですが
 はい、その通りです。
 まず関数 keys は、ハッシュ配列変数のキー名すべてを配列にして返す関数です。
 foreach は、その「返された配列」を1つ1つ $key に入れてループしてくれます。
 すると、最初のループでは $key には '猫' が入ることになるわけですから、$list{$key} は $list{'猫'} と同じ意味になります。
 もちろん、次のループでは $key には '犬' が入るわけです。
 ですので、このプログラムと最初の質問のプログラムは同じ事をすることになります。
    • good
    • 0
この回答へのお礼

丁寧にお答えくださって有り難うございます。
う~ん、しかし分かったような分からないような・・
一度にたくさんのことを詰め込もうとし過ぎているのか、まだ混乱しています。
これから何度も読み直してみます。

お礼日時:2001/09/07 14:49

 C言語もそうなんですが、Perl の条件式の特徴は、「比較と代入を同時に行える」という点です。

そのために、比較演算子(==)と代入演算子(=)が別になってるんです。

 このとき、比較式を記述しなければならない場所(今回の場合は while の中)に代入式だけを記述すると、Perl は自動的に、「代入された値が真か偽か」によって判定を行います。

 真とは、0以外の数値や、undefine、または null ではない文字など、何かを処理するのに適した値です。
 逆に偽とは、0、undefine、null です。

 each は、ファイルの読み込みと同じようにハッシュ変数の中身を、呼び出すごとに順番に「配列として」返す変数で、すべての配列を呼び出し終わると null を返します。
 ですので、正常なデータが返されているうちは、while はそれを「真」であると解釈し処理を繰り返しますが、each が null を返すと、すべての処理が終わったのだと解釈し、ループを抜けるわけです。

 それから、($key, $val) という記述ですが、こんな記述ができるのは、俺が知る中では Perl だけです。(マイナーな言語には他にもこれができるものがあるようですが)
 Perl の関数が「配列」という巨大なデータを返すとき、それを受け取るための手法の1つがこの書き方です。
 通常は配列を返す関数に関しては、受け取り側も配列を記述するのが普通です。

  @kv = each( %list );

 この書き方をすれば、$kv[0]、$kv[1] にそれぞれ値が入りますが、これでは少し面倒です。
 そこで、Perl では、($key, $value) という括弧そのものを、「1つの仮的な配列」として扱うことができるのです。
 ですのでこの処理が終わってしまえば、$key も $value もそれぞれスカラー変数として扱えます。

 これを利用すれば、

  ($a, $b) = ($b, $a);

 という記述も出来ます。これは、$a と $b の中身を入れ替えるという処理です。

 説明が長くなってしまったので、不明点は別途補足ください(^_^;

この回答への補足

補足というか追加質問になってしまうのですが、次のような例文がありました。

foreach $key(keys(%list)){
  $val = $list{$key};
  print "$keyは$val";
}

この中にある、$list{$key} という部分ですが、これはハッシュの要素へのアクセスを示す $ハッシュ名{'キー名'} でしょうか?

補足日時:2001/09/07 13:33
    • good
    • 0
この回答へのお礼

ありがとうございます!条件が真か偽で判断することを忘れていたのと、リスト書式で代入が出来るということを知らなかったのが原因でした。
しかしそうすると each(%list) が返すのは (猫,cat) という書式のものと考えて正解ですか?しかし、 print each(%list); と書くと表示されるのは「猫cat」というようにキーと値がそのまま横に並んだものです。
なんかイマイチ納得できないです・・

お礼日時:2001/09/07 13:04

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qメールの署名設定

メールの署名設定がリッチテキスト形式のなっていて、テキスト形式に代えると青字のアドレスが黒字になってしまします。
返信の場合は変えても大丈夫なのですが、どうすればテキスト形式に変更できますか?

Aベストアンサー

オプションでテキスト形式で作成するようにしていますよね?
それでもリッチテキストになってしまうのですか?
返信するときに元のメールと同じ形式にする、とかしてます?

それ以外に設定はありません。
これでもおかしいなら、IEを再インストールしてみましょう。

Qif($key){ ($key eq 'aaa') || ~~を複数縦に記述したい

sub AAA {my($key)=@_;
if($key){
($key eq "aaa") || ($key eq "bbb") || ($key eq "ccc") || ($key eq "ddd") || &Error("$keyが不正です。");
}
}

のような形があるとして、$key eq "" の数が50個近くあるような場合、横に表示するのではなく縦に
($key eq "aaa") ||
($key eq "bbb") ||
($key eq "ccc") ||
($key eq "ddd") ||
と、見栄えよく表示させたいのですが
どのように記述すればよいのでしょうか。

また代替案などありましたらあわせてご教授頂けますと幸いです。

Aベストアンサー

正規表現で

$key =~ /^(
aaa|
bbb|
ccc|
ddd)$/x || &Error("$keyが不正です。");

QOutlook 2003 メール返信時の署名のずれについて

よろしくお願いします。
現在の設定
【OS】 Windows XP
【メール】 OutLook 2003
【形式】  HTML
【フォント】MS P明朝 新規・返信すべて
【署名】 返信時、新規作成時に設定

メールを返信する際に、署名を設定しているのですが、
相手のフォントが自分のフォントと違っている
場合、署名がずれておかしな形になります。
どんなフォントでも署名がずれないやり方って
ありますでしょうか?

Aベストアンサー

基本的にありません。

もともとメールは単なるテキストです。
質問者さんは、HTML形式でメールを送られているようですが、
メールを受け取った方が、HTMLメールに対応していなければ、
文字サイズやフォントはすべて無効になり、
相手の環境に依存します。

また、HTMLメールで同じフォントを指定している場合でも、
Windows XPとVistaでは、見え方が異なるようです。

メールの署名を凝ったものにするのも結構ですが、
ちょっとでもずれると表示が激しく乱れるようなものは
避けた方が無難と思います。

Q$postflag=1とか$flag=1とかってなにを意味しているの?

CGIでperlを勉強してます。

アンケートフォームや掲示板などのデコード処理の中によく、$postflag=1;とか$flag=0;とか出てくるんですけど、この変数はなにを意味しているのですか?

Aベストアンサー

勉強を始めたばかりの方とお見受けします。
小難しい説明だと理解しづらいですよね。

コーディングの暗黙的ルールとして
flag(フラグ)というものは1か0です。(またはtrue/false、真/偽、on/off、などなど。。。)
つまり2者択一をする場合の判定条件に使われる変数だと思ってください。

例えば性別を選ばせるアンケートフォームがあるとします。
で、女性と回答された場合のみ割引サービスの画面を見せたいって場合などに
フラグを利用します。$seibetsu_flagとでもしましょう。
基本は$seibetsu_flag=0ですが"女性"と選択された場合のみ$seibetsu_flag=1となるよう
プログラムを組んでおけば、後の処理で、


if ($seibetsu_flag=1) {

  ★女性なのでサービス画面表示する処理

}
else {

  ★男性なので通常処理

}


こんな感じで判定することができますよね。
$postflagは名前から察するにNo.3さんの回答の用途だと思いますよ。

勉強を始めたばかりの方とお見受けします。
小難しい説明だと理解しづらいですよね。

コーディングの暗黙的ルールとして
flag(フラグ)というものは1か0です。(またはtrue/false、真/偽、on/off、などなど。。。)
つまり2者択一をする場合の判定条件に使われる変数だと思ってください。

例えば性別を選ばせるアンケートフォームがあるとします。
で、女性と回答された場合のみ割引サービスの画面を見せたいって場合などに
フラグを利用します。$seibetsu_flagとでもしましょう。
基本は$seibets...続きを読む

Qアウトルックのメール送信時に手動で署名を入れたいのですが

アウトルック200のメール送信時に、通常は署名を入れない状態にしておいて、必要な時にだけ手動で入れるようにするにはどうすれば良いのでしょうか?
メール本文作成画面で、挿入から定型句の中の署名を選んで入れることはできるのですが、それだと、ツールのオプションののメール形式の中の署名で作成された署名が入力されずに、ただ単純に名前だけ入力されます。
アウトルックのヘルプを見たら、メール作成のエディタをワードにした時とアウトルックにした時とでは違うらしく、ワードをエディタとして選んだ場合、手動で入力される署名は、ワード起動時に入力した使用者名が挿入されるとのこと。
ならば、アウトルック上で作った署名を手動で入力するには、エディタをアウトルックにしないと不可能なのでしょうか?
それと、エディタをワードにした場合とアウトルックにした場合とでは何が違うのでしょうか?どちらの方が便利でしょうか?

Aベストアンサー

アウトルック2000を使ってます。
アウトルックのツールメニューのオプションでメール形式を選びます。
ここでたくさんの署名を作る事が出来ます。
私の場合、遊び感覚や正式な署名など色々作っています。
私は通常使用頻度の高い署名を設定してます。

テキストメール・HTMLメール・雛型メールについての署名の事。

メールを書くとき署名が既に入る設定にしていますが、その署名を使いたくないときは、面倒でもデリートで裂く一旦削除します。
メール作成画面で、挿入メニューの署名を選択すると、たくさん作った署名にタイトルを付けてありますので数ある署名から適宜を選びます。


ワードなどのオフィスドキュメントのメールについての事。

ワードエディターでの署名はワードのツールメニューの中のオプションの全般タブに電子メールオプションがあります。
その中で電子メール用の署名を作ります。そこでも色々な署名が出来ます。
そこで各種作るとワードメールを使った場合、挿入から署名を選ぶとワード起動時の使用者名の他にも、先ほど作った署名を任意に選ぶ事が出来ます。

余談ですが、動画のイラスト入り署名も出来ますよ。


説明が下手で申しわけありません。
わからなかったら補足します。

間違いなく出来ますよ。
色々署名で楽しんでいます。

(奥が深いです)

アウトルック2000を使ってます。
アウトルックのツールメニューのオプションでメール形式を選びます。
ここでたくさんの署名を作る事が出来ます。
私の場合、遊び感覚や正式な署名など色々作っています。
私は通常使用頻度の高い署名を設定してます。

テキストメール・HTMLメール・雛型メールについての署名の事。

メールを書くとき署名が既に入る設定にしていますが、その署名を使いたくないときは、面倒でもデリートで裂く一旦削除します。
メール作成画面で、挿入メニューの署名を選択すると、...続きを読む

Qwhileの$_とforeachの$_の関係

以下のコードにおけるwhileとforeachでの$_の使いかたについて教えてください。

my @foos = qw( a b );

sub foo1 {
  open FH, "foo.txt";

  while (<FH>) {
    chomp;
    print "$_";
  }

#  while (my $x = <FH>) {
#    chomp $x;
#    print "$x";
#  }
  
  print "\n";
}

sub foo2 {
  foreach (@foos) {
    print "<$_>";
    foo1();
  }
  print "\n";
}

foo2();
foo2();

このコードと同じディレクトリに以下のような内容のfoo.txtをおいて実行します。

x
y

すると、以下のような結果が得られました。

<a>xy
<b>xy

<>xy
<>xy

一回目のfoo2で@foosの内容が消えてしまいます。一方、コメントアウトしてあるようにwhileに変数($x)を使うと期待したとおりの結果が出ます。なぜ、このような結果になるのでしょうか。ご存知の方がいらっしゃったら教えてください。宜しくお願いします。ちなみに、WinXP + ActivePerl(v5.8.6)で試しました。

以下のコードにおけるwhileとforeachでの$_の使いかたについて教えてください。

my @foos = qw( a b );

sub foo1 {
  open FH, "foo.txt";

  while (<FH>) {
    chomp;
    print "$_";
  }

#  while (my $x = <FH>) {
#    chomp $x;
#    print "$x";
#  }
  
  print "\n";
}

sub foo2 {
  foreach (@foos) {
    print "<$_>";
    foo1();
  }
  print "\n";
}

foo2();
foo2();

このコードと同じディレクトリに以下のような...続きを読む

Aベストアンサー

簡単に言うと
$_ をfoo1 とfoo2 で使っている為です。
こういうことがあるので
関数の中では使う変数はできるだけ局所的な使い方をするのがよろしいです。
最初の
foreach(@foos){
}
の中で$_ は、配列の中身のコピーではなくて、配列の要素そのものを指しているので、$_ への変更は直接@foosへの変更になってしまうので注意が必要です(この動作はこの動作で便利なものなんですが・)
なので、
foreach my $x (@foos) {
print "<$x>";
foo1();
}
のようにすれば良かったのかもしれません。
また、
sub foo1{
local $_;

}
のようにすれば、
foo1 で(foo2で使っていても)安心して$_ を使うことができます。

QMicrosoft Office Outlookメール文に署名貼付で

Microsoft Office Outlookメールを利用しております。
Outlook expressの時は、メール文中に署名の貼付が、メニュー[挿入]、[署名]から署名を挿入できましたが、Microsoft Office Outlookでは、どのようにすれば良いのでしょうか、よろしく、お願い致します。

Aベストアンサー

Microsoft Office : Office Outlook 2003 コミュニケーション テクニック - 署名を作成してメールを使い分けたい!
http://www.microsoft.com/japan/office/previous/2003/experience/workstyle/tips/outlook/tips3.mspx

Outlook 2007 で電子メールの署名を作成する方法
http://support.microsoft.com/kb/931825/ja

Q$hts =~ s/##([^#]+)##/$FORM{$1}/g の意味を教えてください!

お世話になります。
perl素人なのですが必要に迫られてWEBで調べながら
ソースを解析していますが、次のコードで完全に止まってしまいました。

$hts =~ s/##([^#]+)##/$FORM{$1}/g

この場合、
#hts から ##([^#]+)## を探して $FORM{$1} に全て置き換えようとしていると思うのですが、以下2点が理解できず困っています。

1.##([^#]+)## の意味
$htsに##で囲まれた文字列が複数あるのでそれら全てを探すということでしょうか?

2.$FORM{$1} の意味
$1は1.で検索した結果だと思いますが、$FORM{ }は一体なんでしょうか?

素人がいきなり解析するのは無謀なのは承知の上ですが、
どうしても業務で必要なので、お知恵をお貸し下さい。
よろしくお願いいたします。

Aベストアンサー

1.
perlを基準に「正規表現」で調べてごらん

2.
同じくperlでHTMLのformデータを受け取る方法を調べてごらん

Qヤフーメールで署名がつけられない

ヤフーのメールを使っています。昨日あたりに突然仕様変更がありました。

そして、メール作成画面の下にあった、「メールに署名を入れる」とかいうボタンが見当たらなくなりました。この仕様で署名を入れるにはどうすればいいのでしょうか?

設定画面の「全てのメールに署名を入れる」だと、個人的には都合が悪いです。あと、これにチェックを入れて自分にテスト送信してみても、署名がありませんでした。

勝手に仕様変えるのって不便極まりないですね。

Aベストアンサー

#1です。

私は、YahooBB会員ですが、署名の入り具合を確認しました。

Yahooの契約IDのybb.ne.jpでの送信では、メールオプションの「メールアドレスの追加・編集・削除」の編集で作成した署名が、

yahoo.co.jpでの送信では、メールオプションの「署名」の項目で作成した署名が、「すべての送信メールに署名を付ける」を有効にすると、そのまま本文にそれぞれの署名が自動的に入るようです。

従って、作成画面での「利用する」のチェック入れは無くなって、不要であれば、本文から削除する必要があります。

追加アドレスでも使う署名はそれぞれ会員IDと同じですが、「署名を利用する」のチェックを入れる項目は作成画面にあって、チェックを入れてそのまま送信するとそのメールに自動的に入るようです。

まだ、完全にすべてのIDに行き渡っていない仕様のようですが、確認した状況はそのようになっていました。

Q$x=''とした場合と$x=0とした場合で

$xにどちらが設定されているか判別する手段はあるのでしょうか?
有るとすればどうすればいいのでしょうか?

Aベストアンサー

単純に if($x eq '0') で大丈夫じゃないでしょうか?


$x = 0;

if($x eq '0') {
print "0を設定\n";
} elsif(! $x and defined $x) {
print "'' を設定\n";
} elsif($x) {
print "$x を設定\n";
} else {
print "\$x は未定義\n";
}


人気Q&Aランキング

おすすめ情報