ascii()にCP932外の文字を渡したときの挙No.08494
でるもんたいいじま さん 17/03/22 07:45
 
でるもんた・いいじまです。

いま書いているマクロの関係で、文字列変数の中にCP932の範囲外の文字が
入っていないかチェックする動作を実装しようとしているのですが、
ascii() 関数の挙動について質問があります。

---- サンプルコード ここから ----
// -*- shift_jis -*-
$BOM = "\uFEFF";  // U+FEFF BYTE ORDER MARK
message sprintf("ascii(BOM) = 0x%04X", ascii($BOM));

$HeavyHeart = "\u2764"; // U+2764 HEAVY BLACK HEART
message sprintf("ascii(HEART) = 0x%04X", ascii($HeavyHeart));

$ZERO = "\x00"; // ASCIIZ-String Terminator
message sprintf("ascii('\\0') = 0x%04X", ascii($ZERO));
---- サンプルコード ここまで ----

このマクロを実際に動かしてみると、
  ascii(BOM) = 0x003F
  ascii(HEART) = 0x8148
  ascii('\0') = 0x0000
と表示されます。0x003Fは半角クエスチョンマーク、0x8148は全角
クエスチョンマークのコードです。codeキーワードと同様に3つとも
0が返ってくるかと思ったので、ちょっと驚いています。

これはサイトー企画さんのほうで想定されていた仕様でしょうか?
それとも、このへんの処理は Win32 APIの WideCharToMultiByte()
あたりに丸投げしていてそちらの仕様なので、ということになるん
でしょうか?

とりあえず私の目標は、「あらゆる文字が入っている可能性のある
文字列」を「非Unicodeアプリがファイル名として使用できる文字列」
に変換することなので、ascii() が何を返そうが困らないのですが、
ちょっと気になったので質問させていただきました。

#私の場合、変数の中身を1文字ずつ ascii() に渡して、ファイル名に
#使えないコードが返ってきたらその部分を代替の文字に差し替える、
#という処理を入念に実装するだけです。元の文字列は編集中の文面から
#採取するので、コントロールコードなども考慮する必要があります。

[ ]
RE:08494 ascii()にCP932外の文字を渡したNo.08495
秀丸担当 さん 17/03/22 09:53
 

ascii()で"?"や"?"になるのは、ソースを確認してみたところでは
WideCharToMultiByte()に丸投げというわけではなく、わざわざそのようにして
いました。
そういう動作であることをヘルプに追記したいと思います。

かなり昔のことですが、Unicodeの扱いが無かったころから全角半角を区別して
整形を行うマクロがあって、その配慮があったためだと思います。
変換できない文字を調べる方法としては、code文やfindspecial文で検索する方
法がありますが、いったん本文に挿入したりする必要があり、文字列変数から直
接調べることはできないです。
ascii()の互換性は維持するとして、追加のパラメータで?に変換するか0にする
かを選べたらいいと思います。そういう方向で検討します。

[ ]