2010-11-30 14 views
7

¿Es posible/(relativamente) fácil/std ™ comenzar a comparar en la parte posterior de una cadena o debería escribir mi propia función para esa ? Sería relativamente sencillo, por supuesto, pero aun así, confiaría en una implementación de biblioteca estándar sobre la mía en cualquier momento.Diga `string :: operator ==` para empezar a comparar en la parte posterior de la cadena

El final de la cadena es casi único, y el frente es bastante común, esa es la única razón por la que necesito esta "optimización".

Gracias!

Respuesta

18

mejor que se me ocurre hasta ahora es str1.size() == str2.size() && std::equal(str1.rbegin(), str1.rend(), str2.rbegin())

+0

quizás un juego en esto sería usar string :: rfind en lugar de igual. – frankc

+0

@frankc: No sé si el 'str1.rfind (str2) == 0' compararía hacia adelante o hacia atrás. Si primero verificamos que las cuerdas tengan la misma longitud, entonces solo hay una posición para verificar, así que vale la pena intentarlo. De hecho, técnicamente no sé si 'std :: equal' va hacia adelante o hacia atrás cuando se aplica a un iterador de acceso aleatorio, pero tengo una sospecha bastante fuerte ... –

+0

no es la parte aleatoria del iterador, es el hecho de que 'rbegin'and' rend' return * reverse * iterators que confirma su sospecha! Gracias, estoy teniendo un momento de "Por qué no pensé en esto" ... – rubenvb

2

Si quiere revertirlo primero, sugeriría reverse() from para invertir primero la cadena, luego comience a comparar usando string.compare() o use su propio algoritmo. Sin embargo, reverse() lleva un tiempo, y es un procesador intensivo, por lo que sugiero su propia función para manejar este. Comience un ciclo con i igual a string.length(), y luego cuente atrás usando --i y 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); 
+0

Creo que te refieres a 'i> = 0', y a partir de' length() - 1'. –

+0

Y pasaría las cadenas como 'const &'; no tiene sentido copiarlos. – MSalters

0

Usted debe escribir su propia función para eso. Podrías revertir como dice Lost, pero eso no sería una optimización a menos que mantengas esa secuencia invertida y donde compares varias veces. Incluso entonces, no sería una mejora sobre la escritura propia que simplemente itere las cadenas en reversa.

3

Puede usar std :: equal en combinación con std :: basic_string :: reverse_iterator (rbegin, rend).

Sin embargo, es relevante solo si las cadenas tienen la misma longitud (por lo que primero debe verificar los tamaños) y solo para la igualdad de las cadenas (ya que la diferencia más significativa será la última comparada al iterar).

Ejemplo:

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

veo dos opciones:

  1. escribir su propia función de comparación y llamar a eso.

  2. Escriba una clase contenedora alrededor de std :: cadena e implemente operator== para que esa clase tenga el comportamiento que desea.

El segundo es probablemente excesivo.

3

Dependiendo de cuánto tiempo son las cadenas (y su compilador), es mejor que se quede con operator==. En Visual C++ v10, eso se reduce a una llamada memcmp a través de char_traits::compare, que (cuando está optimizado) va a comparar los intervalos de bytes de destino en fragmentos, probablemente tantos bytes a la vez como caben en un registro (4/8 para 32/64 bits).

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

Mientras tanto, std::equal (la alternativa más bonito) hace un byte a byte de comparación. ¿Alguien sabe si esto se optimizará de la misma manera ya que son iteradores inversos? En el mejor de los casos, el manejo de la alineación es más complejo ya que el inicio del rango no está garantizado bien alineado.

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

Véase la respuesta de @ greyfade here por algún color en GCC.

Cuestiones relacionadas