views:

294

answers:

5

if statement looks too awkward, because i need a possibility to increase the number of constatnts. Sorry for leading you into delusion by that "constant" instead of what i meant.

+2  A: 

Put the strings to be compared in a static vector or set and then use std::find algorithm.

Naveen
Don't use std::find on sets or maps. The member function find is a lot more efficient for these types
Glen
Yes, you are right.
Naveen
+9  A: 

Add all your constants to a std::set then you can check if the set contains your string with

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";
Glen
Scott Meyers would suggest that you use 'count' here rather than 'find'. It's also less code.
Richard Corden
And he would have been right. I just forgot all about count, I havne't used std::set in quite a while. I'll update my answer
Glen
Just remember that the set should be static and filled only if it's empty or just make sure it's available to you but filled only once if you want it to work efficiently ;)
RnR
A: 
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;
}

Or use a std::set.

anon
+3  A: 

Depends whether you care about performance.

If not, then the simplest code is probably to put the various strings in an array (or vector if you mean you want to increase the number of constants at run time). This will also be pretty fast for a small number of strings:

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

Then either:

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;
    }
}

Or:

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

[Warning: I haven't tested the above code, and I've got the signatures wrong several times already...]

If you do care about performance, and there are a reasonable number of strings, then one quick option would be something like a Trie. But that's a lot of effort since there isn't one in the standard C++ library. You can get much of the benefit either using a sorted array/vector, searched with 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);

... or use a std::set. But unless you're changing the set of strings at runtime, there is no advantage to using a set over a sorted array with binary search, and a set (or vector) has to be filled in with code whereas an array can be statically initialized. I think C++0x will improve things, with initializer lists for collections.

Steve Jessop
+1 for mentioning sorted `vector` with `binary_search`.
avakar
A: 

The technically best solution is: build a 'perfect hash function' tailored to your set of string constants, so later there are no collisions during hashing.

hexcoder
I like the thinking, but the problem is — not only constant should not collide, but the possible input string too.
Michael Krelin - hacker