我发现自己编写的代码看起来很多:
set<int> affected_items;
while (string code = GetKeyCodeFromSomewhere())
{
if (code == "some constant" || code == "some other constant") {
affected_items.insert(some_constant_id);
} else if (code == "yet another constant" || code == "the constant I didn't mention yet") {
affected_items.insert(some_other_constant_id);
} // else if etc...
}
for (set<int>::iterator it = affected_items.begin(); it != affected_items.end(); it++)
{
switch(*it)
{
case some_constant_id:
RunSomeFunction(with, these, params);
break;
case some_other_constant_id:
RunSomeOtherFunction(with, these, other, params);
break;
// etc...
}
}
我最终编写此代码的原因是,即使我收到多个可能导致它们运行的密钥代码,我也只需要在第二个循环中运行一次函数。
这似乎不是最好的方法。有更简洁的方式吗?
答案 0 :(得分:2)
一种方法是维护从字符串到布尔值的映射。主要逻辑可以从以下内容开始:
if(done[code])
continue;
done[code] = true;
然后,您可以在识别代码后立即执行相应的操作。
另一种方法是将可执行文件(对象,函数指针等)存储到某种“待办事项列表”中。例如:
while (string code = GetKeyCodeFromSomewhere())
{
todo[code] = codefor[code];
}
初始化codefor以包含适用于每个代码值的函数指针或从公共基类子类化的对象。如果相同的代码出现多次,则todo中的相应条目将被覆盖与其已有的相同值。最后,迭代todo并运行其所有成员。
答案 1 :(得分:1)
由于您似乎并不关心集合中的实际值,因此可以使用int中的设置位替换它。您还可以使用日志时间搜索逻辑替换线性时间搜索逻辑。这是最终的代码:
// Ahead of time you build a static map from your strings to bit values.
std::map< std::string, int > codesToValues;
codesToValues[ "some constant" ] = 1;
codesToValues[ "some other constant" ] = 1;
codesToValues[ "yet another constant" ] = 2;
codesToValues[ "the constant I didn't mention yet" ] = 2;
// When you want to do your work
int affected_items = 0;
while (string code = GetKeyCodeFromSomewhere())
affected_items |= codesToValues[ code ];
if( affected_items & 1 )
RunSomeFunction(with, these, params);
if( affected_items & 2 )
RunSomeOtherFunction(with, these, other, params);
// etc...
答案 2 :(得分:1)
它肯定不整洁,但你可以保留一组标志,说明你是否已经调用了该特定功能。这样你就可以避免在一组中保存,只需要标记。
由于(可能是从编写它的方式),修复了不同if / else块的编译时编号,你可以用bitset很容易地做到这一点。
答案 3 :(得分:0)
显然,这取决于具体情况,但最好让你调用的函数跟踪它们是否已经运行并在需要时提前退出。