c++ stdstring c++-standard-library

c++ - ¿Por qué `std:: string:: find()` no devuelve el iterador final en caso de fallas?



stdstring c++-standard-library (2)

Me parece que el comportamiento de std::string::find es inconsistente con los contenedores estándar de C ++.

P.ej

std::map<int, int> myMap = {{1, 2}}; auto it = myMap.find(10); // it == myMap.end()

Pero por una cuerda,

std::string myStr = "hello"; auto it = myStr.find(''!''); // it == std::string::npos

¿Por qué el myStr.find(''!'') devuelve myStr.end() lugar de std::string::npos ?

Dado que std::string es algo especial en comparación con otros contenedores, me pregunto si hay alguna razón real detrás de esto. (Sorprendentemente, no pude encontrar a nadie cuestionando esto en ninguna parte).


Esto se debe a que std::string tiene dos interfaces:

  • La interfaz general basada en iterador que se encuentra en todos los contenedores
  • La interfaz basada en índices específicos std::string

std::string::find forma parte de la interfaz basada en índices y, por lo tanto, devuelve índices.

Use std::find para usar la interfaz general basada en iterador.

Use std::vector<char> si no desea la interfaz basada en índice (no haga esto).


Para empezar, la interfaz std::string es bien conocida por ser hinchada e inconsistente, vea Gotw84 Herb Sutter sobre este tema. Sin embargo, hay un razonamiento detrás de std::string::find devuelve un índice: std::string::substr . Esta función de miembro de conveniencia opera en índices, p. Ej.

const std::string src = "abcdefghijk"; std::cout << src.substr(2, 5) << "/n";

Podría implementar substr modo que acepte iteradores en la cadena, pero no tendríamos que esperar mucho tiempo para quejas fuertes de que std::string es inutilizable y contraintuitivo. Entonces, dado que std::string::substr acepta índices, ¿cómo encontraría el índice de la primera aparición de ''d'' en la cadena de entrada anterior para imprimir todo a partir de esta subcadena?

const auto it = src.find(''d''); // imagine this returns an iterator std::cout << src.substr(std::distance(src.cbegin(), it));

Esto también podría no ser lo que quieres. Por lo tanto, podemos dejar que std::string::find devuelva un índice, y aquí estamos:

const std::string extracted = src.substr(src.find(''d''));

Si desea trabajar con iteradores, use <algorithm> . Te permiten lo anterior como

auto it = std::find(src.cbegin(), src.cend(), ''d''); std::copy(it, src.cend(), std::ostream_iterator<char>(std::cout));