UNICODE を用いた文字列操作

SPECIAL

SJIS や JIS などのようなマルチバイト文字列と違って、操作が容易な UNICODE。

慣れない UNICODE の文字列操作を紹介してみました。


UNICODE とは

UNICODE とは、英語/日本語を問わずすべての文字列を2バイトで表した文字コードシステムです。

SHIFT-JIS や EUC といった従来の日本語を表現できる文字コードでは、1バイトの ASCII コードと2バイトの漢字コードとが混ざっていたためになにかと不便な点が多かったのです。

 

具体的にどういった点が不便だったかというと、たとえば文字列の文字数を数える場合に従来のコード体系だと、文字列に割り当てられているメモリ領域をカウントしただけでは正確な文字数が獲得できないのです。

もしこのような方法で文字数をカウントすると、1文字の日本語でも2文字としてカウントされてしまいます。

 

それだけの問題ではなく、文字列から一文字ずつ取り出すような場合にも大きな問題が起こります。

取り出すときにはまずその文字が1バイトなのか2バイトなのかを判定する必要があります。そしてそれに応じた取り出しを行うわけなのですが、1バイトと2バイトは意外と大きな違いとなります。1バイトは 「文字」 ですが、2バイトは 「文字列」 なのです。

そこで1文字も 「文字列」 として扱えば、日本語/英語を問わず似たようなプログラムで処理を行うことができますが、ここでまた大きな壁にぶつかります。それは、C++ は文字列操作があまり得意ではないということです。

数値として扱える 「文字」 ならば簡単にできることでも、文字列だと意外と苦労したりします。ましてや、1バイト文字と2バイト文字が混在する文字コードでは・・・。

 

そこで注目すべきものが、UNICODE (ユニコード)です。

UNICODE は、Visual C++ 6.0 では unsigned short として定義されています。つまり、一文字が2バイトで構成されていることになります。

そしてここに UNICODE で定義された文字コードが保存されるのですが、UNICODE は多国語対応の定義がなされているためどの国の文字でも UNICODE としての1文字の枠に収まります。つまり1文字を操作する場合の処理が、従来の SHIFT-JIS などよりもはるかに簡単になります。

 

WCHAR ヘッダー中身

Visual C++ 6.0 で UNICODE を使用するためには WCHAR.H をインクルードする必要があります。これによって、wchar_t 型をはじめさまざまな UNICODE 用の関数などが利用できるようになります。

 

通常の文字を表す char の変わりのデータ型が wchar_t です。定義を見ると、unsigned short として宣言されていることがわかります。

UNICODE ではこれを配列にして文字列を表します。たとえば100文字未満の文字列を格納できる変数を宣言すると、wchar_t var [100] というようになります。

 

このヘッダにはほかにも文字列を操作するための関数が用意されています。

通常の char 型用の関数と同等の機能を持つものがそろえられていて、名称も非常に似ています。従来のものは str*** というように STR という文字から始まりましたが、ワイドキャラクタ版では wcs*** とうようになっています。

 

よく利用する関数を挙げてみますと、以下のようなものがあります。機能など詳しくは MSDN ライブラリなどを参照してください。

// 文字がアルファベットであるかを判定する関数と、

// 空白文字であるかどうかを判定する関数

int iswalpha ( wint_t )

int iswspace ( wint_t )

 

// 文字を大文字や小文字に変換

wchar_t towupper ( wchar_t )

wchar_t towlower ( wchar_t )

 

// ワイドキャラクタ用の printf 関数

int wprintf ( const wchar_t*, ... )

 

// 文字列の連結・検索・複製・大文字化・小文字化

wchar_t* wcscat ( wchar_t*, const wchar_t* )

wchar_t* wcschr ( const wchar_t*, wchar_t )

wchar_t* wcscpy ( wchar_t*, const wchar_t* )

wchar_t* wcslwr ( wchar_t* )

wchar_t* wcsupr ( wchar_t* )

 

// UNICODE 文字列の比較関数

int wcscmp ( const wchar_t*, const wchar_t* )

 

// 文字列の長さを調べる関数

size_t wcslen ( const wchar_t* )

 

またヘッダの内容とは少し異なりますが、文字リテラルが UNICODE であることを示すのに L というキーワードを使用します。たとえば、"*******" が UNICODE 文字列であることを示すには L"*******" というようにします。

また、UNICODE 文字を表すのにも L を用います。たとえば '?' を UNICODE で表すと L'?' となります。

 

文字列の基本操作

char 型の文字列操作がわかっていれば、wchar_t の文字列操作は簡単です。char 型で ASCII 文字列を操作する感覚で操作できるので、処理はさらに簡単になります。

次の変数宣言がなされているとしましょう。

// UNICODE 文字

wchar_t wc;

 

// UNICODE 文字列へのポインタ

wchar_t *pwc;

 

// 1000 文字未満の UNICODE 文字列

wchar_t wcs[1000];

 

このとき、wcs の 100 文字目を取り出すには次のようにします。

wc = wcs [99];

これで wc に 100 文字目の文字が取り出されます。注意する点は、通常の配列と同様に、配列は 0 から始まる通し番号がつけられているということくらいでしょうか。

さらに、この取り出した文字が '蛾' という文字であるかを調べる場合は

if ( wc == L'蛾' )

{

}

というようになります。

 

また UNICODE 文字は wchar_t 、つまり unsigned int (整数値)であるので switch 構文を用いて、

switch ( wc )

{

case L'A':

    break;

 

case L'あ':

    break;

}

というようなことも可能です。

 

また、wcs の先頭から1文字ずつ取り出していく場合を考えます。

まず、wcs の先頭のポインタを取り出すために、

pwc = wcs;

とします。

wc = *pwc;

とすれば、pwc の指すアドレスの値、すなわち wcs の先頭の文字が取得できます。

 

次に pwc に次の文字を指してもらうようにするのですが、これも非常に簡単です。pwc のポインタのアドレスをひとつ次にずらすだけです。

pwc++

これで完了です。

 

これらをふまえて、wcs の文字列を順番に取り出すプログラムの例をあげて、簡単ではありましたが UNICODE のお話はを終了です。

size_t i;

size_t len = wcslen ( wcs );

 

pwc = wcs;

for ( i = 0; i < len; i++ )

{

wc = *pwc;

pwc++;

}