文字変換クラスを作成したのですが

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
gran

文字変換クラスを作成したのですが

#1

投稿記事 by gran » 11年前

プログラム勉強中の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 );
のようにして使用したいのですがうまくいかず読み取ってくれません。
何が悪いのかこちらもお願いします。

gran

Re: 訂正

#2

投稿記事 by gran » 11年前

コード:

template<class T>
std::wstring toWstring(T val)
{
	std::wstringstream wss;
	wss << val;
	std::wstring wstr = wss.str();

	return wstr.c_str();
}
最初のプログラムミスに気付いたので訂正・・

nil
記事: 428
登録日時: 12年前

Re: 文字変換クラスを作成したのですが

#3

投稿記事 by nil » 11年前

呼び出し側は
toWstring<int>( val );
であるかと思います。

名前空間を使う場合は関数の本体も名前空間内に書かねばなりません。

ひとつ気になったのですが、
wstringを返す関数なのに、wstring::c_str()を呼び出しているのはなぜなんでしょうか。
そのままwss.str()を返せばいいだけでは?

gran

Re: 文字変換クラスを作成したのですが

#4

投稿記事 by gran » 11年前

返信ありがとうございます。

LPCWSTR ws_Lifepoint = toWstring<int>( LifePoint );
と記述してみましたがエラーコードでした。

名前空間の宣言と中身は一緒に書かなければならないのですね。
ありがとうございます。

確かにそのままwss.str()を返しても結果は同じです。
wstring::c_str()を返せば末尾に '\0' が付与され
C言語の形式とも一致するというものです。

しかしまだ文字化けしたままです。
わかる方お願いします。

sq

Re: 文字変換クラスを作成したのですが

#5

投稿記事 by sq » 11年前

wstrはデストラクタで破壊されています。
そのためwstr.c_str()の指す先の中身は保証されません。

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: 文字変換クラスを作成したのですが

#6

投稿記事 by h2so5 » 11年前

>sqさん
その前にstd::wstringのコンストラクタが呼ばれて文字列がコピーされるはずです。

nil
記事: 428
登録日時: 12年前

Re: 文字変換クラスを作成したのですが

#7

投稿記事 by nil » 11年前

>wstring::c_str()を返せば末尾に '\0' が付与され
>C言語の形式とも一致するというものです。
c_str()によってconst wchar_t*が返されますが、
返り値がwstringであるため、暗黙のキャスト=wstring型のコンストラクタが呼ばれます。
wstring型のコンストラクタ内部でnewが呼ばれるため、処理的に無駄の多いものと思われます。

>wstrはデストラクタで破壊されています。
>そのためwstr.c_str()の指す先の中身は保証されません。
上記した通り、返り値はconst wchar_t*ではなくwstringのため、
安全性は保証されるものだと思います。

エラーが出たのならばエラーコードを書き込んでくだされば対処の方法が考えやすくなるかと思います。
念の為に確認しますが、ロケールの設定はなさっていますね?

sq

Re: 文字変換クラスを作成したのですが

#8

投稿記事 by sq » 11年前

すみません。最初のコード見て訂正されたコードを見逃してました。
ただ文字化けは多分最初のコードが原因かなと思います。
次のコードはどちらも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";
}

gran

Re: 文字変換クラスを作成したのですが

#9

投稿記事 by gran » 11年前

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をインクルードするのがなんとなく嫌だったのです。

エラーは現在出ておらず、ロケールの設定は開発環境の方で
行っています。

現在もまだ文字化けしたままです。
よろしくお願いします。

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: 文字変換クラスを作成したのですが

#10

投稿記事 by h2so5 » 11年前

>granさん
そのコードだとsqさんが指摘した通りの問題が発生してしまいます。

gran

Re: 文字変換クラスを作成したのですが

#11

投稿記事 by gran » 11年前

デストラクタが呼ばれているということでしょうか。

コード:


//---------------------------------------------------------------------
// 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

こうしないと中身が保障されないということですか?

nil
記事: 428
登録日時: 12年前

Re: 文字変換クラスを作成したのですが

#12

投稿記事 by nil » 11年前

それでも同じです
p_wstrの中身はwstrが持っているのですから。
[修正]
p_wstrの指す値はwstr.c_str()と同値ですから。

gran

Re: 文字変換クラスを作成したのですが

#13

投稿記事 by gran » 11年前

値がおかしいということはわかりましたが
sqさんが記載していたコードを試してみましたが
変な値が入ったままのようです。

あと私はこんな書き方は知りませんでしたが
return = wss.str();
はエラーコードとなりました。
構文エラー"="だそうです。

依然問題は解決していません、よろしくお願いします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 文字変換クラスを作成したのですが

#14

投稿記事 by softya(ソフト屋) » 11年前

戻り値としてポインタを返すのは無理だと思ってもらった方が良いです。
なんども書かれているように関数を抜けるとクラスのデストラクトとともに変数のメモリは解放されるのです。
※ 出来ないことはないですが、そうするとメモリ解放の管理をする必要が出てきます。
そういう事で、wstrのまま返すのが良いと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

gran

Re: 文字変換クラスを作成したのですが

#15

投稿記事 by gran » 11年前

softya(ソフト屋)さん返信ありがとうございました。
sqさんの言いたいことがようやく理解できました。

ポインタを返していたことに言われるまで
気付きませんでした。
以上のことを踏まえて変換処理をした結果
うまくいきました。

返信してくださったみなさま、本当にありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る