正确使用大量已知常数的方法

时间:2018-09-27 11:56:35

标签: c++

程序将接收一个代表字符的向量。 然后将接收到的向量与代表字符的所有已知向量进行比较。

我不确定应该如何使用已知向量。

我想到的一些选择:

1)使用全局变量:

vector<int> charA{1,2,3,4,5};
vector<int> charB{5,3,7,1};
...
vector<int> charZ{3,2,5,6,8,9,0}

char getLetter(const vector<int> &input){
    if(compareVec(input,charA) return 'A';
    if(compareVec(input,charB) return 'B';
    ....
    if(compareVec(input,charZ) return 'Z';

}

2)声明函数中的所有变量:

 char getLetter(const vector<int> &input){
        vector<int> charA{1,2,3,4,5};
        vector<int> charB{5,3,7,1};
        ...
        vector<int> charZ{3,2,5,6,8,9,0}

        if(compareVec(input,charA) return 'A';
        if(compareVec(input,charB) return 'B';
        ....
        if(compareVec(input,charZ) return 'Z';

    }

3)传递变量

char getLetter(const vector<int> &input, vector<int> charA,
      vector<int> charB... , vecotr<int> charZ){
        if(compareVec(input,charA) return 'A';
        if(compareVec(input,charB) return 'B';
        ....
        if(compareVec(input,charZ) return 'Z';

    }

3 个答案:

答案 0 :(得分:4)

这听起来像是perfect hash generator的应用程序(链接到GNU gperf)。

引用文档

  

gperf是用C ++编写的完美的哈希函数生成器。它   将n元素用户指定的关键字集W转换为完美   哈希函数F。F将W中的关键字唯一地映射到范围0..k,   其中k> = n-1。如果k = n-1,则F是最小完美散列函数。   gperf生成一个0..k元素静态查找表和一对C   功能。这些函数确定给定的字符串   s出现在W中,最多使用一个对查询表的探测。

如果这不是合适的解决方案,那么我建议使用函数静态函数。您要避免使用函数局部变量,因为这会严重影响性能,并且全局变量会污染您的命名空间。

类似

char getLetter(const vector<int> &input){
    static vector<int> charA{1,2,3,4,5};
    static vector<int> charB{5,3,7,1};

答案 1 :(得分:0)

给你摘要,我去:

char getLetter(const vector<int> &input)
{
    struct 
    {
       char result;
       std::vector<char> data; 
    } const data[]=
    {
       { 'A', {1,2,3,4,5}, },
       { 'B', {5,3,7,1}, },
       ...
    };

    for(auto const & probe : data)
    {
        if (comparevec(input, probe.data))
           return probe.result;
    }

    // input does not match any of the given values
    throw "That's not the input I'm looking for!"; 
}

对于40个这样的对,如果没有在紧密的内部循环中调用它,则线性搜索就足够了。

替代品:

  • 使用std::map<std::vector<char>, char>将有效值映射到结果,然后将compareVec转换为适合作为映射键的键的函子,并以相同的方式对其进行初始化。

  • 如上,但使用std :: unordered_map。

  • 按照上面@PaulFloyd的建议使用gperf

答案 2 :(得分:0)

我首先建议您对二进制集合中的数字进行散列或表示,以便您不必每次都比较向量,因为这样做会非常昂贵。就是说,您的问题是关于如何制作字典的,所以无论您是否按照我的建议改进键,我都希望使用map

map<vector<int>, char, function<bool(const vector<int>&, const vector<int>&)>> dictionary([](const auto& lhs, const auto& rhs){
    const auto its = mismatch(cbegin(lhs), cend(lhs), cbegin(rhs), cend(rhs));

    return its.second != cend(rhs) && (its.first == cend(lhs) || *its.first < *its.second);
});

如果可能,dictionary应该使用包含所有映射和比较器的initializer_list构造为常量。如果必须确保已完成所有字母的查找,必须先查找映射,那么显然不能构造常数。无论哪种方式,此map应该是负责翻译字符串的类的私有成员。添加和映射应该是该类的公共功能。

Live Example