dポイントプレゼントキャンペーン実施中!

perl5.8でFormから送られてきたデータを取得し、整理しています。

FormはPOSTでperlに送り、データを整理したのですが、checkboxで複数のデータを送ったとき、うまく処理されていません。
Formのあるページも同じperlでcgiページを作り、エラーがあった場合、エラーメッセージ付きで再度そのcgiページを表示するようにしています。

次の内容で、@noにcheckboxで選択した番号が入るようにしています。
valueには - が余分にありますが、これは試しにcheckboxで複数選択してデータをsubmitしてみたところ、受け取り先の$in{no}で番号が連続して1つのスカラーで連なるので、番号を後に分割するために-を入れ、受け取り後、@no = split(/-/, $in{no});でばらして@noに番号を格納してあります
$r_noは別のデータから受け取った比較先の番号です

Formのcheckboxの部分は(実際はこれを複数回ループして$r_noが変化します)
my $checkbox;
foreach my $l (@no){
my $i = 0;
if($l == $r_no){ $i = 1; }
if($l == $r_no){
$checkbox = "<input type=\"checkbox\" name=\"no\" value=\"$r_no-\" checked>"; last;
}else{
$checkbox = "<input type=\"checkbox\" name=\"no\" value=\"$r_no-\">";
}
}
print "$checkbox";

2つ以上checkboxを選択して、わざとエラーが出るように他の部分を間違った選択をするようにして試してみたところ、@noには選択した分だけの番号が格納されているにもかかわらず、
if($l == $r_no){
の部分が真になるのは1つ目の@noとの真偽だけで、2つ目以降は本来真になるべき比較でも偽になってしまいます。
改行コードなどが入っているのかと思い、chompで後ろを削ったり、$l =~ s/\r?\n/K/g; $l =~ s/\r/K/g;で改行コードを可視化して確認してみましたが、それらしきものも入っていませんでした

@noには選択した番号全てが収納されていますし、後ろに改行コードなど不要なものも入ってないのに真偽の分岐がうまくいかない原因は何にあるのでしょうか?
思い当たるものは一通り試したのですが、どうしてもわかりません。
「これが原因かも?」みたいな可能性だけでも結構ですので教えてください。
よろしくお願いします。

A 回答 (3件)

「cgi-lib checkbox」で検索すると、いくつか見つかります。


それには「複数のチェックボックスから受け取った$in{CHECKBOX}は\0で区切った文字列になる」と書いてあります。
\0は通常文字として表示されないので
"A\0B\0C"
は、画面上は
ABC
と見えてしまいます。

このプログラムでは、
"1-\02-\03-"
というのが入っているはずで、これを/-/でsplitしたら
"1"
"\02"
"\03"
というリストになり、\0は数字ではないので、 \02 は「2」ではなく「0」になります。
最初のだけ、\0がないので、数値として有効になります。



> printf STDERR "l:%s,r_no:%s, Judge:%d\n",$l.$r_no, ($l == $r_no);
> これの構文の意味が理解できてないので、そのままそれをループの中に入れてみて試しましたが、何も起きませんでした

Perlの基本なので覚えてほしいのですが
STDERR(標準エラー出力)に、"l:%s,r_no:%s, Judge:%d\n" という書式で、続く値を出力する、というのものです。
Cのfprintfに相当します。
http://perldoc.jp/func/printf

STDERRだと、httpサーバー(Apacheとか)のログかなんかに残っていると思います。
あるいは、適当なファイルをopenしてSTDERRの代わりにしてもいいかと思います。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
おかげさまで解決に至りました。
使用しているライブラリcgi-lib.plの仕様だとは知りませんでした。

しばらく後にベストアンサーで質問を終了しますが、もしよろしければこれに関連して1つ教えてください。

cgiをperlで動かし、日本語操作をするにあたり、現在最も標準的なライブラリは何を使えばいいのでしょうか?
以前はcgi-lib.plとjcode.plの2つを冒頭に読み込ませ、そこから自分なりのコードを書いていましたが、他の方のご指摘を受け、cgi-lib.plとJcode.pmに変え、そして今はcgi-lib.plのみで受信データの文字コード変換にはuse Encode qw(from_to encode);を使っています。
Encode.pmなどもあると聞きますが、どのライブラリを組み合わせて使用するのが一般的かつ使いやすいのでしょうか?(これらのライブラリがどんな役目をしてくれているのかすらよくわかってません)
なお、コードを書いているマシンはWindowsのため(サーバーはレンタルでUnix系だと思います)sjisのエディタを普段使用しています

お礼日時:2013/04/05 17:01

> cgiをperlで動かし、日本語操作をするにあたり、現在最も標準的なライブラリは何を使えばいいのでしょうか?




スクリプトはUTF-8で記述して、use utf8;する。
cgi-lib.plの代わりに、CGI.pmとEncode
http://search.cpan.org/~lds/CGI.pm-3.43/CGI.pm

Windowsでの確認は、UTF-8のままでもできます。
テキストエディタは、UTF-8に対応しているものを探してください。

5.8とのことですが、その下は何番でしょう?
5.8.xはUnicodeへの対応が安定してきたバージョンで、バージョンが若いと、問題が出るかもしれません。
    • good
    • 0
この回答へのお礼

早速のご教授ありがとうございました。
CGI.pmとEncodeの利用方法について早速調べて導入したいと思います。

> 5.8とのことですが、その下は何番でしょう?

わかりません
レンタルサーバーの紹介では5.8.*となってます

お礼日時:2013/04/06 16:13

> 真になるのは1つ目の@noとの真偽だけで、2つ目以降は本来真になるべき比較でも偽になってしまいます。



これが、どんなことを言っているのかよくわからないのですが。
$no[0]と$no[1]のことですか?
「本来真になるべき」というのは、あなたの頭の中での話ですか?実際に$lと$r_noにどんな値が入っているか確認した上での話ですか?

確認していないのなら、

printf STDERR "l:%s,r_no:%s, Judge:%d\n",$l.$r_no, ($l == $r_no);
とでもして、実際に何と何を比較しているか確認してはどうでしょう?



> 受け取り先の$in{no}で番号が連続して1つのスカラーで連なるので

これもわかりません。
どんな方法で受け取っているのでしょう?
CGI.pmなどを使うとか、自作でも工夫すれば、最初からリストで受け取れるはずですが。
    • good
    • 0
この回答へのお礼

回答ありがとうございます

> $no[0]と$no[1]のことですか?

はいそうです。

> 実際に$lと$r_noにどんな値が入っているか確認した上での話ですか?

はい、画面上にわざと表示させて確認しました
なので、@noにもきちんと数値が格納されており、また$r_noと一致する状況があることも確認しました
なので、もしかしたら画面上に表示されてない改行コードのようなものが付いていて比較したときに一致(真)にならないのかなとも考えたりしましたが、まだ原因がわかっておりません

printf STDERR "l:%s,r_no:%s, Judge:%d\n",$l.$r_no, ($l == $r_no);
これの構文の意味が理解できてないので、そのままそれをループの中に入れてみて試しましたが、何も起きませんでした

> どんな方法で受け取っているのでしょう?

ライブラリはcgi-lib.plとuse Encode qw(from_to encode);を使用しています
これについては中のことはよくわからず、呪文のように使ってます。
そしてその後
&ReadParse;
read(STDIN, $QUERY_DATA, $ENV{'CONTENT_LENGTH'});
として、データを受け取って、一連のデータを&で分割、それぞれを=で$nameと$valueに分割、変換後、各データを$in{$name} = $valueとして整理しています

お礼日時:2013/04/04 14:00

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