Actualmente estoy usando el siguiente código para recortar a la derecha todos los std::strings
programas:
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);
Funciona bien, pero me pregunto si hay algunos casos finales donde podría fallar.
Por supuesto, las respuestas con alternativas elegantes y también la solución de ajuste izquierdo son bienvenidas.
std::string
clase, cuando son funciones como estas las que hacen que otros lenguajes sean tan agradables de usar (Python, por ejemplo).Respuestas:
EDITAR Desde c ++ 17, se eliminaron algunas partes de la biblioteca estándar. Afortunadamente, comenzando con c ++ 11, tenemos lambdas que son una solución superior.
Gracias a https://stackoverflow.com/a/44973498/524503 por presentar la solución moderna.
Respuesta original:
Tiendo a usar uno de estos 3 para mis necesidades de recorte:
Se explican por sí mismas y funcionan muy bien.
EDITAR : Por cierto, tengo
std::ptr_fun
que ayudar a desambiguarstd::isspace
porque en realidad hay una segunda definición que admite configuraciones regionales. Podría haber sido un elenco igual, pero me gusta más.EDITAR : para abordar algunos comentarios acerca de aceptar un parámetro por referencia, modificarlo y devolverlo. Estoy de acuerdo. Una implementación que probablemente preferiría sería dos conjuntos de funciones, una para el lugar y otra que hace una copia. Un mejor conjunto de ejemplos sería:
Sin embargo, mantengo la respuesta original anterior para el contexto y en interés de mantener la respuesta votada aún disponible.
fuente
boost::trim
para resolver el problema.Usar los algoritmos de cadena de Boost sería más fácil:
str
es ahora"hello world!"
. También haytrim_left
ytrim
, que recorta ambos lados.Si agrega
_copy
sufijo a cualquiera de los nombres de funciones anteriorestrim_copy
, por ejemplo , la función devolverá una copia recortada de la cadena en lugar de modificarla a través de una referencia.Si agrega
_if
sufijo a cualquiera de los nombres de funciones anteriorestrim_copy_if
, por ejemplo , puede recortar todos los caracteres que satisfagan su predicado personalizado, en lugar de solo espacios en blanco.fuente
Use el siguiente código para recortar a la derecha los espacios (finales) y los caracteres de tabulación de
std::strings
( ideone ):Y solo para equilibrar las cosas, también incluiré el código de ajuste izquierdo ( ideone ):
fuente
str.substr(...).swap(str)
es mejor. Guarda una tarea.basic_string& operator= (basic_string&& str) noexcept;
?Lo que estás haciendo es bueno y robusto. He usado el mismo método durante mucho tiempo y todavía tengo que encontrar un método más rápido:
Al proporcionar los caracteres que se van a recortar, tiene la flexibilidad para recortar caracteres que no sean espacios en blanco y la eficiencia para recortar solo los caracteres que desea recortar.
fuente
trim
, es decir, haga quertrim(ltrim(s, t), t)
sea un poco más eficienteUn poco tarde para la fiesta, pero no importa. Ahora C ++ 11 está aquí, tenemos lambdas y variables automáticas. Entonces, mi versión, que también maneja espacios en blanco y cadenas vacías, es:
Podríamos hacer un iterador inverso
wsfront
y usarlo como la condición de terminación en el segundo,find_if_not
pero eso solo es útil en el caso de una cadena de espacios en blanco, y gcc 4.8 al menos no es lo suficientemente inteligente como para inferir el tipo del iterador inverso (std::string::const_reverse_iterator
) conauto
. No sé lo costoso que es construir un iterador inverso, así que YMMV aquí. Con esta alteración, el código se ve así:fuente
std::isspace
:auto wsfront=std::find_if_not(s.begin(),s.end(),std::isspace);
candidate template ignored: couldn't infer template argument '_Predicate' find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred)
Prueba esto, funciona para mí.
fuente
str.find_last_not_of(x)
Devuelve la posición del primer carácter que no es igual a x. Solo devuelve npos si los caracteres no coinciden con x. En el ejemplo, si no hay espacios de sufijos, devolverá el equivalente destr.length() - 1
, produciendo esencialmentestr.erase((str.length() - 1) + 1).
Eso, a menos que esté terriblemente equivocado.std::string&
.Me gusta la solución de tzaman, el único problema es que no recorta una cadena que contiene solo espacios.
Para corregir ese 1 defecto, agregue un str.clear () entre las 2 líneas de recorte
fuente
ltrim
ortrim
como este.std::stringstream
.http://ideone.com/nFVtEo
fuente
it
) y viceversa: la posición del carácter después de la cual solo hay espacios (rit
); después de eso, devuelve una cadena recién creada == una copia de la parte de la cadena original - una parte basada en esos iteradores ...En el caso de una cadena vacía, su código asume que agregar 1 para
string::npos
dar 0.string::npos
es de tipostring::size_type
, que no está firmado. Por lo tanto, confía en el comportamiento de desbordamiento de la suma.fuente
1
astd::string::npos
debe dar de0
acuerdo con elC++ Standard
. Por lo tanto, es una buena suposición en la que se puede confiar absolutamente.Hackeado de Cplusplus.com
Esto también funciona para el caso nulo. :-)
fuente
rtrim
, noltrim
Con C ++ 17 puede usar basic_string_view :: remove_prefix y basic_string_view :: remove_suffix :
Una buena alternativa:
fuente
Mi solución basada en la respuesta de @Bill the Lizard .
Tenga en cuenta que estas funciones devolverán la cadena vacía si la cadena de entrada contiene nada más que espacios en blanco.
fuente
Mi respuesta es una mejora con respecto a la respuesta principal para esta publicación que recorta los caracteres de control y los espacios (0-32 y 127 en la tabla ASCII ).
std::isgraph
determina si un personaje tiene una representación gráfica, por lo que puede usar esto para alterar la respuesta de Evan para eliminar cualquier personaje que no tenga una representación gráfica a cada lado de una cadena. El resultado es una solución mucho más elegante:Nota: Alternativamente, debería poder usarlo
std::iswgraph
si necesita soporte para caracteres anchos, pero también tendrá que editar este código para habilitar lastd::wstring
manipulación, que es algo que no he probado (consulte la página de referencia parastd::basic_string
explorar esta opción) .fuente
Con C ++ 11 también vino un módulo de expresión regular , que por supuesto se puede usar para recortar espacios iniciales o finales.
Tal vez algo como esto:
fuente
Esto es lo que yo uso. Simplemente siga eliminando espacio desde el frente y luego, si queda algo, haga lo mismo desde atrás.
fuente
fuente
Para lo que vale, aquí hay una implementación optimizada con miras al rendimiento. Es mucho más rápido que muchas otras rutinas de recorte que he visto. En lugar de usar iteradores y std :: find, usa cadenas e índices en bruto. Optimiza los siguientes casos especiales: cadena de tamaño 0 (no hacer nada), cadena sin espacios en blanco para recortar (no hacer nada), cadena con solo espacios en blanco al final para recortar (solo cambiar el tamaño de la cadena), cadena que es completamente un espacio en blanco (solo borrar la cadena) . Y finalmente, en el peor de los casos (cadena con espacios en blanco iniciales), hace todo lo posible para realizar una construcción de copia eficiente, realizando solo 1 copia y luego moviendo esa copia en lugar de la cadena original.
fuente
Una forma elegante de hacerlo puede ser como
Y las funciones de apoyo se implementan como:
Y una vez que tenga todo esto en su lugar, puede escribir esto también:
fuente
Recorte la implementación de C ++ 11:
fuente
Supongo que si comienzas a pedir la "mejor manera" de recortar una cadena, diría que una buena implementación sería aquella que:
Obviamente, hay muchas maneras diferentes de abordar esto y definitivamente depende de lo que realmente necesita. Sin embargo, la biblioteca estándar de C todavía tiene algunas funciones muy útiles en <string.h>, como memchr. Hay una razón por la cual C sigue siendo considerado como el mejor lenguaje para IO: su stdlib es pura eficiencia.
fuente
No estoy seguro de si su entorno es el mismo, pero en el mío, el caso de cadena vacía hará que el programa se cancele. Envolvería esa llamada de borrado con un if (! S.empty ()) o usaría Boost como ya se mencionó.
fuente
Esto es lo que se me ocurrió:
La extracción de flujo elimina los espacios en blanco automáticamente, por lo que esto funciona de maravilla.
Bastante limpio y elegante también, si lo digo yo mismo. ;)
fuente
Aportando mi solución al ruido.
trim
por defecto crea una nueva cadena y devuelve la modificada mientrastrim_in_place
modifica la cadena que se le pasa. Latrim
función admite semántica de movimiento de c ++ 11.fuente
Esto se puede hacer de manera más simple en C ++ 11 debido a la adición de
back()
ypop_back()
.fuente
Aquí está mi versión:
fuente
Los métodos anteriores son geniales, pero a veces desea utilizar una combinación de funciones para lo que su rutina considera espacios en blanco. En este caso, el uso de functores para combinar operaciones puede ser complicado, así que prefiero un bucle simple que pueda modificar para el recorte. Aquí hay una función de recorte ligeramente modificada copiada de la versión C aquí en SO. En este ejemplo, estoy recortando caracteres no alfanuméricos.
fuente
Aquí hay una implementación sencilla. Para una operación tan simple, probablemente no deberías estar usando construcciones especiales. La función isspace () incorporada se encarga de varias formas de caracteres blancos, por lo que debemos aprovecharla. También debe considerar casos especiales donde la cadena está vacía o simplemente un montón de espacios. El recorte hacia la izquierda o hacia la derecha podría derivarse del siguiente código.
fuente
Aquí hay una solución fácil de entender para principiantes que no están acostumbrados a escribir en
std::
todas partes y que aún no están familiarizados con laconst
corrección,iterator
s, STLalgorithm
s, etc.Espero eso ayude...
fuente
Esta versión recorta espacios en blanco internos y no alfanuméricos:
fuente
Otra opción más: elimina uno o más caracteres de ambos extremos.
fuente