【问题标题】:What is the best way of comparing a string variable to a set of string constants?将字符串变量与一组字符串常量进行比较的最佳方法是什么?
【发布时间】:2009-08-21 11:09:10
【问题描述】:

if 语句看起来太尴尬了,因为我需要增加常量数量的可能性。 很抱歉用那个“常数”而不是我的意思来误导你。

【问题讨论】:

  • 您确定要将一个常量与一组常量进行比较吗?这个测试的结果是静态已知的,对吧?
  • 他的意思可能是指向常量字符串的非常量指针:const char *blah = "foo"; if (isRiemannHypothesisTrue()) blah = "bar";。然后检查 blah 是否在集合中。
  • to onebyone - 我想我在思考之前已经发布了一个问题 =) 我需要解析一个字符串,所以当函数看到一个关键字时,它应该用其他字符串值替换它。
  • 请编辑您的问题以反映您刚才所说的内容。我只是阅读这个问题,看看您将常量与常量进行比较可能意味着什么。

标签: c++ string compare constants


【解决方案1】:

将所有常量添加到 std::set 然后您可以检查该集合是否包含您的字符串

std::set<std::string> myLookup;
//populate the set with your strings here

set<std::string>::size_type i;

i = myLookup.count(searchTerm);
if( i )
    std::cout << "Found";
else 
    std::cout << "Not found";

【讨论】:

  • Scott Meyers 建议您在此处使用“计数”而不是“查找”。代码也更少。
  • 他是对的。我只是忘记了所有关于计数的事情,我已经有一段时间没有使用 std::set 了。我会更新我的答案
  • 请记住,集合应该是静态的,并且只有在它为空时才被填充,或者只是确保它对您可用,但如果您希望它有效地工作,则只填充一次;)
【解决方案2】:

取决于你是否关心性能。

如果不是,那么最简单的代码可能是将各种字符串放入一个数组(或向量,如果您的意思是要在运行时增加常量的数量)。对于少量字符串,这也将非常快:

static const char *const strings[] = { "fee", "fie", "fo", "fum" };
static const int num_strings = sizeof(strings) / sizeof(char*);

然后:

int main() {
    const char *search = "foe";
    bool match = false;
    for (int i = 0; i < num_strings; ++i) {
        if (std::strcmp(search, strings[i]) == 0) match = true;
    }
}

或者:

struct stringequal {
    const char *const lhs;
    stringequal(const char *l) : lhs(l) {}
    bool operator()(const char *rhs) {
        return std::strcmp(lhs, rhs) == 0;
    }
};

int main() {
    const char *search = "foe";
    std::find_if(strings, strings+num_strings, stringequal(search));
}

[警告:我没有测试过上面的代码,我已经把签名弄错了好几次......]

如果您确实关心性能,并且有合理数量的字符串,那么一个快速的选择就是Trie。但这需要付出很多努力,因为标准 C++ 库中没有。您可以使用已排序的数组/向量(使用 std::binary_search 搜索)获得很多好处:

// These strings MUST be in ASCII-alphabetical order. Don't add "foo" to the end!
static const char *const strings[] = { "fee", "fie", "fo", "fum" };
static const int num_strings = sizeof(strings) / sizeof(char*);

bool stringcompare(const char *lhs, const char *rhs) {
    return std::strcmp(lhs, rhs) < 0;
}

std::binary_search(strings, strings+num_strings, "foe", stringcompare);

...或使用std::set。但是,除非您在运行时更改字符串集,否则在使用二进制搜索的排序数组上使用集合并没有优势,并且必须用代码填充集合(或向量),而数组可以静态初始化.我认为 C++0x 会改进一些东西,为集合提供初始化列表。

【讨论】:

    【解决方案3】:

    将要比较的字符串放入静态向量或集合中,然后使用 std::find 算法。

    【讨论】:

    • 不要在集合或地图上使用 std::find。成员函数 find 对于这些类型来说效率更高
    【解决方案4】:

    技术上最好的解决方案是:构建一个适合您的字符串常量集的“完美散列函数”,以便以后在散列期间不会发生冲突。

    【讨论】:

    • 我喜欢这种想法,但问题是——不仅常量不应该冲突,而且可能的输入字符串也是。
    【解决方案5】:
    const char * values[]= { "foo", "bar", ..., 0 };
    
    bool IsValue( const std::string & s ) {
       int i = 0;
       while( values[i] ) {
          if ( s == values[i] ) {
             return true;
          }
          i++;
       }
       return false;
    }
    

    或者使用 std::set。

    【讨论】:

      猜你喜欢
      • 2014-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-17
      • 1970-01-01
      • 1970-01-01
      • 2015-10-03
      相关资源
      最近更新 更多