ネタもと:文字列の全角半角判定
某所で、てか、普通の「使う人」は文字コードなんて興味ないだろう。
と、コメントがあったので。
確かに、興味はないでしょうね。ただし、「どのように表示/印字されるか」には、執着と言っていいほどの興味があると思います。そして、その執着を満足するために、開発者は知っていなければならないのではなかろうか、と思うのです。
元々、全角/半角という言葉は、格子状にしか表示できないところで、表示するために格子のどれくらいを使用するか、を表していました。「あ」のような文字を表示するために格子を1つ使うとすると、「A」のような文字を表示するためには、格子を左右に2つに分けた半分しか使用しません。ここから、「あ」のような文字を「全角」と呼び、「A」のような文字を「半角」と呼びました。
この、表示幅を表していた言葉をややこしくするのが、「バイト数」という考え方です。Shift_JIS コードにおいて、「あ」のような文字は2バイト、「A」のような文字は1バイトで表現可能でした。これが、表示上の「全角」「半角」と重なって、いつの間にか Shift_JIS の2バイト文字を「全角文字」と呼ぶようになっていました。つまり、表示上の幅を表していて言葉が、メモリ上の幅に変わってしまったのです。
ここに、さらにややこしさを追加するのが、他の文字コードです。Mac がどのような文字コードを使っているのかは知りません。私が使っていたのは UNIX で、こいつでは EUC_JP というコードを使っていました。EUC_JP では、Shift_JIS での 0xA1 ~ 0xDF にあたるコード、いわゆる「半角カタカナ」が、2バイトで表現されます。つまり、半角の幅で全角のバイト数を持つ文字のあるコードなのです。
また、JIS コード。最近のは違うようですが、私が知っている頃の JIS コードは Kanji In コードと Kanji Out コードがありました。つまり、KI コードから KO コードまでは漢字だよ、と。もちろん、1文字1文字を KI, KO コードで挟むこともできます。そうすると、メモリ上の幅はいくらでも増えます。
もう一つ、Unicode。Unicode には、UTF-8 とか UTF-16 とかありますが、この8とか16は、1文字を表現するために必要な、最低のビット数です。UTF-8 は ASCII コードと互換があり、この範囲の文字は8ビットで表現できます。つまり、UTF-8 では、表示幅とバイト数が一致していると言えそうです。いいえ。3バイトや4バイトで表現する文字があります。こういうものは、「3倍角」「4倍角」と言いますか?UTF-16 では8ビットで表現することはありませんが、この場合はどうなります?というか。バイト数で「全角」「半角」と言っていたのが、いつの間にか表示幅に変わっていますよ?
さらにややこしくしましょう。今でも「あ」は、「A」の2倍の幅を使って描かれるの?実験。
あい
AAい
IIい
プロポーショナル フォントを使って書いてみました。「い」の位置がずれてますよね。「A」と「I」は、同じ「半角」のはずなのに、これも位置が違います。つまり、プロポーショナル フォントを使うと、表示幅でも「全角」「半角」ではなくなってしまいます。
Windows の世界で「全角/半角」というと、たいていの場合は「Shift_JIS コードで、2バイト文字と1バイト文字」を表していると考えていいでしょう。しかし、その考え方が、なぜ必要なのでしょう?
.NET アセンブリの中では…System.String クラスが扱うのは UTF-16 です。System.Char 構造体も、2バイトです。これは、Common Language Infrastructure の話なので、Windows に限らず、どの OS に移植されてもそのように作られていることが期待できます。
データベースも、昔はバイト単位で varchar の幅を指定していましたが、今では文字数単位で幅を指定できます。また、Unicode から他のコードへ変換すると、「Wave-Dash 問題」のようなことが発生するため、同じ Unicode で構成する方がいいでしょう。そうすると、「データベースではバイト数で指定しているので、バイト数で制限したい」という問題はなくなります。というか、なくさなければならないと言えるでしょう。
表示にしても、プロポーショナル フォントを使用すると、1文字の幅は一定していないため、「漢字に2文字分の読み仮名」などということが馬鹿げてきます。少なくとも確定申告の用紙は漢字2文字に付きふりがな3文字なので、フリガナが半角である必要がありません。「表示の幅を狭めるため」ということでも、フォント サイズやストレッチなどで調整できます。そうすると、表示幅の面でも全角だの半角だのいう必要はなさそうです。
そんなわけで、「全角/半角」という言葉が出てきたら、「何をもって全角というの?」と聞きたい。そして、それを通り越して、「そもそも、なんでそんな判断をしなければならないの?」と聞きたいのでした。
もちろん、URL や メールアドレスは、ASCII 7bit コードで書かれなければなりません。このことから、「半角のみ」を判定したい?いえいえ。こいつを判定したいなら、「半角のみ」ではなく、「ASCII 7ビットの可視文字」であるはずです。つまり、Shift_JIS の「半角カタカナ」が入ってはいけませんし、制御コードも入ってはいけません。え?「制御コードなんて、キーボードから入力できないだろ」ですって?そんなことはありませんよ。バックスラッシュ(円マーク)に続けて入力すると、制御コードと判断されるかもしれませんよ。あるアプリケーションのとある設定項目で、「円マーク」は入力できない、となっていました。確かに、「\\」とか「value\」は入力できないのですが、「\t」は入力できました。制御コードのタブ文字と判断されてしまったからです。
つまり、「全角/半角」という区別では、本当にしたいことが、適切に表現できていない場合があるです。
「全角/半角と表現したことが、本当は何がしたいのか」、「本当にその判別をしなければならないのか。あるいは、判別しないとどんな不都合があるのか」という2点。もう一度、考えていただきたいと思います。
余談:ところで、ここまで「バイト」という言葉を多用していますが、「バイト」も長さが不定であると、ご存じでした?C 言語の int のビット数と同じで、その処理系で一番扱うのが簡単な長さが、バイトです。でも、8ビットで1バイト、というのが通例になっています。ここでも、8ビットを1バイトとしました。
投稿日時 : 2007年8月20日 22:23