• 締切済み

変数に値を代入するのに、まず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言語なんかでもこんな代入の仕方をしているのを私は見たことがないし、まあ、こんな代入の仕方をしないといけない言語もあるのでしょうが、ではその言語でこのやり方をせずに私がやるような方法を取った場合、どんなエラーが出るのでしょう。 どなたか分かる方、教えていただけないでしょうか。

  • Perl
  • 回答数3
  • ありがとう数1

みんなの回答

回答No.3

NULL文字を入れているのって、同じフォーム名を複数使った場合の区切り文字ってことはないですか? ソースコードを細かく追ったわけではないので違っていたらごめんなさい。 よくフォームのデコード処理でNULL文字は区切り文字として使われることが多いので。 参考になりましたら。

makoji
質問者

お礼

このコードはフォームデータを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; としていました。 ありがとうございます。

  • t-okura
  • ベストアンサー率75% (253/335)
回答No.2

> 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;

makoji
質問者

補足

6行目のように、ただ  %in; と宣言しただけでは、前の%inを引きずってundefに初期化されないんですね。 この場合の6行目は宣言と言えるかという問題もあります。結果的に何もしない式を書いただけとも言えます。このように実際のコーディングの中で、コーディングする方は宣言したつもりが、Perlの方はそうではない解釈をしている可能性もあるわけで、そこらへんが自動認識の怖さですね。  undef(%in); としておけば、そこらへんの曖昧さがなくなるということですね。 ありがとうございます。

  • kabaokaba
  • ベストアンサー率51% (724/1416)
回答No.1

 $in{$key}.=$val;  $in{$key}=$val; この二つが同じにみえるのですか? これが同じにみえるなら $a += 1; と $a = 1; が同じということになります. KENT氏は,\0をきっと 「値のセパレータ」 として使ってるんでしょうね.

makoji
質問者

補足

アドバイス、ありがとうございます。 セパレータとして使うのであれば、同じキーの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文字を加えるなんてしていないんですよね。

関連するQ&A

  • 置換した文字列を変数に代入する方法

    お世話になります。 たとえば、 #!C:\Perl\bin\perl print $form->header("text/html");  : open(IN,"<file.txt"); while(<IN>){ : : s/あい(.*?)うえお/$1/; (????)←「$1」の内容を変数に代入したい : : } close(IN); というように、テキストファイルの文章中の 「あい(.*?)うえお」から(.*?)を取り出して、 その取り出した(.*?)を変数に代入したいのですが、 いろいろ試してやっているのですが、難儀して おります。どのように書いたらいいか教えてください。よろしくお願いします。 最終的にclose(IN);のあとで、print 変数;として(.*?)の文字列を表示させたいです。

    • ベストアンサー
    • Perl
  • SQL における変数の宣言と代入の仕方

    SQL における変数の宣言と代入の仕方 データベース言語でどの様なことが出来るものかと思い、postgreSQL を独りでいじり始めました。入力されたデータのチェックをきちんとしないといけないのだな、と思い、 --- CONSTRAINT rangeMin check (policyMin in (-3,-2,-1,0,1,2,3,4)), CONSTRAINT rangeMax check (policyMax in (-3,-2,-1,0,1,2,3,4)), --- と記述したのですが、「-3 から 4」という部分を重複して記述するのを避けたいので、 変数を宣言するなり何なりして何とかしたいのですが、 "SQL assign" やら "SQL variable" といったキーワードで色々検索しても、どうしても有用な情報に行き当たりませんでした。なにかしらのヒントを頂ければ幸いです。 宜しくお願いいたします。

  • 変数について

    お世話になります。 VBAにてプログラムを作成しています。 本コードで得た変数をCALLのサブルーチン先 でもその変数を生かしたいのですが、empty空 になってしまいます。 変数宣言はPublicにしているのですが。 そう言うものなのでしょうか。 お教え頂きたく宜しくお願い申し上げます。

  • サブルーチンについて

    サブルーチンについて教えて頂きたいのですが HTMLからPOSTされる複数のデータ(Key=A&値=B…)をkeyごとにサブルーチンの引数 として渡したいのですが、現在は「&ReadParse」を使って$inから値を取り出しています。 ただ数十個の値が一度にPOSTされる為、下記のコードをひたすら書く感じになってしまう のかな…と思ってお尋ねしております。 それから、サブルーチンからの戻り値を、フォームに(Key=A&値=B…)の感じで返したいのですが どうすればいいのでしょう。 @pairs = ($in{'val1'},$in{'val2'},$in{'val3'},$in{'val4'},$in{'val5'}); ($para1,$para2,$para3,$para4,$para5) = @pairs; $values = func($para1,$para2,$para3,$para4,$para5); 私自体、Perl初心者でわかっていない為、なにか方法があれば教えて下さい。宜しくお願いしますm(__)m

    • ベストアンサー
    • Perl
  • 超基本 変数への代入教えてください。

    dim mychr as string * 255 mychrという変数を255個宣言しているのは分かりますが、どうやって代入するかが分かりません。ちなみに mychr=vbnullstring '初期化 mychr="ABCDEFG" mychr="A" mychr(0)="A" 全部だめでした、本で調べるにも調べようがなく、ご教授お願いいたします。

  • 変数の大きさを超える代入

    現在作っているプログラムで、一定時間ごとに変数に一定値が 加算され続けるような場所があります。 基本的にはint型の最大値を超えることはまずないのですが、 C言語やC++でたとえばint型で宣言した変数に対し、x++; のように一定周期ごとに記述して加算してゆき、最大値である、 +2147483647を超えた場合、xには何が代入されているんでしょうか。 -2147483648~+2147483647が範囲ですから、一周して、 最低値である-2147483648に加算されてゆくことになるのでしょうか? それとも、超えることが予想される場合、最大値を超えたら0にするなど 明示的に何らかの対処をしたほうがよいのでしょうか。 プログラム的には中身の数値に関してはあまり関係ないので、 その変数型の範囲で不可なく動作するなら問題ありません。 超えることが予想される場合、対処するべきなのか、 放っておいてもよいのかどうかを教えていただきたいです。

  • VC++ 高速演算コードの沢山の変数の宣言方法

     【VC++ 高速演算コードの沢山の変数を、どのように宣言すべきでしょうか?】  今日は、質問させていただきます。 もしお詳しい方がいらっしゃいましたら、 どうぞよろしくお願いいたします。  Fortranのコード(歴10年程度)を、VC++2010(歴3ヶ月程度)になおそうとしております。  ボリュームのある数値解析のコード(3000行程度ございます)を、見やすくするために、 数百行ずつでサブルーチン化したい次第でございます。    例)int main(){                ←変数の宣言場所         definition()         calculation1()         calculation2()         calculation3()         conclusion()      }  しかしmainの最初(上記「変数の宣言場所」)にまとめて宣言しております変数が200個以上ございまして、これらの半分近くを各々のサブルーチンに毎回渡そうといたしますと、引数の量が膨大になってしまいますし、 またサブルーチン内で何か追記する度に引数を追加・削除せねばなりませんので、出来れば避けたい次第でございます。  そこで「全てPublicで宣言してしまおうかな?」などと考えて検索しておりましたが、「できる限りPublic変数を宣言すべきでない」といったような記事もございましたので、悩んでおります。 (Fortran環境下では、ヘッダファイル内のPublic変数を、全サブルーチンで毎回呼び出しておりましたが、それも良くないのかな、と迷っております。)  あと、上記のような宣言方法や参照方法が計算速度に影響するものなのかどうか分からないのでございますが、 平均で10日間程度まわし続けるプログラムになりますので、出来る限り「高速化」を優先したい次第でございます。  変なご質問かもしれませんので大変恐縮でございますが、 是非アドバイスいただけないでしょうか。(書物やサイトをご紹介いただけるのでも結構でございます)  何卒よろしくお願いいたします。

  • 変数名の連結

    以下のような配列があるとします。 $str[0] = aaa; $str[1] = bbb; $str[2] = ccc; foreachでまわし変数名を連結し代入するというような事は可能なの でしょうか? foreach ($str as $key => $val) { //$keyをechoすると012と表示 //ここで変数名を$data0,$data1のようにしたいがうまくいかない $data . $key = $val; //配列にするぶんには正常に動作しました $data[$key] = $val; }

    • ベストアンサー
    • PHP
  • Array()で配列の一次元部分と二次元部分に同時に値を代入するには

    class categoryInfo{  var $langName = array(   "app" => array(    "c" => "C&C++",    "java" => "Java",    "vb" => "Visual Basic.NET",(以下略)   ),   "markup" =>array(    "html" => "HTML",    "css" => "CSS"   ),   "web_app" => array(    "javascript" =>"JavaScript",    "php"=>"PHP",    "perl"=>"CGI/Perl"   ),  );  $langName[app] = "アプリケーション開発用言語";  $langName[markup] = "マークアップ言語";  $langName[web_app] = "Webアプリ"; } ・・・という風にしているのですが、当然ながら、最後の $langName[app] = "アプリケーション開発用言語"; などは、既に宣言した変数に値を代入する行為であるため、関数内で行うように、とのエラーメッセージが出力されてしまいます。  コンストラクタで宣言すれば良い話ではあるのですが、600行ほどあるファイルなので、別の場所で宣言すると面倒になってしまいます。  又、後々foreachを使うので、連想配列を用いている以上、Array()を使って順番を定義したいのです。  このArray()の中で、$langName['app']などの一次元部分に値を代入した上、$langName['app']['c']などの二次元の部分にも値を代入する方法はありますでしょうか?

    • 締切済み
    • PHP
  • 警告 ”値が割り当てられていないローカルな変数~”について

    以下のコード1では、”値が割り当てられていないローカルな変数 'key' に対して参照が行われました。”という警告が出ますが、コード2では出ません。 コード2でも値が割り当てられていないと思うのですが、どうして警告が出ないのでしょうか? お分かりの方、お教えくだい。 あと、かなり省略してしまったので、意味の無いコードになってしまいましたが、この2つのコードでkeyの意味合いはどう違うのでしょうか? よろしくお願いいたします。 <コード1> int in_dt() { int *key; scanf( "%d", key );///ここで警告が出る return 1; } int main( void ) { int code; code = in_dt( ); return 0; } <コード2> int in_dt( int *key) { scanf( "%d", key ); return 1; } int main( void ) { int code,key; code = in_dt( &key); return 0; }

専門家に質問してみよう