ANSI ⇔ UNICODE の相互変換

プログラムは、文字列の処理に ANSI と UNICODE の二つを使用しています。今回は短いながらも、 ANSI と UNICODE との相互変換について説明します。



ANSI と UNICODE の違い

まず一番に、 ANSI は(最低) 1 バイトで文字を表現し、 UNICODE は(最低) 2 バイトで 文字を表現するところが違います。

半角英数字のみを使用する場合、どちらの形式でも問題ありませんが、 ANSI の方がメモリ使用量が少なくすみます。

しかし、日本語など、 1 バイトだけで表現できない言語の場合、 ANSI では 2 バイトで 1 字を表現します。このとき、 Windows 等、パスに使われる文字「\」が 2 バイトで表現している文字の 2 バイト目に表れる場合があります(「表示」など)。

ANSI ではこのような問題があり、日本語を使用する場合は UNICODE が適しています。

しかし、コンソール画面への出力など、 ANSI 文字列でしか対応していない関数などがあり、 UNICODE から ANSI に、または ANSI から UNICODE に変換する必要があります。


変換処理について

printf関数などの書式出力関数で容易に ANSI と UNICODE の相互変換が出来ます。


// コンソールに出力
printf("%Sn",L"UNICODE string.");

// ANSI 文字列バッファに出力
sprintf(ansibuffer,"%S",L"wide text");

// UNICODE 文字列バッファに出力
swprintf(widebuffer,L"%S",L"single text");


変換時の問題

上記の方法では正しく変換されますが、日本語を変換する場合には注意が必要です。


// コンソールに出力
printf("%Sn",L"UNICODE 文字列.");

// ANSI 文字列バッファに出力
sprintf(ansibuffer,"%S",L"wide テキスト");

// UNICODE 文字列バッファに出力
swprintf(widebuffer,L"%S",L"single テキスト");

これをそのまま実行すると、日本語が表示されないばかりか、それ以降の文字列も表示されなくなってしまいます。

この問題を解消するためには、3つあります。一つ目はsetlocale関数を使用します。

この関数は、 C 標準ライブラリ内での文字列の扱い方を変更することが出来るものです。

デフォルトではsetlocale(LC_ALL,"C")という状態になっています。

日本語で文字列を処理したい場合は、setlocale(LC_ALL,"jpn")として呼び出します。

これをプログラムの開始時に実行しておけば、以降問題なく日本語が変換されます。


#include <stdio.h>
#include <locale.h>
// setlocale 関数を使用する場合は"locale.h"が必要。

int main(){
char ansibuffer[32];
wchar_t widebuffer[32];
// 日本語用に処理を行わせる
setlocale(LC_ALL,"jpn");

// コンソールに出力
printf("%Sn",L"UNICODE 文字列.");

// ANSI 文字列バッファに出力
sprintf(ansibuffer,"%S",L"wide テキスト");

// UNICODE 文字列バッファに出力
swprintf(widebuffer,L"%S",L"single テキスト");

printf("%sn",ansibuffer); // コンソールに出力
printf("%Sn",widebuffer); // コンソールに出力
}

二つ目は、#pragma setlocale("jpn")と、コードの先頭に記述することです。

こちらの場合は上記のようにプログラムとしてでなく、デフォルトでロケールを指定するため、余計なコードが省かれます。

しかし、多言語対応のアプリケーションを製作する場合は向きません。

ちなみに、#pragma setlocale("jpn")と同等の記述を次の方法で行うこともできます。


static const char* g_locale = setlocale(LC_ALL,"jpn");


追記

#pragma setlocale("jpn")コードはコンパイラに依存するため、コンパイラによっては有効にならない場合があります。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

This blog is kept spam free by WP-SpamFree.