スタックを実現するクラス

CAtlListを使えば簡単にスタックを作ることができる。

ここではテンプレートクラスとして作成したため、スタック化する変数の型は自由に設定できる。



ちなみにこのクラスは画像をスライドショー表示するユーティリティを作ったときに作ったクラス。表示した画像を順次スタックに入れておき、ユーザーが「戻る」ボタンを押したときにスタックから画像を取り出して表示する、、、というようにすることで履歴機能を作成した。また、24時間連続で表示するようなスライドショーなため、無限に画像をスタックに入れておくとメモリー消費量が大変なことになる。そのためスタックへ追加する最大数をコンストラクタで設定できるようにした。



■使用例
int型のスタックを用意して「1 2 3 4 5」の順番でデータを追加。順番に取り出すと「5 4 3 2 1」という順でデータが取り出せる。
#include "DnpStack.h"

void	Test()
{
	int		n;
	bool	ret;
	CDnpStack<int>	cStack;		//ここを「cStack(3)」にして最大数を3に設定すると出力は「5 4 3」になる

	cStack.AddData(1);		//データ追加、1,2,3,4,5の順に追加
	cStack.AddData(2);
	cStack.AddData(3);
	cStack.AddData(4);
	cStack.AddData(5);

	do
	{
		ret = cStack.GetData(n);
		if(ret)
		{
			ATLTRACE("%d ",n);
		}
	}
	while(ret);
	ATLTRACE("\n");
}




■以下が「DnpStack.h」の内容

依存環境:ATL
#pragma	once

#include "atlcoll.h"

/*!
 * \brief
 * スタックテンプレートクラス
 * 
 * データ格納順序を「A->B->C->D」とすると、
 * 「D->C->B->A」の順で取得できる。
 * 
 * 以下のコードでは「5 4 3 2 1」と出力される
 * \code
	int		n;
	bool	ret;
	CDnpStack<int>	cStack;		//ここを「cStack(3)」にして最大数を3に設定すると出力は「5 4 3」になる

	cStack.AddData(1);		//データ追加
	cStack.AddData(2);
	cStack.AddData(3);
	cStack.AddData(4);
	cStack.AddData(5);

	do
	{
		ret = cStack.GetData(n);
		if(ret)
		{
			ATLTRACE("%d ",n);
		}
	}
	while(ret);
	ATLTRACE("\n");
 * \endcode
*/
template<class VALUE>
class CDnpStack
{
	UINT		_nMaxSize;

public:
	CAtlList<VALUE>	_listData;			//!< スタック用内部データ


	/*!
	 * \brief
	 * コンストラクタ(最大保持サイズの設定可能)
	 * 
	 * \param[in]	nMaxSize
	 * データ最大保持サイズ(0なら無制限)
	 * 
	 * nMaxSizeに3を設定して、「A->B->C->D」の順で格納すると、
	 * 「D->C->B」の順で取得できる。「A」のデータは内部で削除される。
	 * 
	 */
	CDnpStack(int nMaxSize = 0)
	{
		_nMaxSize = nMaxSize;
	}

	virtual ~CDnpStack()
	{
	}


	/*!
	 * \brief
	 * スタックにデータ追加
	 * 
	 * \param[in]	data
	 * 追加するデータ
	 * 
	 */
	void	AddData(VALUE data)
	{
		_listData.AddTail(data);

		//古いデータ削除(ポインタだとメモリリークの可能性あり)
		if(_nMaxSize > 0 && _listData.GetCount() > _nMaxSize)
			_listData.RemoveHead();
	};


	/*!
	 * \brief
	 * スタックからデータを取り出す
	 * 
	 * \param[out]	data
	 * 取りだしたデータ
	 * 
	 * \retval	true	成功
	 * \retval	false	失敗
	 * 
	 */
	bool	GetData(VALUE& data)
	{
		if(_listData.GetCount() > 0)
			data = _listData.RemoveTail();
		else
		{
//			data = NULL;
			return	false;
		}
		return	true;
	};


	/*!
	 * \brief
	 * スタックからデータを取り出す
	 * 
	 * \return	取りだしたデータ
	 * 
	 * \attention
	 * データ取得に失敗した場合、どのようなデータが返るかわからないので
	 * 安全のために CDnpStack<VALUE>::GetData(VALUE&) を利用すべき
	 */
	VALUE	GetData(void)
	{
		VALUE	ret;
		GetData(ret);
		return	ret;
	};


	/*!
	 * \brief
	 * 先頭のデータを取得する(GetDataのように内部データの削除はしない)
	 * 
	 * \param[out]	data
	 * 取りだしたデータ
	 * 
	 * \retval	true	成功
	 * \retval	false	失敗
	 */
	bool	ReferData(VALUE& data)
	{
		if(_listData.GetCount() > 0)
			data = _listData.GetTail();
		else
		{
//			data = NULL;
			return	false;
		}
		return	true;
	}



	/*!
	 * \brief
	 * 先頭のデータを取得する(GetDataのように内部データの削除はしない)
	 * 
	 * \return	取りだしたデータ
	 * 
	 * \attention
	 * データ取得に失敗した場合、どのようなデータが返るかわからないので
	 * 安全のために CDnpStack<VALUE>::ReferData(VALUE&) を利用すべき
	 */
	VALUE	ReferData(void)
	{
		VALUE	ret;
		ReferData(ret);
		return	ret;
	}



	/*!
	 * \brief
	 * スタックに格納されているデータ数取得
	 * 
	 * \return
	 * スタックに格納されているデータ数
	 */
	int		GetSize(void)
	{
		return	(int)_listData.GetCount();
	};


	/*!
	 * \brief
	 * 内部データの全削除
	 */
	void	RemoveAll(void)
	{
		_listData.RemoveAll();
	};
};
プロジェクトファイルをダウンロード

カテゴリー「その他」 のエントリー