开发者

C++: set of C-strings

I want to create one so that I could check whether a certain word is in the set using set::find

However, C-strings are pointers, so the set would compare them by the pointer values by default. To function correctly, it would have to dereference them and compare the strings.

I could just pass the constructor a pointer to the strcmp() function as a comparator, but this is not exactly how I want it to work. The word I might want to check could be part of a longer string, and I don't want to create a new string due to performance concerns. If there weren't for the set, I would use strncmp(a1, a2, 3) to check the first 3 letters. In fact, 3 is probably the longest it could go, so I'm fine with having the third argument constant.

Is there a way to construct a set that would compare its elements by calling strncmp()? Code samples would be greatly appreciated.

Here's pseudocode for what I want to do:

bool WordInSet (string, set, length)
{
   for (each word in set)
    {
       if strncmp(string, word, length) == 0
            return true;
    }
    return false;
}

But I'd prefer to impleme开发者_如何学运维nt it using the standard library functions.


You could create a comparator function object.

struct set_object {
    bool operator()(const char* first, const char* second) {
        return strncmp(first, second, 3);
    }
};

std::set<const char*, set_object> c_string_set;

However it would be far easier and more reliable to make a set of std::strings.


Make a wrapper function:

bool myCompare(const char * lhs, const char * rhs)
{
    return strncmp(lhs, rhs, 3) < 0;
}


Assuming a constant value as a word length looks like asking for trouble to me. I recommend against this solution.

Look: The strcmp solution doesn't work for you because it treats the const char* arguments as nul-terminated strings. You want a function which does exactly the same, but treats the arguments as words - which translates to "anything-not-a-letter"-terminated string.

One could define strcmp in a generic way as:

template<typename EndPredicate>
int generic_strcmp(const char* s1, const char* s2) {
    char c1;
    char c2;
    do { 
        c1 = *s1++; 
        c2 = *s2++; 
        if (EndPredicate(c1)) {
            return c1 - c2; 
        }
    } while (c1 == c2);

    return c1 - c2; 
}

If EndPredicate is a function which returns true iff its argument is equal to \0, then we obtain a regular strcmp which compares 0-terminated strings.

But in order to have a function which compares words, the only required change is the predicate. It's sufficient to use the inverted isalpha function from <cctype> header file to indicate that the string ends when a non-alphabetic character is encountered.

So in your case, your comparator for the set would look like this:

#include <cctype>

int wordcmp(const char* s1, const char* s2) {
    char c1;
    char c2;
    do { 
        c1 = *s1++; 
        c2 = *s2++; 
        if (!isalpha(c1)) {
            return c1 - c2; 
        }
    } while (c1 == c2);

    return c1 - c2; 
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜