argius note

プログラミング関連

VisualC++で任意の2バイトのShift_JIS文字を得るには

(タイトル続き: Visual Studio Express 2012 for Windows Desktopを入れてみた)

最近はVisualC++を触ることが多いです。でも経験が浅いので調べては書き、調べては書きのコーディングになってしまいます。
そして本当はC#をやりたいんですけどね。


最近のVisualC++は、文字列の内部表現がUTF-16のワイド文字になっていますね。そういえば昔はどうだったのか良く知りません。
こういう環境で、じゃあSJISの2バイトの文字からCStringを作るにはどうしたらいいの? というのが分からなかったので、調べました。
それを記録しておきます。


環境

最初は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になっています。



時代と逆行している感がありますが、これはこれで楽しい。