Каков наилучший способ сравнения строковой переменной с набором строковых констант? - PullRequest
1 голос
/ 21 августа 2009

if утверждение выглядит слишком неловко, потому что мне нужна возможность увеличить число констант. Извините, что ввел вас в заблуждение этой «константой» вместо того, что я имел в виду.

Ответы [ 5 ]

9 голосов
/ 21 августа 2009

Добавьте все свои константы в 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";
3 голосов
/ 21 августа 2009

Зависит от того, заботитесь ли вы о производительности.

Если нет, то простейший код, вероятно, состоит в том, чтобы поместить различные строки в массив (или вектор, если вы хотите увеличить число констант во время выполнения). Это также будет довольно быстро для небольшого числа строк:

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 улучшит ситуацию со списками инициализаторов для коллекций.

2 голосов
/ 21 августа 2009

Поместите строки для сравнения в статический вектор или набор, а затем используйте алгоритм std :: find.

1 голос
/ 21 августа 2009

Технически наилучшее решение: создать «идеальную хэш-функцию», адаптированную к вашему набору строковых констант, чтобы впоследствии не возникало коллизий во время хеширования.

0 голосов
/ 21 августа 2009
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.

...