比较std :: strings的最佳方法

时间:2011-01-23 04:33:58

标签: c++ string comparison io string-comparison

比较std::string的最佳方式是什么?显而易见的方法是if / else

std::string input;
std::cin >> input;

if ( input == "blahblahblah" )
{
    // do something.
}

else if ( input == "blahblah" )
{
    // do something else.
}

else if ( input == "blah" )
{
    // do something else yet.
}

// etc. etc. etc.

另一种可能性是使用std::mapswitch / case。在进行这些比较(例如8,10,12 +)时,最好的方法是什么?

6 个答案:

答案 0 :(得分:25)

这是使用std :: map。

的示例
#include <map>
#include <string>
#include <iostream>
#include <utility>

void first()
{
  std::cout << "first\n";
}

void second()
{
  std::cout << "second\n";
}

void third()
{
  std::cout << "third\n";
}


int main()
{
  typedef void(*StringFunc)();
  std::map<std::string, StringFunc> stringToFuncMap;

  stringToFuncMap.insert(std::make_pair("blah", &first));
  stringToFuncMap.insert(std::make_pair("blahblah", &second));
  stringToFuncMap.insert(std::make_pair("blahblahblah", &third));

  stringToFuncMap["blahblah"]();
  stringToFuncMap["blahblahblah"]();
  stringToFuncMap["blah"]();
}

输出是:

second
third
first

这种方法的好处是:

  • 很容易扩展。
  • 它强制您将字符串处理例程分解为单独的函数(按意图编程)。
  • 函数查找是O(log n),而您的示例是O(n)

使用boost :: function来使语法更好一些,特别是对于类成员函数。

答案 1 :(得分:3)

使用operator==非常好,但如果性能非常重要,您可以根据用例进行改进。如果目标是选择一个选项之一并执行特定操作,则可以使用TRIE。此外,如果字符串足够不同,您可以执行以下操作:

switch(s[0]) {
case 'a':
    // only compare to strings which start with an 'a'
    if(s == "abcd") {

    } else if (s == "abcde") {

    }
    break;
case 'b':
    // only compare to strings which start with an 'b'
    if(s == "bcd") {

    } else if (s == "bcde") {

    }
    break;
default:
    // we know right away it doesn't match any of the above 4 choices...
}

基本上使用字符串中的某个字符,它具有良好的唯一性(如果所有字符串的长度至少为N,则在N之前的任何字符中都不必是第一个!)来执行switch然后执行对符合该独特特征的字符串子集进行一系列比较

答案 2 :(得分:1)

“12”并不是很多......但无论如何。

您只能使用switch作为整数类型(charint等),因此对于std::string来说是不可能的。使用地图可能更具可读性。

然后,这一切都取决于你如何定义“最佳”。

答案 3 :(得分:0)

这个问题的答案完全取决于问题。你已经列举了两个例子。您可以添加诸如哈希表,正则表达式等选项......

答案 4 :(得分:0)

通过8,10甚至12个比较,你仍然可以使用if ... else if ...方案,没什么不好的。如果你想要100或者其他东西,我建议写一个函数来计算字符串的散列(即使是通过简单的xoring所有字符,但是其他一些好的方法更适合更好的分配),然后将其结果切换为Evan建议。如果函数返回所有可能输入字符串的唯一数字 - 那就更好了,不需要进行额外的比较。

答案 5 :(得分:0)

如果你的意思是“最有效”,那么请提前阅读。

如果有很多话,我建议使用以下方法 Switch中的字符串实际上是Java 7中的字符串。(作为Project Coin的一部分)

根据proposal,这是Java语言实现它的方式 首先,计算每个字符串的哈希值。这个问题是一个“switch int”问题,它以大多数当前语言提供,并且是有效的。在每个case语句中,然后检查这是否真的是字符串(在极少数情况下,不同的字符串可以散列到相同的int)。
我个人有时不会在实践中做最后一步,因为它的必要性取决于你特定程序所处的情况,即字符串是否在程序员的控制之下以及程序需要多么强大。

对应的样本伪代码

String s = ...
switch(s) {
 case "quux":
    processQuux(s);
    // fall-through

  case "foo":
  case "bar":
    processFooOrBar(s);
    break;

  case "baz":
     processBaz(s);
    // fall-through

  default:
    processDefault(s);
    break;
}

来自the fore-mentioned proposal以帮助您理解。

// Advanced example
{  // new scope for synthetic variables
  boolean $take_default = false;
  boolean $fallthrough = false;
  $default_label: {
      switch(s.hashCode()) { // cause NPE if s is null
      case 3482567: // "quux".hashCode()
          if (!s.equals("quux")) {
              $take_default = true;
              break $default_label;
          }
          processQuux(s);
          $fallthrough = true;
                case 101574: // "foo".hashCode()
          if (!$fallthrough && !s.equals("foo")) {
              $take_default = true;
              break $default_label;
          }
          $fallthrough = true;
      case 97299:  // "bar".hashCode()
          if (!$fallthrough && !s.equals("bar")) {
              $take_default = true;
              break $default_label;
          }
          processFooOrBar(s);
          break;

      case 97307: // "baz".hashCode()
          if (!s.equals("baz")) {
              $take_default = true;
              break $default_label;
          }
          processBaz(s);
          $fallthrough = true;

      default:
          $take_default = true;
          break $default_label;
      }
  }
  if($take_default)
      processDefault(s);
}