c++ - 如何从1000个潜在关键字中确定给定关键字?

标签 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);
        }

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

好的,这就是我要说的重点,但是仍然有点不了解如何使用 map 确定对象类型,然后实例化该对象。以下是一些代码段:
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
            }

最佳答案

Once I matched the given keyword, I plan to jump to a general routine that instantiates an object of that keyword type.



您不希望拥有1000个不同的IF语句的直觉是正确的。

抽象地讲,我建议考虑一本老式卡片目录的工作原理(假设您曾经看过,那么年轻人还知道这些是什么吗?)

卡片目录很有用,因为您不必从第一个抽屉开始依次浏览所有物品,然后再进入下一个抽屉。取而代之的是,您进行了一次快速测试,可以用来了解要看哪个抽屉。该快速测试涉及指纹或候选项的"hash"。旧的图书馆卡目录通常使用非常简单的“哈希函数”(前一个或两个字母;“此抽屉包含标题为“S-Ti”开头的所有图书卡)。您可以缩小需要比较的数量根据该测试只能在一个抽屉中查看。

如果要想出一种方法来对字符串进行指纹识别并将其归档到这样的存储桶中似乎需要大量工作,那么您很幸运。这是标准库的全部工作。除非您的需求非常特化(或者您的关键字在它们都具有相同的“指纹”的地方有奇怪的模式),否则std::unordered_map应该可以工作。

选择一个代表您的关键字的std::string的“关键字”。 “值”将是某种工厂……一种根据关键字后面的内容创建对象的方法。那可能是您“更好的方式”的基础...

..但

在这种情况下,就初始化std::unordered_map进行出价而言,如果 map 中的“值”每个都适合构造不同的类,则1000个是大量类。在键入class ObjectOne并将其编号为class ObjectOneThousand之前,您可能需要布置更多细节,这听起来和执行1000个IF语句进行比较一样令人怀疑。

因此,也许您应该在聊天或其他论坛中寻求更多评论,然后再继续进行此构想。

更新以响应编辑

就关键字类是什么而言,您的代码有问题。它们是否打算代表关键字类(例如,……实例化与您拥有的关键字一样多?)人们应该对只有一个实例并且代表一类事物的类持怀疑态度;这就是类(class)本身的目的。如果这样的话。 :-/

因此,您要放入 map 中的不是关键字的实例。从概念上讲,您还想添加一个关键字类,以便以后使用。从本质上讲,这将是:
#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) ));

您可能以为以后可以用type_info调用某种make_class,但这种方式行不通。因此...存储工厂函数以获取该行为的想法。我将为您提供一个带有静态成员函数的简单答案,因此在每个关键字类中,您都将具有以下内容:
class keyword1 : public baseClass {
    // ...
    static shared_ptr<baseClass> factory() {
        return make_shared<keyword3>();
    }
    // ...
};

因为它是一个静态成员,所以它就像一个普通的函数。您可以获取它的地址,存储指针,然后在没有任何类实例的情况下调用它来调用它。它返回一个指向基类的共享指针,尽管最后您将得到一个指向基类的指针……它会根据您在基类的接口(interface)中定义的任何虚函数(根据类型)进行多态操作的关键词是。

(请注意,在这种情况下,您需要make your destructors virtual!最好默认执行此操作,并且只有在确实有充分理由的情况下才执行此操作。)
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 ));

现在,稍后找到关键字时,您调用从find返回的函数以获取相应关键字类的实例。然后执行您打算使用对象实例执行的所有操作。

但是我想您会发现很难在基类上定义一个满足您这种设计要求的接口(interface)。这就是为什么我说的1,000课表示您可能没有想要以自己认为的方式来解决问题的原因。我也想像您还会有许多其他问题,但请为他们提供新的问题。 :-)

关于c++ - 如何从1000个潜在关键字中确定给定关键字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25540242/

相关文章:

c++ - 使用正则表达式匹配字符串

c++ - 在 C++ 中将 wchar_t 转换为 wstring

c++ - Try, Throw, Catch 函数

c# - 未使用的导入命名空间与程序效率有关系吗?

mysql - 简单 InnoDB 表上的简单 MySQL INSERT 查询需要 40+ms

java - 解析 .txt 文件(考虑性能指标)

c++ - 在 C++ 中比较 double,同行评审

javascript - 在 javascript 中滚动时隐藏标题的性能问题

java - Java 中是否有比 Xalan/Xerces 更快的 XML 解析器

php 从 html 字符串中提取第一张图像,删除所有图像标签,并截断 html 字符串