VisualC++で任意の2バイトのShift_JIS文字を得るには
(タイトル続き: Visual Studio Express 2012 for Windows Desktopを入れてみた)
最近はVisualC++を触ることが多いです。でも経験が浅いので調べては書き、調べては書きのコーディングになってしまいます。
そして本当はC#をやりたいんですけどね。
最近のVisualC++は、文字列の内部表現がUTF-16のワイド文字になっていますね。そういえば昔はどうだったのか良く知りません。
こういう環境で、じゃあSJISの2バイトの文字からCStringを作るにはどうしたらいいの? というのが分からなかったので、調べました。
それを記録しておきます。
環境
- Windows 7 Professional
- Visual Studio Express 2012 for Windows Desktop
最初はVisual Studio 2010 Professionalで確認しています。
Visual Studio Express
これを書いている環境にはVisualStudio入っていないので、入れました。
従来のデスクトップ版はたぶんこれでしょう。
(アンカーがfor Windows Desktopについています。)
最初の起動で「登録されていません」というダイアログが出ますが、無視して起動します。
30日過ぎたら登録すれば無料で継続利用できます。
サンプルプログラム
Win32コンソールアプリケーションで作ります。
メインのcppに貼り付けてビルドし、デバッグ実行します。
#include "stdafx.h" #include <windows.h> LPWSTR CreateStringFromSJISCode( BYTE hi, BYTE lo ) { char sjisChars[] = { hi, lo, '\0' }; wchar_t utf16Chars[] = { '\0', '\0', '\0' }; MultiByteToWideChar( CP_ACP, 0, sjisChars, 2, utf16Chars, 2 ); LPWSTR s = new wchar_t[2]; s[1] = '\0'; if ( utf16Chars[1] == '\0' ) s[0] = utf16Chars[0]; else s[0] = '\0'; return s; } int _tmain(int argc, _TCHAR* argv[]) { LPWSTR s = CreateStringFromSJISCode( 0x95, 0x6A ); OutputDebugString(s); // => 彬 delete[] s; // いちおう return 0; }
処理のポイント
ExpressだとCStringが使えない("atlstr.h"とか付属していない)ので、CString無しバージョン。
MultiByteToWideCharについては、MSDNを参照。
int MultiByteToWideChar( UINT CodePage, // コードページ DWORD dwFlags, // 文字の種類を指定するフラグ LPCSTR lpMultiByteStr, // マップ元文字列のアドレス int cchMultiByte, // マップ元文字列のバイト数 LPWSTR lpWideCharStr, // マップ先ワイド文字列を入れるバッファのアドレス int cchWideChar // バッファのサイズ );
CP_ACPはこの場合"ANSIコードページ"です。LPCSTRにはSJISバイト配列として(char*)を、LPWSTRにはワイド文字列の配列として(wchar_t*)を指定しています。
変換した結果をいったんutf16Charsに入れ、utf16Chars[1]がNUL文字でない場合は、ワイド文字1文字に変換できていないので、失敗として空文字列を返しています。コードを簡潔にするために、空文字列はサイズが2になっています。
時代と逆行している感がありますが、これはこれで楽しい。