プロが教える店舗&オフィスのセキュリティ対策術

Perlで日本語を扱う際にjcode.plを使いたいと思いました。

問題点はgetcodeを使用した際に文字コードが出力されなかったということです。
'あ'はsjisと出るのですが 'a'は出力がありません。
文字コードが判別できなくてもなんらかの出力は得られるとWebで見たのでなぜ
このような現象になるのか質問させていただきました。

参考にしたサイト
http://www.mikeneko.ne.jp/~lab/kcode/jcode.html

[ソース]
#!/usr/local/bin/perl
require './jcode.pl';
print "Content-type: text/html\n\n";
$line = 'あ';
$code = &jcode::getcode(\$line);
print "print1 = $code\n";
$line = 'a';
$code = &jcode::getcode(\$line);
print "print2 = $code\n";

[結果(コマンドプロンプト上)]
Content-type: text/html

print1 = sjis
print2 =

このようになる原因を知りたいです。回答や実行環境への質問などお願いします。

実行環境 1
OS: WindowsXP SP1a
webサーバ: Apache 1.3.27
Perl: ActivePerl 5.8.0
ブラウザ: IE6.0

実行環境 2
infoseek無料webスペース

A 回答 (5件)

> undef != ヌルという認識でよろしいのでしょうか


「ヌル」という言葉は色々な意味に使われるので曖昧なのですが、もし「空文字列」のことを指しているのであれば、この認識は正しいです。

未定義値や空文字列などは、次のように分類されます。

  データ
   ├──────────┐
  定義値           未定義値
   ├───────┐  (undef)
   真          偽
 (その他)  (0, 空文字列, 空リスト)

一度も使用していない、または undef() を実行した変数は未定義値となります。
ちなみに論理演算(条件判定など)においては、未定義値は偽となります。

> なんとなく'未定義'を返すというのが変わっている(?)と感じた
undef を返す関数は結構あります。
getcode の場合、別に undef ではなく 0 や '' を返したってよいと思いますが、この辺は作者の好みでしょう。
(「判別不能→未定義」というニュアンスの問題かな?とも思います。)

結果を論理演算に使うことがメインとなる関数では 0 か 1 を返せば済みますが、0 の代わりに undef を返しても問題はありません。

しかし、何らかの計算を行う関数などでは、結果が 0(偽)になることも考えられますから、オーバーフローなどのエラーを undef で表現するというのは十分に考えられます。
    • good
    • 0
この回答へのお礼

毎回早い回答ありがとうございました。
図解までしていただき非常にわかりやすかったです。

説明も私のレベルに合わせていただいた感じを受け非常に感謝しています。

結論を勝手にまとめます
・getcode は'euc','jis','sjis','binary',undefを返す。
・ASCIIはundefになる
・undef は definedで偽となるものである。
・undefは未定義である。なお0,空文字列,空リストは定義値である

まとめて書いて申し訳ありませんがdeagleとleaz024さんありがとうございました。大変助かりました。

お礼日時:2003/08/21 01:45

> 文字列がASCIIか判定する方法はないのでしょうか。



getcode が undef を返す条件は
・日本語が含まれない時
・sjis か euc か判断できない時
の2通りしかありません。

1つ目の「日本語が含まれるかどうか」は、「\e 及び \x80 ~ \xFF」が含まれるかどうかで判断しています。(\e は JIS で使われるエスケープコード)
幸いなことに、これらの文字を含まない日本語コードは存在しないようなので、日本語が含まれないと判断されたら ASCII だと考えてよいでしょう。

2つ目の条件と区別するには、getcode をリストコンテキストで呼び出し、戻値の1番目の値を 0 と比較します。

  ($matched, $icode) = jcode::getcode(\$line);
  if (! defined $icode) {
    if ($matched == 0) { print 'ASCII' }
    else { print 'sjis or euc' }
  }

ちなみに上記の文字が含まれていれば、それは 'jis', 'sjis', 'euc', 'binary' のどれかだと判断されます。
これは「未知の文字コードかどうかは判断できない」ということであり、試しに unicode の「日本語」という文字列を渡してみても 'sjis' という結果が返ってきます。

> getcode,convertの判定・変換結果に多用されるASCIIがないのはなぜだと思われるかも可能だったら教えていただきたいです。
そもそも jcode.pl は日本語変換ライブラリなわけで、何の変換処理も必要としない ASCII をわざわざ覚えておく必要もないと考えたのではないでしょうか。
また、convert は文字コードが偽であるかどうかを真っ先に調べていますが、この時
  return if $icode eq 'ascii';
とするより
  return unless $icode;
とした方が効率も良さそうですからね。
注:実際のコードとは異なります。

この回答への補足

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

実際にleaz024さんのコードを使って試してみたところ
動作の確認が取れ、理解できました。

再三の質問になってしまい大変申し訳ないのですがundef=ヌルという認識でいたので
ASCII時に返されているのはヌルだとおもっていたのですがdefinedはヌル・0・空配列の時に真で
未定議時に偽とみたのでundef != ヌルという認識でよろしいのでしょうか。
結果とdefinedの定義からするとundef != ヌルなのですがなんとなく'未定義'を返すという
のが変わっている(?)と感じたので確認させていただきたいと思いました。

参考:http://tohoho.wakusei.ne.jp/wwwperl2.htm#defined

補足日時:2003/08/20 23:31
    • good
    • 0

getcode の戻り値は 'jis', 'sjis', 'euc', 'binary' 及び undef のいずれかです。


文字コードが判別できなければ undef が返ります。

> なんらかの出力が得られるとWebで見た
これは undef まで含めた広い意味で書かれたか、そうでなければ出所の内容が間違っているのでしょう。
単なるアスキー文字列は 'JIS' でも 'シフトJIS' でも 'EUC' でもないので、当然「判別不能」という結果になります。

> その対策も知りたい
とのことですが、対策というからには「getcode が undef を返すことに問題がある」ということですよね?
私も長らく jcode.pl を使っていましたが、これが問題となったことはありません。
ですが、もしその辺を補足もらえれば、アドバイスのしようもあるかと思います。
(ちなみに jcode.pl に含まれる関数で、これが問題となるものはありません。)

jcode.pl については、参考URLの「jcode.pl の私的な解説書」も参考にされるとよいでしょう。

参考URL:http://www.mikeneko.ne.jp/~lab/kcode/jcode.html

この回答への補足

詳細な回答ありがとうございます。

>単なるアスキー文字列は 'JIS' でも 'シフトJIS' でも 'EUC' でもないので、当然「判別不能」という結果になります。

ここがわかっていなかったようです。

>>その対策も知りたい
これは「簡単な文字列なのだから'jis','sjis','eus'のいずれかになるはず。undefになるのはバグもしくは
使い方の間違いをしたため」と勘違いしていたための質問でした。
その答えは「getcodeはASCIIでundefになる仕様だからundefを返すのは当然で正常である」ということだと
わかりました。

私が「対策も知りたい」と考えたのはASCII文字列が
ASCII文字列であるという確認をgetcodeで得たいと思ったためです。
ある文字列がASCIIのような汎用的な文字コードであるかそれ以外の不明な文字コードであるのかが判断したいです。

getcodeにおいてはASCIIは「その他の文字コード」に
分類されますが、文字列がASCIIか判定する方法はないのでしょうか。


getcode,convertの判定・変換結果に多用されるASCIIがないのはなぜだと思われるかも可能だったら教えていただきたいです。

補足日時:2003/08/20 16:04
    • good
    • 0

 他の半角文字や長文の半角文字で成功するかどうか確認してください。


 その場合、文字列が短すぎて判定材料がないためであると思われます。

 他の文字でも失敗する場合には、単に半角文字の文字コードは「アスキーだから」と決まってるせいでしょう。
    • good
    • 0
この回答へのお礼

文章が長くても同様にヌルでした。

おっしゃる通り原因はASCIIだからということのようです。判定結果にASCIIがないということを理解していませんでした。

大変助かりました。ありがとうございました。

お礼日時:2003/08/20 15:41

 それは出力がないのではありません。


 ヌル文字列が出力されているのです。ヌル文字列もれっきとした出力です。
 よって、

  if ( $code eq '' ) { .... }

 とでもやれば、文字コード判定に失敗したかどうかを知ることができます。

この回答への補足

回答ありがとうございます。
15日にレスをしたのですが失敗していたようです。
すみません。

getcodeにヌル出力があるということを知りませんでした。ありがとうございます。

当初の質問とずれがあるかもしれませんが「a」という
非常に単純な文字コード判定に失敗している
原因はなんでしょうか。Webを見て使用例にあるような「a」の判定ができない原因
を知りたいです。またその対策も知りたいです。

よろしくお願いいたします。

補足日時:2003/08/19 18:40
    • good
    • 0

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