mbstowcs, wcstombs
http://d.hatena.ne.jp/janus_wel/20100315/1268654296 の C 標準関数版。
// nwconv_c.hpp #ifndef NWCONV_C_HPP #define NWCONV_C_HPP #include <string> #include <vector> #include <cstdlib> #include "../../header/wexcept.hpp" #ifdef _MSC_VER # include <errno.h> #endif namespace util { namespace string { std::wstring ntow(const std::string& src) { #ifdef _MSC_VER const std::size_t src_size = src.length() + 1; const std::size_t dst_size = src_size; std::size_t converted; std::vector<wchar_t> dst_vctr(dst_size + 1); wchar_t* dst = &dst_vctr[0]; if (mbstowcs_s(&converted, dst, dst_size, src.c_str(), _TRUNCATE) != EINVAL) { return std::wstring(dst); } #else const std::size_t size = std::mbstowcs(NULL, src.c_str(), 0); std::vector<wchar_t> dst_vctr(size + 1); wchar_t* dst = &dst_vctr[0]; if (std::mbstowcs(dst, src.c_str(), size) == size) { return std::wstring(dst); } #endif std::string errmsg("failed: "); errmsg.append(src); throw std::logic_error(errmsg); } std::string wton(const std::wstring& src) { #ifdef _MSC_VER const std::size_t src_size = src.length() + 1; const std::size_t dst_size = src_size * MB_CUR_MAX; std::size_t converted; std::vector<char> dst_vctr(dst_size + 1); char* dst = &dst_vctr[0]; if (wcstombs_s(&converted, dst, dst_size, src.c_str(), _TRUNCATE) != EINVAL) { return std::string(dst); } #else std::size_t size = std::wcstombs(NULL, src.c_str(), 0); std::vector<char> dst_vctr(size + 1); char* dst = &dst_vctr[0]; if (std::wcstombs(dst, src.c_str(), size) == size) { return std::string(dst); } #endif std::wstring errmsg(L"failed: "); errmsg.append(src); throw util::exception::wlogic_error(errmsg); } } } #endif // NWCONV_C_HPP
と定義しておいて以下のように使う。同様に command line で指定された文字列の最初の一文字を落として表示する例。
// main.cpp #include <string> #include <locale> #include <iostream> #include <stdexcept> #include "wexcept.hpp" #include "nwconv_c.hpp" void initialize_locale(void); int main(const int argc, const char* const argv[]) { initialize_locale(); try { for (int i = 0; i < argc; ++i) { std::wstring arg = util::string::ntow(argv[i]); arg.erase(0, 1); std::cout << util::string::wton(arg) << std::endl; } } catch (const std::exception& ex) { std::cerr << ex.what() << std::endl; } catch (const util::exception::wexception& ex) { std::wcerr << ex.what() << std::endl; } return 0; } void initialize_locale(void) { std::locale system_locale(""); std::locale::global(system_locale); std::cin.imbue(system_locale); std::cout.imbue(system_locale); std::cerr.imbue(system_locale); std::wcin.imbue(system_locale); std::wcout.imbue(system_locale); std::wcerr.imbue(system_locale); }
こっちは global locale に system locale を設定してやらないといけない。上記の initialize_locale() 関数のようについでに既存の stream object に対して imbue をしておくと何かと都合がいいかも。
こっちも VC++ 2008 Express Edition と andLinux g++ 4.3.3 で動作確認してる。あとこっちだと VC++ & cmd.exe で wton で変換 & cout で出力という手順を踏まなくても wcout を使ってそのまま出力できる。 VC++ の locale の取り扱いがおかしいのかな。