[c++] Сравниваем со статическим массивом
От: Warturtle  
Дата: 30.08.05 15:04
Оценка: :)
Проблема несколько надумана (на самом деле ее нет=)), но все же. Бывает так, что нужно сравнить динамический массив со статическим (размер которого заранее известен). Например, со строкой вида
char szSTRING[] = "wonderful string";


Можно написать нечто вроде:
void Func(char const *psz, size_t nLen)
{
    if (sizeof(szSTRING) <= nLen + 1) {
        if (psz[0] == 'w'
            && psz[0] == 'o'
            && psz[1] == 'n'
            && psz[2] == 'd'
            && psz[3] == 'e'
            && psz[4] == 'r'
            && psz[5] == 'f'
            && psz[6] == 'u'
            && psz[7] == 'l'
            && psz[8] == ' '
            && psz[9] == 's'
            && psz[10] == 't'
            && psz[11] == 'r'
            && psz[12] == 'i'
            && psz[13] == 'n'
            && psz[14] == 'g')
        {
            // че-то делаем...
        }
    }
}

а можно и не париться:
void Func(char const *psz, size_t nLen)
{
    if (::strncmp(szSTRING, psz,nLen) == 0) {
        // че-то делаем...
    }
}

Но мы ведь ищем легких путей!
Поэтому делаем "совсем с обратной стороны":
#include <iostream>
#include <algorithm>
using namespace std;

// [url=http://rsdn.ru/Forum/Message.aspx?mid=265122&only=1]товарищ[/url]дал стране угля:
template< class T, size_t N > char (&LengthOf (T(&)[N]) )[N];
#define length_of(arr) sizeof(LengthOf(arr)) \
  /**/

#if !defined(_MSC_VER)
#  define __forceinline inline
#endif

//////////////////////////////////////////////////////////////////////////
// FindMismatch - generalized mismatch search
//

template< class T, size_t t_nCount, size_t t_nStart = 0 >
struct FindMismatch 
{
    enum { IDX = t_nStart + t_nCount - 1 };
    typedef T const * const ArrayT;
    __forceinline static size_t Do(ArrayT lhs, ArrayT rhs)
    {
        //cout << "IDX == " << IDX << endl
        //     << "\tlhs[IDX] == " << lhs[IDX] << endl
        //     << "\trhs[IDX] == " << rhs[IDX] << endl
        //     << flush;

        return lhs[IDX] == rhs[IDX] ?
            FindMismatch< T, t_nCount - 1, t_nStart >::Do(lhs, rhs) : IDX;
    }
};
template< class T, size_t t_nStart >
struct FindMismatch< T, 1, t_nStart > 
{
    typedef T const * const ArrayT;
    __forceinline static size_t Do(ArrayT lhs, ArrayT rhs)
    {
        //cout << "IDX == " << t_nStart << endl
        //     << "\tlhs[t_nStart] == " << lhs[t_nStart] << endl
        //     << "\trhs[t_nStart] == " << rhs[t_nStart] << endl
        //     << flush;

        return lhs[t_nStart] == rhs[t_nStart] ? (size_t)-1 : t_nStart;
    }
};


//////////////////////////////////////////////////////////////////////////
// ArrayStuff
//

template< class CharT = char >
struct ArrayStuff
{
    template< size_t N >
    __forceinline static size_t Compare(CharT const *pStr, CharT const (&symb_arr)[N])
    {
        enum { LEN = length_of(symb_arr) - 1 };
        return FindMismatch< CharT, LEN >::Do(pStr, symb_arr);
    }


    template< size_t t_nIdx, class T, template <class T1, size_t, size_t> class HasDo >
    struct RT2CT
    {
        typedef T const * const ArrayT;
        __forceinline static size_t Get(size_t n, ArrayT lhs, ArrayT rhs)
        {
            return n < t_nIdx ?
                RT2CT< t_nIdx - 1, T, HasDo >::Get(n, lhs, rhs)
                : HasDo< T, t_nIdx, 0 >::Do(lhs, rhs);
        }
    };
    template< class T, template <class T1, size_t, size_t> class HasDo >
    struct RT2CT<1, T, HasDo >
    {
        typedef T const * const ArrayT;
        __forceinline static size_t Get(size_t n, ArrayT lhs, ArrayT rhs)
        {
            return n == 1 ?
                HasDo< T, 1, 0 >::Do(lhs, rhs) : (size_t)-1;
        }
    };
    template< size_t N >
    __forceinline static int Compare(CharT const *pStr, size_t nLen, CharT const(&symb_arr)[N])
    {
        enum { LEN = length_of(symb_arr) - 1 };
        if (nLen < LEN) {
            //cout << "!!! nLen (" << nLen << ") < LEN (" << LEN << ") !!! " << endl;
            return RT2CT< LEN, CharT, FindMismatch >::Get(nLen, pStr, symb_arr);
        }
        else {
            return FindMismatch<CharT, LEN >::Do(pStr, symb_arr);
        }
    }
};


int main()
{
    char const *pstr = "abcdef";
    cout << "ArrayStuff<char>::Compare(\""<< pstr <<"\", \"abcdeF\") == "
         << ArrayStuff<char>::Compare(pstr, "abcdeF") << endl
         << flush;

    cout << "ArrayStuff<char>::Compare(\""<< pstr <<"\", 3, \"abcQWE\") == "
         << ArrayStuff<char>::Compare(pstr, 3, "abcQWE") << endl
         << flush;

    ::system("PAUSE");
    return 0;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.