开发者

Tell `string::operator==` to start comparing at the back of the string

Is it possible/(relatively) easy/std™ to start comparing at the back of a string or should I write my own function for that? It would be relatively straightforward of course, but still, I would trust a standard library implementation over mi开发者_运维问答ne any day.

The end of the string is almost unique, and the front is quite common, that's the only reason I need this "optimization".

Thanks!


Best I can think of so far is str1.size() == str2.size() && std::equal(str1.rbegin(), str1.rend(), str2.rbegin())


You could use std::equal in combination with std::basic_string::reverse_iterator (rbegin, rend).

However, it is relevant only if the strings have the same lenght (so you need first to check the sizes) and only for equality of the strings (since the most significant difference will be the last compared while iterating).

Example:

bool isEqual = s1.size() == s2.size() && std::equal( s1.rbegin(), s1.rend(), s2.rbegin());


Depending on how long the strings are (and your compiler), you may be better off sticking with operator==. On Visual C++ v10, that reduces to a memcmp call via char_traits::compare, which is (when optimized) going to compare the target byte ranges in chunks, probably as many bytes at a time as will fit in a register (4/8 for 32/64-bit).

static int __CLRCALL_OR_CDECL compare(const _Elem *_First1, const _Elem *_First2,
    size_t _Count)
    {   // compare [_First1, _First1 + _Count) with [_First2, ...)
    return (_CSTD memcmp(_First1, _First2, _Count));
    }

Meanwhile, std::equal (the nicest alternative) does a byte by byte comparison. Does anybody know if this will get optimized in the same way since they are reverse iterators? At best, alignment handling is more complex since the start of the range is not guaranteed well-aligned.

template<class _InIt1,
    class _InIt2> inline
    bool _Equal(_InIt1 _First1, _InIt1 _Last1, _InIt2 _First2)
    {   // compare [_First1, _Last1) to [First2, ...)
    for (; _First1 != _Last1; ++_First1, ++_First2)
        if (!(*_First1 == *_First2))
            return (false);
    return (true);
    }

See @greyfade's answer here for some color on GCC.


If you want to reverse it first, I would suggest reverse() from to reverse the string first, then start comparing using string.compare() or use your own algorithm. However, reverse() does take a while, and is processor intensive, so I do suggest your own function to handle this one. Start a loop with i equal to the string.length(), and then count back using --i and compare.

function stringCompFromBack(string str1, string str2)
{
    if (str1.length() != str2.length)
    {return false;}

    for(int i = str1.length() ; i > 0; --i)
    {
        if(str1[i] != str2 [i])
        {return false;}
    }
    return true;
}

string str1 = "James Madison";
string str2 = "James Ford";
bool same = stringCompFromBack(str1, str2);


You should write your own function for that. You could reverse as Lost says, but that wouldn't be an optimization unless you kept that reversed string around and where comparing multiple times. Even then, it wouldn't be an improvement over writing your own that simply iterates the strings in reverse.


I see two options:

  1. Write your own comparison function and call that.

  2. Write a wrapper class around std::string, and implement operator== for that class to have the behavior you want.

The second is probably overkill.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜