问题描述
void funnel(string line) {
if (line.find("Keyword1",0) == 0){
call_function1();
}
else if (line.find("Keyword2",0) == 0){
call_function2();
}
else if (line.find("Keyword3",0) == 0){
call_function3();
}
............
}
是否有一种更简单/更好/更有效的方法来执行此操作?还是我陷入了这个空漏斗的问题?
ClientConnect: (blake_won) ID: 0 (IP: 192.168.0.177:29071)
Kill: 0 0 7: blake_won killed blake_two by MOD_SWORD
这些行看起来像这样,我想根据每个开始关键字调用一个适当的函数。该文件不是我自己的,因此我无法控制写入的内容。
解决方法
我正在编写一个处理读取文本文件的程序。
以您的示例为例,我至少考虑在程序中嵌入一些现有解释器,例如Lua或Guile(或者也许Python)。
重用现有解释器的优势对于您作为开发人员和您的用户而言都是如此。
-
作为开发人员,您正在重用一些成熟的开源软件,并节省了宝贵的开发人员精力。
-
您的软件的用户可以参考现有的文档和示例。
请注意,嵌入某些解释器是一项重要的软件体系结构决定。
解释器强加了一些编码规则(特别是与内存管理和garbage collection相关的规则)。
或者,阅读有关parsing的更多信息(例如Dragon book的前半部分),并使用一些解析器生成器,例如GNU bison或ANTLR。 请确保首先以有效的语法记录EBNF的语法。
,正则表达式确实可以帮助从统一模式中收集信息,例如:
std::regex pattern { R"(^(\w+):)" };
std::map<std::string,std::function<void()>> dispatch {
{ "function1",function1 },{ "function2",function2 }
};
void funnel(const std::string& line) {
std::smatch match;
if (std::regex_search(line,match,pattern) && match.size() > 1) {
auto command = match.str(1);
auto fn = dispatch.find(command);
if (fn != dispatch.end()) {
fn->second();
} else {
std::cout << "command not recognized" << std::endl;
}
} else {
std::cout << "pattern doesn't match";
}
}
演示:https://godbolt.org/z/s5Mqej
,如果您有类似的重复代码,请将数据填充到vector
中并对其进行迭代。
例如:vector<pair<string,function<void()>>>
。或者,用人类语言:列表中的每个元素都是一对,其第一个元素是您的关键字,第二个元素是您要调用的函数。如果您想将其更明确,可以用专用的pair
代替struct
。
void funnel(string line,const vector<pair<string,function<void()>>>& list)
{
for (auto element: list)
{
if (line.find(element.first,0) != string::npos) // search
{
element.second(); // call the function
return;
}
}
}