Visual Studio 2017 の C++ 関連、その2
今度は std::list 関連
前回とは違い、std::list 関連!
MFC で DLL を作っていて、設定項目を管理するのに std::list を使ってみたけど、他の vector や array でも良いんだと思います
年度別に管理してみようと思っていますので、list が良いかな?と単純に考えて見ましたが…さて⁉
std::list の宣言
#include <list>
…
struct DLLList {
int year; // 年度
std::wstring dll_path; // パス
std::wstring dll_title; // 表示名
HMODULE hModue = NULL;
};
…
std::list<DLLList> _dll_list; // リスト形式
…
こんな感じ
年度ごとに特定の処理をする DLL を用意して LoadLibrary してみようと目論んでみましたので、宣言はこんな感じ
リストの追加
この前の、swscanf のところの fgets でファイルを読んで処理します..
_dll_list.clear();
…
while(0 != fgetws(wreadbuf, MAX_READ_BUF, fp)) {
…
DLLList tmp;
tmp.year = year;
tmp.dll_path = buf1;
tmp.dll_title = buf2;
_dll_list.push_back(tmp);
…
}
リストに項目を追加します
順番を指定したインサートとかもありますが、ソートとかする予定ですので読み込んだ順番にそのまま突っ込んでいきました
項目へのアクセス
突っ込んだ項目の、構造体のメンバーに変更を加えます
イテレーターを使わないで項目に直接アクセスしても、構造体のメンバーを変更できませんので、こんな感じで扱います
for (auto iter = _dll_list.begin(); iter != _dll_list.end(); iter++) {
…
HMODULE hMod = LoadLibraryW(iter->dll_path.c_str());
iter->hModue = hMod;
…
}
begin から end まで、インクリメントしてイテレーターを進めて、要素にアクセスしてゆきます
ソート
比較関数は bool 型で引数は const で対象が二つ送られてきます
最初の引数が小さいときに真で、逆の時は偽を返すようです
bool _dll_sort_comp(const DLLList& d1, const DLLList& d2) {
bool ret = FALSE;
if (d1.year < d2.year)
ret = TRUE;
return ret;
}
これで年度ごとの昇順にソートされます
実施はこんな感じ
…
_dll_list.sort(_dll_sort_comp);
…
降順に並べるときは、真偽を逆に返します
比較関数では真偽しか返していませんので、比較する項目が同じ値の場合はプッシュした順になります
※ 比較が甘いときの事ですね..
ソート自体は void 型なので戻り値は無し
検索 find_if
指定された年度を持つ構造体をリスト中から返すには、こんな感じに無名関数を使います
DLLList cmp{2005,L"",L"",NULL};
auto iter = std::find_if(_dll_list.begin(), _dll_list.end(),
[cmp](DLLList t) {return t.year == cmp.year; });
if( iter == _dll_list.end())
MessageBoxW(0, L"not found", L"find", 0);
else
MessageBoxW(0, iter->dll_title.c_str(),L"find", 0);
year が 2005 の行をイテレーターへ返してきます
# 最近は、こんな書き方出来るんだ ^^.. JSer&PHPer なので割と得意だけど…何か馴染まないなぁ..
こう言う auto …. と言う書き方は ラムダ式と言うのか…
https://msdn.microsoft.com/ja-jp/library/dd293599.aspx
ここの、ラムダ式の説明にも find_if で開設しているなぁ…
PHP のクロージャーとか、JavaScript の無名関数とは少し趣が異なるのか?厳格化しているだけなのか?…
# PHP はそういう所がよく出来てるよなぁ…そのうち調べて見よう…
検索条件を別に指定できるなら、検索関数を指定する事が出来ます
bool _dll_find_func(const DLLList& t) {
bool ret = FALSE;
…
if( 2005 == t.year) ret = TRUE;
…
return ret;
}
…
auto iter = std::find_if(_dll_list.begin(), _dll_list.end(), _dll_find_func);
こんな感じの比較関数を作ると、begin() から end() まで、全件聞いてきますので、条件に一致したら真を返します
# まぁ、検索をかけるならソートする必要も無いよね ^^;
検索 find
検索方法 その2
struct 宣言したときに、== オペレーターを書いておくと、std::find でも簡単に検索できる様です
auto iter = std::find(_dll_list.begin(), _dll_list.end(), DLLList{2005,L"",L"",NULL});
上の find_if をこんな風に置き換え出来ます
struct では こんな風にオペレーターを指定しました
bool operator == (const DLLList & tgt) {
// find 用のオペレータ
if (this->year == tgt.year)
return TRUE;
return FALSE;
}
で、オペレーターで比較できると言う事は…
struct DLLList {
int year; // 年度
std::wstring dll_path; // DLL のパス
std::wstring dll_title; // DLL の表示名
HMODULE hModue = NULL;
bool operator == (const DLLList& tgt) {
// find 用のオペレータ
if (this->year == tgt.year)
return TRUE;
return FALSE;
}
bool operator == (const int& year) {
// find 用のオペレータ 年度だけ比較
if (this->year == year)
return TRUE;
return FALSE;
}
};
こんな風に、 int 型の == オペレーターを指定すると、
int tgt_year = 2005;
auto iter = std::find(_dll_list.begin(), _dll_list.end(), tgt_year);
こんな感じの検索も出来ました ^^/
find_if にくらべて、こっちの方がシックリくる様な気がするけど…
# もしかして、const 型なので if 文の比較は year == this->year の方が良いのかな…
.