ページ 1 / 1
文字変換クラスを作成したのですが
Posted: 2012年12月22日(土) 13:13
by gran
プログラム勉強中のgranです。よろしくお願いします。
以下のようなint型をLPCWSTR型へ変換するファイルを作成しました。
コード:
//---------------------------------------------------------------------
// File: trans.h
// 文字変換クラス
//---------------------------------------------------------------------
#ifndef INCLUDED_TRANS
#define INCLUDED_TRANS
#pragma once
#include <sstream>
//namespace trans{
// template<class T> T toWstring(int num);
//}
template<class T>
T toWstring(int num)
{
std::wstringstream wss;
wss << num;
std::wstring wstr = wss.str();
return wstr.c_str();
}
#endif
しかしこのコードを
コード:
LPCWSTR Lifepoint = toWstring( LifePoint );
のように使用し、表示すると文字化けしてしまいました。
クラス化する前の
コード:
std::wstringstream wss;
wss << LifePoint; // ライフポイント格納
std::wstring wstr = wss.str();
LPCWSTR ws_Lifepoint = wstr.c_str();
このようなコードなら文字化けせずに数字が表示されます。
なぜ文字化けしてしまうのでしょうか。原因が調べても
わかりませんでした。わかる方お願いします。
あとコメントアウトしてあるnamespaceなのですが
toWstring( LifePoint );
を
trans::toWstring( LifePoint );
のようにして使用したいのですがうまくいかず読み取ってくれません。
何が悪いのかこちらもお願いします。
Re: 訂正
Posted: 2012年12月22日(土) 13:18
by gran
コード:
template<class T>
std::wstring toWstring(T val)
{
std::wstringstream wss;
wss << val;
std::wstring wstr = wss.str();
return wstr.c_str();
}
最初のプログラムミスに気付いたので訂正・・
Re: 文字変換クラスを作成したのですが
Posted: 2012年12月22日(土) 13:38
by nil
呼び出し側は
toWstring<int>( val );
であるかと思います。
名前空間を使う場合は関数の本体も名前空間内に書かねばなりません。
ひとつ気になったのですが、
wstringを返す関数なのに、wstring::c_str()を呼び出しているのはなぜなんでしょうか。
そのままwss.str()を返せばいいだけでは?
Re: 文字変換クラスを作成したのですが
Posted: 2012年12月22日(土) 13:50
by gran
返信ありがとうございます。
LPCWSTR ws_Lifepoint = toWstring<int>( LifePoint );
と記述してみましたがエラーコードでした。
名前空間の宣言と中身は一緒に書かなければならないのですね。
ありがとうございます。
確かにそのままwss.str()を返しても結果は同じです。
wstring::c_str()を返せば末尾に '\0' が付与され
C言語の形式とも一致するというものです。
しかしまだ文字化けしたままです。
わかる方お願いします。
Re: 文字変換クラスを作成したのですが
Posted: 2012年12月22日(土) 15:18
by sq
wstrはデストラクタで破壊されています。
そのためwstr.c_str()の指す先の中身は保証されません。
Re: 文字変換クラスを作成したのですが
Posted: 2012年12月22日(土) 15:29
by h2so5
>sqさん
その前にstd::wstringのコンストラクタが呼ばれて文字列がコピーされるはずです。
Re: 文字変換クラスを作成したのですが
Posted: 2012年12月22日(土) 15:37
by nil
>wstring::c_str()を返せば末尾に '\0' が付与され
>C言語の形式とも一致するというものです。
c_str()によってconst wchar_t*が返されますが、
返り値がwstringであるため、暗黙のキャスト=wstring型のコンストラクタが呼ばれます。
wstring型のコンストラクタ内部でnewが呼ばれるため、処理的に無駄の多いものと思われます。
>wstrはデストラクタで破壊されています。
>そのためwstr.c_str()の指す先の中身は保証されません。
上記した通り、返り値はconst wchar_t*ではなくwstringのため、
安全性は保証されるものだと思います。
エラーが出たのならばエラーコードを書き込んでくだされば対処の方法が考えやすくなるかと思います。
念の為に確認しますが、ロケールの設定はなさっていますね?
Re: 文字変換クラスを作成したのですが
Posted: 2012年12月22日(土) 15:47
by sq
すみません。最初のコード見て訂正されたコードを見逃してました。
ただ文字化けは多分最初のコードが原因かなと思います。
次のコードはどちらも100を出力します。
コード:
#include <iostream>
#include <sstream>
#include <windows.h>
template<class T>
std::wstring toWstring(T val)
{
std::wstringstream wss;
wss << val;
return = wss.str();
}
int main()
{
std::wstring ws1 = toWstring(100);
std::wcout << ws1 << "\n";
std::wstring ws2 = toWstring(100);
LPCWSTR pWstr = ws2.c_str();
std::wcout << pWstr << "\n";
}
Re: 文字変換クラスを作成したのですが
Posted: 2012年12月22日(土) 15:49
by gran
3名の方返信ありがとうございます。
まず現在のコードはこのような感じにしました。
コード:
//---------------------------------------------------------------------
// File: trans.h
// 文字変換クラス
//---------------------------------------------------------------------
#ifndef INCLUDED_TRANS
#define INCLUDED_TRANS
#pragma once
#include <Windows.h>
#include <sstream>
template<class T>
LPCWSTR toWstring(T val)
{
std::wstringstream wss;
wss << val;
std::wstring wstr = wss.str();
return wstr.c_str();
}
#endif
返り値を素直にLPCWSTRとしました。
windows.hをインクルードするのがなんとなく嫌だったのです。
エラーは現在出ておらず、ロケールの設定は開発環境の方で
行っています。
現在もまだ文字化けしたままです。
よろしくお願いします。
Re: 文字変換クラスを作成したのですが
Posted: 2012年12月22日(土) 15:59
by h2so5
>granさん
そのコードだとsqさんが指摘した通りの問題が発生してしまいます。
Re: 文字変換クラスを作成したのですが
Posted: 2012年12月22日(土) 16:24
by gran
デストラクタが呼ばれているということでしょうか。
コード:
//---------------------------------------------------------------------
// File: trans.h
// 文字変換クラス
//---------------------------------------------------------------------
#ifndef INCLUDED_TRANS
#define INCLUDED_TRANS
#pragma once
#include <Windows.h>
#include <sstream>
//namespace trans{
// template<class T> T toWstring(int num);
//}
template<class T>
LPCWSTR toWstring(T val)
{
std::wstringstream wss;
wss << val;
std::wstring wstr = wss.str();
LPCWSTR p_wstr = wstr.c_str();
return p_wstr;
}
#endif
こうしないと中身が保障されないということですか?
Re: 文字変換クラスを作成したのですが
Posted: 2012年12月22日(土) 18:00
by nil
それでも同じです
p_wstrの中身はwstrが持っているのですから。
[修正]
p_wstrの指す値はwstr.c_str()と同値ですから。
Re: 文字変換クラスを作成したのですが
Posted: 2012年12月22日(土) 18:45
by gran
値がおかしいということはわかりましたが
sqさんが記載していたコードを試してみましたが
変な値が入ったままのようです。
あと私はこんな書き方は知りませんでしたが
return = wss.str();
はエラーコードとなりました。
構文エラー"="だそうです。
依然問題は解決していません、よろしくお願いします。
Re: 文字変換クラスを作成したのですが
Posted: 2012年12月22日(土) 19:13
by softya(ソフト屋)
戻り値としてポインタを返すのは無理だと思ってもらった方が良いです。
なんども書かれているように関数を抜けるとクラスのデストラクトとともに変数のメモリは解放されるのです。
※ 出来ないことはないですが、そうするとメモリ解放の管理をする必要が出てきます。
そういう事で、wstrのまま返すのが良いと思います。
Re: 文字変換クラスを作成したのですが
Posted: 2012年12月22日(土) 19:30
by gran
softya(ソフト屋)さん返信ありがとうございました。
sqさんの言いたいことがようやく理解できました。
ポインタを返していたことに言われるまで
気付きませんでした。
以上のことを踏まえて変換処理をした結果
うまくいきました。
返信してくださったみなさま、本当にありがとうございました。