asciiNo.03044
bouz さん 09/08/10 12:41
 
$s="\xd0\xe0\xf0";
$t1=leftstr($s,1);
$t2=midstr($s,1,1);
$t3=midstr($s,2,1);
message hex(ascii($t1))+","+hex(ascii($t2))+","+hex(ascii($t3));

を実行すると、
D0,E000,F000
と表示されますが、これはいったいどういういうことでしょうか?

[ ]
RE:03044 asciiNo.03053
秀丸担当 さん 09/08/10 16:46
 

insert $s;
としてみると分かりやすいですが、\xd0は半角カタカナで、\xe0\xf0は1文字の
漢字になっています。
\xe0(または\xf0)の場合は漢字の1文字目として認識されて、続く2バイト目
も含んだ2バイトのコードが1文字ぶんのコードとして解釈されていました。
midstrで切った場合は2バイト目が終端のNULL(\x00)になってしまうので、結果
的にE000となってしまうようです。
とりあえず、& 0xff した値が 0 であれば上位8ビットを使うというようにすると
回避できるのではないかと思います。

(例)
$s = "\xe0";
call ASCII $s;
message hex(##return);
endmacro;

ASCII:
#ret = ascii($$1);
if( (#ret & 0xff) == 0 ) #ret = #ret / 256;
return #ret;

2バイト目が無い場合のasciiは1バイト目だけを返すようにしたほうがいいかも
しれません。
ずっと以前からこの動作だったため互換性の心配もあるので、慎重に考えたいと
思います。

[ ]
RE:03053 asciiNo.03061
bouz さん 09/08/11 11:48
 
どうしてなのか理由というか経緯は大体わかりました。
興味があったのでもう少し調べてみました。asciiが2バイト返すということなので、
今度は本来のE000を横着して読もうとして、
$s="\xe0\x00\xe0";
$t=leftstr($s,2);
message hex(ascii($t));
とやると、
結果は
E0E0
となってしまいした。0の場合はとばす特例になっているようです。
E001の場合はうまくいくので、本来このような(E0とE000を区別できる状態)目的に使
用する関数ではないということがだんだんわかってきました。asciiが少し奇異な感
じもしますが、この組み合わせではちょっと簡単にはいかない、ということですね。

[ ]
RE:03061 asciiNo.03063
アルビレオ さん 09/08/11 13:02
 
ユーザーのアルビレオです。

>asciiが少し奇異な感じもしますが、
>この組み合わせではちょっと簡単にはいかない、ということですね。

そんなことは承知の上で試されたのかもしれませんが、そもそもマルチバイト文
字列を扱うために作られた仕組みなので、バイナリをまともに扱えることを期待
する時点で無理があると思います。

Perlのようなバイナリも扱える処理系を使うか、どうしても秀丸にこだわるのな


$s="\xd0\xe0\xf0";
#t=dllfunc("subbin",$s,2);//文字列のうち1バイト分を整数として返す
message hex(#t);

のように、外部DLLとしてバイナリ操作用の自作関数を追加するのが現実的なと
ころではないでしょうか。

[ ]