sirve que para length comparar ccs array c++ string comparison io string-comparison

c++ - que - La mejor forma de comparar std:: strings



string c++ (6)

¿Cuál es la mejor manera de comparar std::string s? La forma más obvia sería con if / else :

std::string input; std::cin >> input; if ( input == "blahblahblah" ) { // do something. } else if ( input == "blahblah" ) { // do something else. } else if ( input == "blah" ) { // do something else yet. } // etc. etc. etc.

Otra posibilidad es usar un std::map y un switch / case . ¿Cuál es la mejor manera de hacer lotes (como 8, 10, 12+) de estas comparaciones?


"12" no es mucho ... pero de todos modos.

Solo puede usar un switch para tipos integrales ( char , int , etc.), por lo que está fuera de cuestión para std::string . Usar un mapa probablemente sería más legible.

Por otra parte, todo depende de cómo se defina "mejor".


Aquí hay un ejemplo usando std :: map.

#include <map> #include <string> #include <iostream> #include <utility> void first() { std::cout << "first/n"; } void second() { std::cout << "second/n"; } void third() { std::cout << "third/n"; } int main() { typedef void(*StringFunc)(); std::map<std::string, StringFunc> stringToFuncMap; stringToFuncMap.insert(std::make_pair("blah", &first)); stringToFuncMap.insert(std::make_pair("blahblah", &second)); stringToFuncMap.insert(std::make_pair("blahblahblah", &third)); stringToFuncMap["blahblah"](); stringToFuncMap["blahblahblah"](); stringToFuncMap["blah"](); }

La salida es:

second third first

Los beneficios de este enfoque son:

  • Es fácilmente extensible.
  • Te obliga a dividir las rutinas de manejo de cadenas en funciones separadas (programación por intención).
  • La búsqueda de función es O (log n), mientras que su ejemplo es O (n)

Investigue el uso de la función boost :: para hacer que la sintaxis sea un poco más agradable, especialmente con las funciones de los miembros de la clase.


Con 8, 10 e incluso 12 comparaciones, puede seguir usando if ... else if ... esquema, nada malo. Si quieres 100 o algo así, te recomiendo escribir una función que calcule un hash de cadena (incluso si simplemente anulas todos los caracteres, pero sería preferible utilizar otro método bueno para una mejor distribución) y luego cambiaría su resultado como Evan. propuesto. Si la función devuelve números únicos para todas las cadenas de entrada posibles, eso es aún mejor y no requiere comparaciones adicionales.


La respuesta a esta pregunta depende demasiado del problema. Has nombrado dos ejemplos. Puede agregar a sus opciones cosas como tablas hash, expresiones regulares, etc.


Si quiere decir "más eficiente" por "el mejor", lea adelante.

Sugiero usar el siguiente método si realmente hay mucho.
String in Switch es algo que realmente estará en Java 7. (Como parte de Project Coin )

Y de acuerdo con la propuesta , esta es la forma en que el lenguaje Java lo implementará.
Primero, se calcula el valor hash de cada una de las cadenas. Este problema es entonces un problema "switch int", que está disponible en la mayoría de los idiomas actuales y es eficiente. En cada una de las declaraciones de casos, se verifica si realmente se trata de la cadena (en casos muy raros, diferentes cadenas podrían hacer hash con la misma int).
Personalmente, no doy el último paso en la práctica, ya que su necesidad depende de la situación en la que se encuentre el programa específico, es decir, si las cadenas posibles están bajo el control del programador y qué tan sólido debe ser el programa.

Un pseudocódigo de muestra corresponde

String s = ... switch(s) { case "quux": processQuux(s); // fall-through case "foo": case "bar": processFooOrBar(s); break; case "baz": processBaz(s); // fall-through default: processDefault(s); break; }

de la propuesta mencionada para ayudarlo a comprender.

// Advanced example { // new scope for synthetic variables boolean $take_default = false; boolean $fallthrough = false; $default_label: { switch(s.hashCode()) { // cause NPE if s is null case 3482567: // "quux".hashCode() if (!s.equals("quux")) { $take_default = true; break $default_label; } processQuux(s); $fallthrough = true; case 101574: // "foo".hashCode() if (!$fallthrough && !s.equals("foo")) { $take_default = true; break $default_label; } $fallthrough = true; case 97299: // "bar".hashCode() if (!$fallthrough && !s.equals("bar")) { $take_default = true; break $default_label; } processFooOrBar(s); break; case 97307: // "baz".hashCode() if (!s.equals("baz")) { $take_default = true; break $default_label; } processBaz(s); $fallthrough = true; default: $take_default = true; break $default_label; } } if($take_default) processDefault(s); }


usar operator== es bastante bueno, pero si el rendimiento es realmente crítico, puedes mejorarlo según tu caso de uso. Si el objetivo es elegir una de las pocas opciones y realizar una acción específica, puede usar un TRIE . Además, si las cadenas son lo suficientemente diferentes, podría hacer algo como esto:

switch(s[0]) { case ''a'': // only compare to strings which start with an ''a'' if(s == "abcd") { } else if (s == "abcde") { } break; case ''b'': // only compare to strings which start with an ''b'' if(s == "bcd") { } else if (s == "bcde") { } break; default: // we know right away it doesn''t match any of the above 4 choices... }

básicamente use un cierto carácter en la cadena cuya buena singularidad (¡no tiene que ser la primera si todas las cadenas tienen al menos N en longitud cualquier carácter antes de que lo haga N!) para hacer un switch luego hacer una serie de comparaciones en un subconjunto de las cadenas que coinciden con esa característica única