CAtlListを使えば簡単にスタックを作ることができる。
ここではテンプレートクラスとして作成したため、スタック化する変数の型は自由に設定できる。
ちなみにこのクラスは画像をスライドショー表示するユーティリティを作ったときに作ったクラス。表示した画像を順次スタックに入れておき、ユーザーが「戻る」ボタンを押したときにスタックから画像を取り出して表示する、、、というようにすることで履歴機能を作成した。また、24時間連続で表示するようなスライドショーなため、無限に画像をスタックに入れておくとメモリー消費量が大変なことになる。そのためスタックへ追加する最大数をコンストラクタで設定できるようにした。
#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");
}
#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();
};
};
プロジェクトファイルをダウンロード