WCHARって何ですか? 文字列の変換

投稿日:

これまでchar型でしか文字列を扱ったことがなかったので、DirectXTexの画像ファイル読み込みでLPCWSTR(const WCHAR*)という型を見ても特に気にせず、L”文字列”と書けばいいやぐらいしか考えてませんでした。しかし、リテラルではなくconst char*のファイルパスを渡そうとするとコンパイルエラー、どうやら簡単に型のキャストで済むようなものではないらしい。

WCHAR( wchar_t )とは
Wikipedia ワイド文字
その他、ググって調べてみた。

文字列の内部表現が違うので、テキストファイル(char)から取得した文字列をそのままでは使えず、変換する必要があるようです。「wchar_t = 1文字」とは限らないので取扱いに注意(なんか中途半端な文字型のような気がする)。
C++11ではchar16_tやchar32_tという文字型があるので、今後慎重に文字列型の扱い方を考えていきたい。

文字列の変換方法を調べていくつか作成してみました。

mbstowcsを使った変換

#include <stdlib.h>

// 日本語を使うには
// setlocale( LC_ALL, "Japanese" );

bool to_wstring(const std::string& str, std::wstring& wstr)
{
	 size_t size;
	 if( 0!= mbstowcs_s(&size, NULL, 0, str.c_str(), 0) ){
		 return false;
	 }
	 std::vector<wchar_t> wch(size);
	 if( 0!= mbstowcs_s(&size, wch.data(), wch.size(), str.c_str(), str.length()) ){
		return false;
	 }
	 wstr = wch.data();
	 return true;
}

文字列の変換にはmbstowcs_s(mbstowcsだと警告)を使用します。最初のmbstowcs_sにNULLを渡すことで変換後のサイズを取得し、必要なメモリを確保してmbstowcs_sで変換。wstringはwchar_tの文字列クラス。

std::codecvt(C++11)を使った変換

#include <locale>

bool to_wstring(const std::string& str, std::wstring& wstr)
{
	std::locale loc("Japanese");//日本語

	// code_conv char->wchar_tの変換クラス
	typedef std::codecvt<wchar_t, char, std::mbstate_t> code_conv;

	// 変換するファセットがあるか
	if( !std::has_facet<code_conv>(loc) ){ return false;}

	// 日本語でのchar->wchar_t変換クラスのインスタンス取得
	// ライブラリが用意しているインスタンス(ファセット)を使う
	const code_conv& conv = std::use_facet<code_conv>(loc);

	//変換後のサイズ
	const size_t str_size = str.length()+1;//char文字列長さ(\0含む)
	std::mbstate_t state_len = {0};
	const char* ch = str.c_str();
	size_t size = conv.length( state_len, ch, ch+str_size, str_size );
	
	// 変換
	std::vector<wchar_t> wch(str_size);
	const char* ch_next = 0;
	wchar_t* wch_next = 0;
	std::mbstate_t state = {0};
	if( std::codecvt_base::ok
		!= conv.in(state, ch, ch+str.size(), ch_next,
				wch.data(), wch.data() + wch.size(), wch_next) )
	{
		return false;
	}
	
	wstr = wch.data();
	return true;
}

std::codecvtというクラスを使って変換を行います。ただ、使い方が少し変わっていて、codecvt conv;とせずにstd::use_facetという関数でライブラリが用意したインスタンス(ファセット)の参照を取得して使用します。1つのインスタンスを複数のプログラムで共有するため変換処理に内部状態を保持する状態クラス(ここではstd::mbstate_t)を渡すようになっています。

コメントを残す

メールアドレスが公開されることはありません。

認証:数字を入力してください(必須) * Time limit is exhausted. Please reload CAPTCHA.