- 締切済み
変数に値を代入するのに、まずundef、次にNULL文字を足して、それから入れたい値を足すって回りくどくないですか?
KENTさんの作ったメールフォームのコードをフォローしています。 Clip Mail v1.1です。 http://www.kent-web.com/data/clipmail.html その中で、メールフォームから送られてきたデータを取り入れるサブルーチンに関する質問です。 undef(%in); $in{$key}.="\0"; $in{$key}.=$val; 最初の undef(%in); はサブルーチン中の冒頭にあり、残り2行とはかなり離れた位置にあります。 これまで私がこういうコードを書く場合、 %in; $in{$key}=$val; と書いてきました。この他、変数の宣言にはourとかmyとか付けてますけど、KENTさんがこのプログラムを書いた当時はmyはともかくとして、ourを付けることはあまり普及していなかったのではないでしょうか。 さて、C言語などだと変数を用いる前に宣言だけでなく初期化も行っていないといけないわけですが、Perlの場合は初期化されていない変数はundefとして自動認識されます。 undef(%in); と、私がやっているような %in; の違いは初期化もきちんとしているか、ただ宣言だけで初期化はPerlにお任せしているかの違いです。Perlの仕様上はどちらでもいいでしょう。 分からないのは残りの2行のコードです。 undef(%in); でキチンと初期化してある変数に対して、まず $in{$key}.="\0"; とします。なんでNULL文字なんか入れないといけないのでしょう。それも単純に $in{$key}="\0"; ではなくて、 $in{$key}=$in{$key}."\0"; です。 更に3行目で $in{$key}.=$val; とするわけですが、こんな2行かけた代入を行わなくても、私がこれまでやってきたように $in{$key}=$val; で実用上の用は足りると思うのですが・・・ 1行目は何となく分かるんです。変数の初期化は、Perlに自動認識の機能があるのを知っていても、他の言語を知っている方は、やはり言語任せに出来ないのではないでしょうか。 残りの2行のコードも多分そんなところだと思います。実用上は私のやり方で足りると思うので。ただC言語なんかでもこんな代入の仕方をしているのを私は見たことがないし、まあ、こんな代入の仕方をしないといけない言語もあるのでしょうが、ではその言語でこのやり方をせずに私がやるような方法を取った場合、どんなエラーが出るのでしょう。 どなたか分かる方、教えていただけないでしょうか。
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- 大野 悟(@ohnosatoru)
- ベストアンサー率56% (17/30)
NULL文字を入れているのって、同じフォーム名を複数使った場合の区切り文字ってことはないですか? ソースコードを細かく追ったわけではないので違っていたらごめんなさい。 よくフォームのデコード処理でNULL文字は区切り文字として使われることが多いので。 参考になりましたら。
- t-okura
- ベストアンサー率75% (253/335)
> undef(%in); >と、私がやっているような > %in; >の違いは初期化もきちんとしているか、ただ宣言だけで初期化はPerlにお任 >せしているかの違いです。 $in{$key}.="\0"; はおいておいて、 %in; では変数の初期化は行われません。変数の初期化を行うなら %in = (); ですね。 下記を実行してみてください。 use strict; use warnings; use Data::Dumper; my %in = ( a=>1, b=>2); print Data::Dumper->Dump( [ \%in ] ); %in; print Data::Dumper->Dump( [ \%in ] ); undef %in; print Data::Dumper->Dump( [ \%in ] ); exit;
補足
6行目のように、ただ %in; と宣言しただけでは、前の%inを引きずってundefに初期化されないんですね。 この場合の6行目は宣言と言えるかという問題もあります。結果的に何もしない式を書いただけとも言えます。このように実際のコーディングの中で、コーディングする方は宣言したつもりが、Perlの方はそうではない解釈をしている可能性もあるわけで、そこらへんが自動認識の怖さですね。 undef(%in); としておけば、そこらへんの曖昧さがなくなるということですね。 ありがとうございます。
- kabaokaba
- ベストアンサー率51% (724/1416)
$in{$key}.=$val; $in{$key}=$val; この二つが同じにみえるのですか? これが同じにみえるなら $a += 1; と $a = 1; が同じということになります. KENT氏は,\0をきっと 「値のセパレータ」 として使ってるんでしょうね.
補足
アドバイス、ありがとうございます。 セパレータとして使うのであれば、同じキーのin変数に何度もその時々の$valが代入されなくてはいけません。でもそれぞれのキーで件の2行のコードが行われるのは1度きりです。もっともコード自体はforeach文で何度も廻していますけど、その時々でキーが違います。 そうすると、 $a += 1; と $a = 1; が同じということになってしまうような。 つまり当初$aはundefで、Perlの場合、$aを数字として扱う場合は0と自動認識されますから、一度だけ $a+=1; を行った結果は1であり、 $a=1; と同じ意味になってしまうのではないでしょうか。 同じくたった一度きり$valを代入するのであれば、 $in{$key}=$val; でいいような。 ちょっとNULL文字の意味が良く分からないのですが、今問題にしているプログラムはメールフォームなので、後々全てのデータを一繋ぎにして送信を掛けるような仕様になっているのかも。その際にはNULL文字が仰るようにセパレータになるのかもしれません。 でもとりあえず、それぞれのキーで $in{$key}.="\0"; $in{$key}.=$val; は一度しか行われていないので、私の持っている知識だとこの2式は $in{$key}="\0".$val; と同意です。 それと、このプログラムではデータをメール形式に直すサブルーチンとしてmimew.plを用いていますが、私の持っている別の本にあるサンプルプログラムのメールフォームでは、同じくmimew.plを用いていますが、mimew.plにデータを渡す前処理として個々のデータの前にNULL文字を加えるなんてしていないんですよね。
お礼
このコードはフォームデータをCGI側で受け取る際に使っています。 普通、フォームデータはinputタグごとに一つずつname値なりid値なりを設定するので、フォームデータから得たキーと値をそれぞれ$key、$valに格納して、さらにそれを $in{$key}.=$val; とすると、この式は $in{$key}=$val; と同意になります。 しかしinputタグのtype値がcheckboxの場合など複数回答がありうる場合は、その設問でname値なりid値を同じくしておいた方が便利な場合があります。この場合に、 $in{$key}=回答1\0回答2\0回答3・・・ のようにするために、 $in{$key}.=$val; としていました。 ありがとうございます。