¿Cómo recortar un std::string?

7 minutos de lectura

¿Como recortar un stdstring
Milán Babuškov

Actualmente estoy usando el siguiente código para recortar a la derecha todos los std::strings en mis 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 en los que podría fallar.

Por supuesto, las respuestas con alternativas elegantes y también con la solución de ajuste a la izquierda son bienvenidas.

¿Como recortar un stdstring
leon timmermans

Utilizando Algoritmos de cadena de Boost sería más fácil:

#include <boost/algorithm/string.hpp>

std::string str("hello world! ");
boost::trim_right(str);

str es ahora "hello world!". También hay trim_left y trimque recorta ambos lados.


si agregas _copy sufijo a cualquiera de los nombres de funciones anteriores, por ejemplo trim_copyla función devolverá una copia recortada de la cadena en lugar de modificarla a través de una referencia.

si agregas _if sufijo a cualquiera de los nombres de funciones anteriores, por ejemplo trim_copy_ifpuede recortar todos los caracteres que satisfagan su predicado personalizado, a diferencia de solo los espacios en blanco.

  • ¿Qué utiliza boost para determinar si un carácter es un espacio en blanco?

    – Tomás

    7 de diciembre de 2008 a las 21:22

  • Depende del lugar. Mi configuración regional predeterminada (VS2005, en) significa que se recortan las pestañas, los espacios, los retornos de carro, las líneas nuevas, las pestañas verticales y los avances de formulario.

    – MattyT

    26 de enero de 2009 a las 13:11

  • Ya estoy usando mucho impulso, #include <boost/format.hpp> #include <boost/tokenizer.hpp> #include <boost/lexical_cast.hpp> pero estaba preocupado por el exceso de código para agregar <boost/algorithm/string.hpp> cuando ya hay std::string::erase alternativas basadas. Feliz de informar al comparar compilaciones de MinSizeRel antes y después de agregarlo, ese recorte de impulso no aumentó mi tamaño de código en absoluto (ya debe estar pagando por él en alguna parte) y mi código no está abarrotado con algunas funciones más.

    –Rian Sanderson

    25 de julio de 2011 a las 5:36


  • @MattyT: ¿Qué referencia está usando para esta lista (determinando si un carácter es un espacio en blanco)?

    – Fahim Mitha

    30 de diciembre de 2011 a las 4:04

  • realmente no responde la pregunta que solicita std::string (no para boost ni ninguna otra biblioteca …)

    – hfrmóvil

    4 de noviembre de 2019 a las 14:20

  • si usa basic_string y template en el CharT, puede hacer esto para todas las cadenas, solo use una variable de plantilla para el espacio en blanco para que lo use como ws. técnicamente, en ese momento, podría prepararlo para c ++ 20 y marcarlo constexpr también, ya que esto implica en línea

    – varado

    2 de diciembre de 2019 a las 1:09

  • @Beached de hecho. Sin embargo, es un poco complicado poner una respuesta aquí. He escrito funciones de plantilla para esto y ciertamente es bastante complicado. He probado un montón de enfoques diferentes y todavía no estoy seguro de cuál es el mejor.

    – Galik

    2 de diciembre de 2019 a las 1:18

1647573313 686 ¿Como recortar un stdstring
Bill el lagarto

Use el siguiente código para recortar a la derecha (finales) los espacios y los caracteres de tabulación de std::strings (idea):

// trim trailing spaces
size_t endpos = str.find_last_not_of(" \t");
size_t startpos = str.find_first_not_of(" \t");
if( std::string::npos != endpos )
{
    str = str.substr( 0, endpos+1 );
    str = str.substr( startpos );
}
else {
    str.erase(std::remove(std::begin(str), std::end(str), ' '), std::end(str));
}

Y solo para equilibrar las cosas, también incluiré el código de recorte izquierdo (idea):

// trim leading spaces
size_t startpos = str.find_first_not_of(" \t");
if( string::npos != startpos )
{
    str = str.substr( startpos );
}

  • Esto no detectará otras formas de espacios en blanco… nueva línea, avance de línea, retorno de carro en particular.

    – Tomás

    7 de diciembre de 2008 a las 21:23

  • Derecha. Debe personalizarlo para el espacio en blanco que desea recortar. Mi aplicación particular solo esperaba espacios y tabulaciones, pero puede agregar \n\r para atrapar a los demás.

    – Bill el lagarto

    8 de diciembre de 2008 a las 0:20

  • str.substr(...).swap(str) es mejor. Guardar una tarea.

    – updogliu

    30 de agosto de 2012 a las 8:55


  • @updogliu ¿No usará la asignación de movimiento? basic_string& operator= (basic_string&& str) noexcept; ?

    – nurettina

    8 de octubre de 2013 a las 8:47


  • Esta respuesta no altera las cadenas que son TODOS espacios. Que es un fail.

    –Tom Andersen

    09/04/2014 a las 22:19

Un 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:

#include <cctype>
#include <string>
#include <algorithm>

inline std::string trim(const std::string &s)
{
   auto wsfront=std::find_if_not(s.begin(),s.end(),[](int c){return std::isspace(c);});
   auto wsback=std::find_if_not(s.rbegin(),s.rend(),[](int c){return std::isspace(c);}).base();
   return (wsback<=wsfront ? std::string() : std::string(wsfront,wsback));
}

Podríamos hacer un iterador inverso de wsfront y usar eso 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) con auto. No sé qué tan costoso es construir un iterador inverso, así que YMMV aquí. Con esta alteración, el código se ve así:

inline std::string trim(const std::string &s)
{
   auto  wsfront=std::find_if_not(s.begin(),s.end(),[](int c){return std::isspace(c);});
   return std::string(wsfront,std::find_if_not(s.rbegin(),std::string::const_reverse_iterator(wsfront),[](int c){return std::isspace(c);}).base());
}

  • Esto no detectará otras formas de espacios en blanco… nueva línea, avance de línea, retorno de carro en particular.

    – Tomás

    7 de diciembre de 2008 a las 21:23

  • Derecha. Debe personalizarlo para el espacio en blanco que desea recortar. Mi aplicación particular solo esperaba espacios y tabulaciones, pero puede agregar \n\r para atrapar a los demás.

    – Bill el lagarto

    8 de diciembre de 2008 a las 0:20

  • str.substr(...).swap(str) es mejor. Guardar una tarea.

    – updogliu

    30 de agosto de 2012 a las 8:55


  • @updogliu ¿No usará la asignación de movimiento? basic_string& operator= (basic_string&& str) noexcept; ?

    – nurettina

    8 de octubre de 2013 a las 8:47


  • Esta respuesta no altera las cadenas que son TODOS espacios. Que es un fail.

    –Tom Andersen

    09/04/2014 a las 22:19

1647573314 382 ¿Como recortar un stdstring
jeromey adofo

Prueba esto, me funciona.

inline std::string trim(std::string& str)
{
    str.erase(str.find_last_not_of(' ')+1);         //suffixing spaces
    str.erase(0, str.find_first_not_of(' '));       //prefixing spaces
    return str;
}

  • @rgove Por favor explique. str.find_last_not_of(x) devuelve la posición del primer carácter que no es igual a x. Solo devuelve npos si ningún carácter no coincide con x. En el ejemplo, si no hay espacios de sufijo, devolverá el equivalente de str.length() - 1produciendo esencialmente str.erase((str.length() - 1) + 1). Es decir, a menos que esté terriblemente equivocado.

    – Travis

    30 de octubre de 2013 a las 14:46


  • Esto debería devolver std::string& para evitar invocar innecesariamente al constructor de copias.

    – heksesang

    17/10/2014 a las 10:49

  • Estoy confundido por qué esto devuelve una copia después de modificar el parámetro de retorno.

    – Galik

    18 de junio de 2015 a las 0:51

  • @MiloDC Mi confusión es por qué devolver una copia en lugar de una referencia. Para mí tiene más sentido volver std::string&.

    – Galik

    21 de diciembre de 2017 a las 2:16

  • Si cambia el orden (haga que primero elimine los espacios de sufijo y luego los espacios de prefijo), será más eficiente.

    – CITBL

    7 de enero de 2019 a las 18:05


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad