- ベストアンサー
lengthで返ってくるバイト数の計算があいません
お世話になります。 lengthで返ってくるバイト数の計算があわず困っています。 全角文字列と全角スペースをあわせて12文字(24バイト)の出力をさせたくて以下のように記述しました。 $spaceStr = ' ' x ((24 - length($in{'name'}))/2); $in{'name'}には全角の名前が入るようにしています。 最終的に$spaceStrをテキストに出力したいのですが、 例えば$in{'name'}が「あ」の一文字の場合、期待では ' ' x ((24 - 2)/2) なので11文字の全角スペースが出力されると思ったのですが、出力は9文字の18バイト分の全角スペースしか出力されません。 この原因は何でしょうか? ご教授の方をよろしくお願いします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
#2補足>入力"あい"で253832256130253832256132出てきました。 #2補足>これを16進数(から戻す)にすると%82%a0%82%a2になりますが・ ということは、 length($in{$name})している時 $in{$name}="%82%a0%82%a2"; となっているということです。(それなら12バイトは納得ですね。) $value="%82%a0%82%a2"; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; で $value="あい"; になりますから $in{$name}= しているところで、変換された$valueを使っていないか、 $valueを変換しているところをスキップしているような感じですね。 もう一度流れを見直してみるか、 ところどころで、printして確認して見て下さい。
その他の回答 (3)
- Hasty
- ベストアンサー率73% (19/26)
もしかしてmod_perl環境だったりしませんか? mod_perlではグローバル変数が保持されてしまうので、リクエストの度に%inに次々と値が格納されてしまい、変な動作をしているように見えることがあります。 $in{'name'}の値を表示してみて、過去に入力したデータなども入っているようであればこれが原因だと思いますので、スクリプトの最初で undef %in; とするようにしてみて下さい。
補足
回答有難うございます。 一応indef %in;も試してみましたが、変化はありませんでした。 使用しているサーバーの環境はmod_perlではないようです。 以前の値が格納されていることはないようです。 ご助言に感謝いたします。
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
#1補足>特におかしなところは無いようですが、 $in{'name'}="あい"; でシフトJISのはずなのに6バイトということであれば、 sub StoH ($){ my $chs = shift; return join("",map(sprintf("%02X", $_),unpack("C*",$chs))); } みたいな感じで print &StoH($in{$name}); してみてどんなコードがでてくるか調べてみたらどうでしょう シフトJISで"あい"なら 82A082A2 になるはずですが。
補足
何度もご回答を頂き本当に有難うございます。 上のサブルーチンをお借りして出力させてみたところ、入力"あい"で253832256130253832256132と出てきました。 どこかで10進数になっているらしく、これを16進数にすると%82%a0%82%a2になりますが・・・ どこかで変換ミスがあるのでしょうか。 小さな可能性でもいいので、宜しくお願いします。
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
結果から考えると、$in{'name'}が6バイトあるということです。 全角一文字が2バイトというのは、文字コードによっては異なることがありますが、「あ」一文字が6バイトは、ちょっと考えにくいので、他の文字がくっついているのではないかと思います。 ちなみに encodingの指定をちゃんとしてやれば、lengthを使っても全角文字も1文字として数えます。
補足
確かにそうなんですよね。 それでいろいろ試してみましたが、例えば、$in{'name'}のバイト数は、「あい」を入力すると12バイト、「あいう」を入力すると18バイト、「12文字」と入力すると20バイトと言うようになりました。 1文字あたり6バイトというわけでもないようで… $in{'name'}の中身はS-JISなので、S-JISのまま文字数カウントしてもEUCに変換して文字数カウントしても、おかしなことになりました。 そもそも$in{'name'}にはフォームから受け取った値が入るので、そこに問題があるのかなと思って考えたのですが、以下の書き方におかしな点がありますでしょうか? sub decode_form{ @pairs = split(/&/,$buffer); foreach $pair (@pairs) { ($name,$value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; $name =~ tr/+/ /; $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; &jcode'convert(*value,'sjis'); #同じname属性の場合 if($in{$name} ne ''){ $in{$name} .= " ".$value; }else{ $in{$name} = $value; } } }
お礼
正常に出力されるようになりました。 有難うございました。 >それなら12バイトは納得ですね。 確かにそこは納得できましたが、そもそもの原因はわからないままです。。。 再度全体を確認してみます。 本当にお世話になりました。