如何确定1000个潜在关键字中的给定关键字?

Not*_*mer 3 c++ performance parsing

所以我不是一个专业的开发人员,但我定期编程.我正在寻找编写代码,并寻找一些关于管理解析器的建议,该解析器正在读取文本文件,将每行视为字符串,并尝试确定该行的输入.任何给定的行可能是1000多个不同的关键字之一,这是困难的部分.一旦我有了这个关键字,我觉得必须有一个更有效的方法来确定它是什么,而不是实现1000 if-else语句或1000 case-break语句.一旦我匹配给定的关键字,我计划跳转到一个例程,该例程实例化该关键字类型的对象.在找到我的目标之前,我不想进行999次测试,这只是我觉得的浪费.我尝试按字母顺序拆分它,这大大减少了它,但仍然存在无法管理的大量if-else语句.

我已经发现我不能嵌套超过128个if-else语句,所以我当前的替代方案是1000个只是"if"语句没有匹配"else"语句,我知道这是一个不好的做法.所以这是我当前代码的概括:

if (keyword_str.compare(keyword1)) {
        Parse(keyword1); // A general routine to parse all these similarly formatted keywords
        } 
if (keyword_str.compare(keyword2)) {
        Parse(keyword2);
        } 
if (keyword_str.compare(keyword3)) {
        Parse(keyword3);
        }
//
//
//

if (keyword_str.compare(keyword999)) {
        Parse(keyword999);
        }
if (keyword_str.compare(keyword1000)) {
        Parse(keyword1000);
        }
Run Code Online (Sandbox Code Playgroud)

任何帮助将不胜感激!谢谢!


好的,所以这就是我所处的观点,但仍然有点迷失在如何使用地图来确定对象类型,然后实例化该对象.以下是一些代码段:

class baseClass
    {
    public:
        baseClass();
        ~baseClass();
    };
//
// keyword1 class declaration
class keyword1 : public baseClass
    {
    public:
        // Constructors
        keyword1 () { cout << "keyword1 constructor..." << endl;}
        ~keyword1 () { cout << "keyword1 destructor..." << endl;}

    protected:

    };
//
// keyword2 class declaration
class keyword2 : public baseClass
    {
    public:
        // Constructors
        keyword2 () { cout << "keyword2 constructor..." << endl;}
        ~keyword2 () { cout << "keyword2 destructor..." << endl;}

    protected:

    };
//
// keyword3 class declaration
class keyword3 : public baseClass
    {
    public:
        // Constructors
        keyword3 () { cout << "keyword3 constructor..." << endl;}
        ~keyword3 () { cout << "keyword3 destructor..." << endl;}

    protected:

    };


//
//*******************


    map <string, baseClass> keyword_map;

    keyword_map.insert (make_pair ("keyword1", keyword1 )); // ########## This is where I'm lost
    keyword_map.insert (make_pair ("keyword2", keyword2 )); // ########## This is where I'm lost
    keyword_map.insert (make_pair ("keyword3", keyword3 )); // ########## This is where I'm lost

    // Search for keyword
    string searching_for = "keyword3";
    map <string, baseClass> ::const_iterator it = keyword_map.find(searching_for);


    if (it == keyword_map.end()) {
        cout << "No keyword found." << endl;
            }
        else 
            {
        cout << "Found the keyword!" << endl;
        it->second; // ########## This is where I'm lost
            }
Run Code Online (Sandbox Code Playgroud)

Hos*_*ork 5

一旦我匹配给定的关键字,我计划跳转到一个例程,该例程实例化该关键字类型的对象.

你不想拥有1000种不同的IF语句的直觉是正确的.

抽象地说,我建议考虑一下老式的卡片目录是如何工作的(假设你曾见过一个,年轻人还知道这些是什么吗?)

在此输入图像描述

卡片目录很有用,因为您不是从第一个抽屉开始并按顺序查看所有项目,然后转到下一个抽屉.相反,您可以使用快速测试来了解要查看的抽屉.快速测试涉及指纹或候选人的"哈希".旧图书馆卡目录通常使用非常简单的"哈希函数"(前一个或两个字母;"此抽屉包含标题以"S-Ti"开头的书籍的所有卡片.)您缩小了所需的比较数量基于该测试做的只能看一个抽屉.

如果想出一种指纹字符串的方法听起来很多工作,并将它们归档到像这样的桶中,那么你很幸运.这是在标准库的引擎下已经完成的所有工作.除非你的需求非常专业(或者你的关键字中有奇怪的模式,他们都有相同的"指纹")... std :: unordered_map应该有用.

选择std::string代表关键字的"密钥" ."价值"将是某种工厂......从关键字后面的东西创建对象的方法.这可能是你"更好的方式"的基础......

..但

std::unordered_map这种情况下初始化a 来进行出价时,如果地图中的"值"都适合构建不同的类,则1000就是大量的类.您可能希望在键入class ObjectOne和编号之前列出更多细节class ObjectOneThousand,这听起来像执行1000个IF语句进行比较一样有问题.

所以也许你应该在聊天或其他论坛中寻求更多的评论,然后再继续这个想法.


更新以响应编辑

您的代码在关键字类别方面存在问题.它们是否打算代表关键字类(因为......只有那么多的实例化,因为你有关键字?)一个人应该对只有一个实例并代表一类事物的类持怀疑态度; 这就是班级本身的意义所在.如果这是有道理的.: - /

因此,您想要放在地图中的不是关键字的实例.更重要的是,您在概念上想要放置稍后调用的关键字类.在精神上,这将是:

#include <typeinfo>

map <string, type_info &> keyword_map;

keyword_map.insert (make_pair ("keyword1", typeid(keyword1) )); 
keyword_map.insert (make_pair ("keyword2", typeid(keyword2) )); 
keyword_map.insert (make_pair ("keyword3", typeid(keyword3) ));
Run Code Online (Sandbox Code Playgroud)

您可能会认为稍后您可以make_class使用type_info 调用某种类型,但它不会那样工作.因此......存储工厂函数以获得该行为的想法.我将用静态成员函数给你一个简单的答案,所以在每个关键字类中你都有这样的东西:

class keyword1 : public baseClass {
    // ...
    static shared_ptr<baseClass> factory() {
        return make_shared<keyword3>();
    }
    // ...
};
Run Code Online (Sandbox Code Playgroud)

因为它是一个静态成员,它就像一个普通的函数.你可以获取它的地址,存储指针,然后在没有任何类实例的情况下调用它来调用它.它返回一个指向基类的共享指针,尽管你最终会得到的是一个指向基类的指针...它会对你在基类接口中定义的任何虚函数进行多态化处理,因为它适用于那种类关键字是.

(注意你需要在这种情况下使你的析构函数变为虚拟!最好默认情况下这样做,只有在你有充分理由的情况下才能这样做.)

map <string, shared_ptr<baseClass>(*)()>> keyword_map;

keyword_map.insert (make_pair ("keyword1", &keyword1::factory )); 
keyword_map.insert (make_pair ("keyword2", &keyword2::factory )); 
keyword_map.insert (make_pair ("keyword3", &keyword3::factory ));
Run Code Online (Sandbox Code Playgroud)

现在,稍后当您找到关键字时,可以调用从中获取的函数find来获取相应关键字类的实例.然后做你计划用对象实例做的任何事情.

但我想你会发现很难在基类上定义一个在这样的设计中满足你的接口.这就是为什么我说1000个班级表明你可能没有问题,你想要接近你的想法.我还想象你会有很多其他问题,但请把它们作为自己的新问题帖子.:-)