Version 11.03
Shift JIS
「前回は、ファイルパスからファイル名だけ取り出すっていうのをしてみま
した」
『と思ったら』
char ch[] = "C:\\Test\\ソフト.txt";
『が』
フト.txt
『になっちゃったのよねー。なんで?』
「これは、日本語の文字列が特殊だから。日本語を処理することを考える
と、実は文字列処理はとっても難しくなります」
『げげ!』
「でも、避けては通れない部分だから、まず最初に解決しておくことにしま
す」
『……そんなに難しい?』
「ややこしいんだよね、とにかく。苦手な人もかなりいるから、すぐわから
なくても大丈夫だからね」
『フツーのプログラマーも難しい分野なのね……』
「ではさっそくいきます。まず、さっきの文字列」
char ch[] = "C:\\Test\\ソフト.txt";
「これが、メモリ上にはどう並んでいるかメモリウィンドウで見てみます」
C : \ T e s t \ ソ フ ト . t x t \0
43 3A 5C 54 65 73 74 5C 83 5C 83 74 83 67 2E 74 78 74 00
『あれ? ソフトのところ……』
「そう、ふたつずつになってるでしょ。日本語の文字は」
ソ
「だったら」
83 5C
「っていう2文字分、つまり2バイトで表現してるんです」
『なんで2文字分?』
「まずはそこからだね。コンピューターはアメリカでできたものだから、文
字って言ったらもちろんアルファベット」
『そうだね』
「アルファベットって文字数少ないから1バイトで……1バイトで表現でき
る数ってやったっけ」
『えっと、数字だと、 char は -128 〜 127 だよね』
「 unsigned だと?」
『あー、えーっと、 0 〜 255 だったね、 Version 4.06 ( No.056 ) の時
に教わったけど』
「ってことは、1バイトだと256文字分表現できるってこと」
『 C が 0x43 、 : が 0x3A 、みたいにってことだよね』
「そうそう。でも256文字じゃ漢字は」
『あ! そっか、漢字なんてすんごく数あるもんね、入りきらないんだ』
「だから、日本語の文字は何バイトかくっつけて1文字を表現するしかなく
て、だから 0x83 0x5C でソを表すってなったわけ」
『なるほどねー』
「ただし!」
『ただし?』
「同じソでも」
0x83 0x5C
0x30 0xBD
0xA5 0xBD
0x25 0x3D
「って色々な数字で表されるんです」
『ど、どういうこと?』
「ソを表示するためには」
[「ソ」を表す数字]
↓
[変換表で数字を「ソ」に]
↓
[フォントの「ソ」を使って画面に表示]
「っていう段階を踏みます。ところが、真ん中の」
[変換表で数字を「ソ」に]
「がいっぱいあるんです」
『げ!』
「ある変換表は 0x83 0x5C をソに、またある変換表は 0x30 0xBD をソに変
換するっていう具合に。こういう変換表を【文字コード表】って言います」
『あー、インターネットしてるといっぱいあるよね、 EUC とかシフト JIS
とか』
「そうそう、それそれ。で、ウィンドウズでは Shift JIS っていう文字
コードが使われてます。だから」
[「ソ」を表す数字 0x83 0x5C ]
↓
[ Shift JIS 文字コード表で数字を「ソ」に]
↓
[フォントの「ソ」を使って画面に表示]
「っていう手順で表示されます。インターネットとかの他の文字コードの場
合は」
[ 他の文字コードの「ソ」を表す数字 0x30 0xBD ]
↓
[ 他の文字コードから Shift JIS に変換 ]
↓
[「ソ」を表す数字 0x83 0x5C ]
↓
[ Shift JIS 文字コード表で数字を「ソ」に]
↓
[フォントの「ソ」を使って画面に表示]
「って感じになります」
『一度 Shift JIS ってゆーのに変換してから表示するわけね。あれ? こ
の Shift JIS と、さっきあたしが言ったシフト JIS って同じもの?』
「そう、おなじもの。この Shift JIS =シフト JIS がウィンドウズで使わ
れてる日本語の文字コードだから、インターネットのとか考える必要がなけ
ればこの Shift JIS のことだけ考えればいいから」
『普通にプログラムしてればそれでいいってことよね』
「今のところはね」
『?』
「本当は Shift JIS じゃなくて MS932 とか Windows-31J とか言わなく
ちゃいけないんだけど……ん、今のは忘れて」
『むー、なんか気になる……』
「もういちどまとめると、ウィンドウズでは日本語の文字は Shift JIS
っていうのを使ってて、ソなら」
[「ソ」を表す数字 0x83 0x5C ]
↓
[ Shift JIS 文字コード表で数字を「ソ」に]
↓
[フォントの「ソ」を使って画面に表示]
「って感じに変換されます」
『うん、そこまでは大丈夫』
「じゃあ、前回の問題について。というより見ればわかると思うけど」
\ ソ
5C 83 5C
『あ! なに、 \ は 0x5C 、ソは 0x83 0x5C 、ってことはその2文字目が
\ と同じなんじゃない!』
「そうなんです。だから普通に \ を探していくと、このソの2バイト目と
一致しちゃうんです」
『……よーするに、それが \ じゃなくて、ソの2バイト目ってことがわか
ればいいんだ』
「そういうこと。この Shift JIS の1バイト目を【リードバイト】、2バ
イト目を【トレイルバイト】っていいます」
『りーどばいとととれいるばいと?』
「英語で書くと Lead Byte と Trail Byte 。 lead は〈先行する〉、
trail は〈ついていく〉って意味があります」
『よーするに前と後ろってことね』
「そゆこと」
『だから、 \ がみつかったときにそれがトレイルバイトかどうかが判れば
いい、ってことだよね。……でも、ピンポイントで見たら、わかんないよ
ね』
「そう、だから前後関係で見ないといけないんです」
『つまり、1バイト前がリードバイトかどうか調べるってこと?』
「まずはそう」
『まずは?』
「そう、まずは、ね。このリードバイトは、 0x81 〜 0x9F と
0xE0 〜 0xFC の間の値って決まってます」
『つまりその間かどうか見ればリードバイトかどうか』
「わからないんです」
『へっ?』
「なぜかっていうと、トレイルバイトは 0x40 〜 0x7E と 0x80 〜 0xFC の
間の値って決まってるからです」
『……重なってる?』
「そういうこと。プログラムで試してみようか」
void OutputLeadAndTrail()
{
char ch[] = "==";
TRACE( "%s\n%s\n", ch, &( ch[1] ) );
}
「==は Shift JIS 、つまりいわゆる全角文字で書いてください」
『えーっと、まず普通に表示して、次に……あ、1バイト先から出力してる
んだね』
「そう。で、これを実行すると」
==
=
『げ! なに、また同じ=?』
「 ch をメモリウィンドウで見ると」
= = \0
81 81 81 81 00
「ってなってるんです」
『……ってことは、ずらすと……』
= \0
81 81 81 00
『ってこと??? これじゃリードバイトかトレイルバイトかわかんない
じゃん!』
「というわけで次回に続く!」
/*
Preview Next Story!
*/
『あーもうなんだか混乱してきた!!』
「こういうのはメモリを見たり紙に書いたりするといいかも」
『今みたいに?』
「頭の中だけで考えると混乱するだけだから」
『へー』
「というわけで次回」
< Version 11.04 文字種の判定 >
『につづく!』
「だから、 VC って初心者向けかな」
『なんの話?』
「こっちの話」