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