Eliminar espacios de std :: string en C ++

222

¿Cuál es la forma preferida de eliminar espacios de una cadena en C ++? Podría recorrer todos los personajes y construir una nueva cadena, pero ¿hay una mejor manera?

Steve Hanov
fuente

Respuestas:

257

Lo mejor que puede hacer es usar el algoritmo remove_ify el espacio de emisión:

remove_if(str.begin(), str.end(), isspace);

Ahora el algoritmo en sí mismo no puede cambiar el contenedor (solo modificar los valores), por lo que realmente baraja los valores y devuelve un puntero a donde debería estar el final ahora. Entonces tenemos que llamar a string :: erase para modificar realmente la longitud del contenedor:

str.erase(remove_if(str.begin(), str.end(), isspace), str.end());

También debemos tener en cuenta que remove_if hará como máximo una copia de los datos. Aquí hay una implementación de muestra:

template<typename T, typename P>
T remove_if(T beg, T end, P pred)
{
    T dest = beg;
    for (T itr = beg;itr != end; ++itr)
        if (!pred(*itr))
            *(dest++) = *itr;
    return dest;
}
Matt Price
fuente
54
Debido a que 'isspace' tiene sobrecargas, es probable que deba calificar el código genérico para usar :: isspace (la implementación de C que no tiene una configuración regional) o ser recibido con errores crípticos de creación de instancias.
Bklyn
44
Todos: tenga cuidado con el método anterior (las dos líneas simples, no la versión con plantilla, aunque puede tener el mismo problema). Lo usé en un proyecto sin darme cuenta de que no siempre es correcto. Por ejemplo, si le pasa la cadena "1 + 1", devuelve "1 + 11". Cambié al método de @rupello a continuación y funcionó bien para este caso. ¡Feliz codificación!
JoeB
66
@ Joe La respuesta menciona explícitamente que debe llamar erasedespués. Eso devolverá el resultado correcto.
Konrad Rudolph
31
-1 este uso de isspacees UB para todos los juegos de caracteres excepto el ASCII original de 7 bits. C99 §7.4 / 1. que no sorprende mí que ha sido upvoted por una suma de 71 votos por ahora, a pesar de ser muy mal consejo.
Saludos y hth. - Alf
16
Solo para repetir, el código en esta respuesta pasa valores negativos (diferentes de EOF) a isspace, para todos los caracteres no ASCII, con la opción predeterminada de firma en la práctica char. Por lo tanto, tiene un comportamiento indefinido . Lo estoy repitiendo porque sospecho un intento deliberado de ahogar ese hecho en ruido.
Saludos y hth. - Alf
100
std::string::iterator end_pos = std::remove(str.begin(), str.end(), ' ');
str.erase(end_pos, str.end());
Arno
fuente
31
Mi voto positivo por el lenguaje canónico de borrar / eliminar. Se puede convertir en una sola línea: str.erase (std :: remove (str.begin (), str.end (), ''), str.end ());
Bklyn
11
Nota: debe incluir <algorithm>para que esto funcione.
Tara
37

De gamedev

string.erase(std::remove_if(string.begin(), string.end(), std::isspace), string.end());
rupello
fuente
22
Esto no se compilará en implementaciones que cumplan con los estándares debido a las sobrecargas de toma de locación de std :: isspace. Deberá usar :: isspace o realizar algunas maquinaciones ilegibles con std :: bind2nd. ¿No es hermoso el código genérico?
Bklyn
También tenga en cuenta que si alguno de los caracteres es negativo (por ejemplo, un carácter UTF8 cuando se firma el carácter), el uso de ::isspacees UB.
Martin Bonner apoya a Monica el
30

¿Puedes usar Boost String Algo? http://www.boost.org/doc/libs/1_35_0/doc/html/string_algo/usage.html#id1290573

erase_all(str, " "); 
Nemanja Trifunovic
fuente
3
Es más lento que el remove_if(str.begin(), str.end(), isspace);que mencionó Matt Price. No se porque. En realidad, todas las cosas de impulso, que tienen alternativas STL, son más lentas que las correspondientes a gcc (todas las que probé). ¡Algunos de ellos son inmensamente más lentos! (hasta 5 veces en inserciones de mapas desordenados) Tal vez se deba a la memoria caché de la CPU del entorno compartido o algo similar.
Etherealone
16

Para recortar, use algoritmos de cadena de refuerzo :

#include <boost/algorithm/string.hpp>

using namespace std;
using namespace boost;

// ...

string str1(" hello world! ");
trim(str1);      // str1 == "hello world!"
romano
fuente
15

Puede usar esta solución para eliminar un char:

#include <algorithm>
#include <string>
using namespace std;

str.erase(remove(str.begin(), str.end(), char_to_remove), str.end());
usuario2281802
fuente
1
#include <string.h> usando el espacio de nombres estándar;
slackmart
Esta solución es correcta para mí. El de arriba no lo es.
Jason Liu
1
Se debe evitar usar el espacio de nombres estándar. stackoverflow.com/questions/1452721/…
infinitezero
12

Hola, puedes hacer algo así. Esta función elimina todos los espacios.

string delSpaces(string &str) 
{
   str.erase(std::remove(str.begin(), str.end(), ' '), str.end());
   return str;
}

Hice otra función, que elimina todos los espacios innecesarios.

string delUnnecessary(string &str)
{
    int size = str.length();
    for(int j = 0; j<=size; j++)
    {
        for(int i = 0; i <=j; i++)
        {
            if(str[i] == ' ' && str[i+1] == ' ')
            {
                str.erase(str.begin() + i);
            }
            else if(str[0]== ' ')
            {
                str.erase(str.begin());
            }
            else if(str[i] == '\0' && str[i-1]== ' ')
            {
                str.erase(str.end() - 1);
            }
        }
    }
    return str;
}
ddacot
fuente
8
string replaceinString(std::string str, std::string tofind, std::string toreplace)
{
        size_t position = 0;
        for ( position = str.find(tofind); position != std::string::npos; position = str.find(tofind,position) )
        {
                str.replace(position ,1, toreplace);
        }
        return(str);
}

úsalo:

string replace = replaceinString(thisstring, " ", "%20");
string replace2 = replaceinString(thisstring, " ", "-");
string replace3 = replaceinString(thisstring, " ", "+");
SudoBash
fuente
7

Si desea hacer esto con una macro fácil, aquí hay una:

#define REMOVE_SPACES(x) x.erase(std::remove(x.begin(), x.end(), ' '), x.end())

Esto supone que lo has hecho, #include <string>por supuesto.

Llámalo así:

std::string sName = " Example Name ";
REMOVE_SPACES(sName);
printf("%s",sName.c_str()); // requires #include <stdio.h>
Volomike
fuente
55
¿Por qué usarías una macro para esto?
dani
1
Menos tipeo de teclado para una tarea común.
Volomike
3
Igualmente corto para el sitio de llamada es llamar a una función que toma una referencia de valor a una cadena. Las macros pueden tener comportamientos sorprendentes al interactuar con sus argumentos (especialmente con efectos secundarios), pero lo que es peor, si están involucrados en un error, sus nombres no aparecen en los mensajes del compilador, su implementación sí.
Chris Uzdavinis
2

Usé el siguiente trabajo durante mucho tiempo, no estoy seguro de su complejidad.

s.erase(std::unique(s.begin(),s.end(),[](char s,char f){return (f==' '||s==' ');}),s.end());

cuando quieres eliminar el personaje ' 'y algunos, por ejemplo, - usan

s.erase(std::unique(s.begin(),s.end(),[](char s,char f){return ((f==' '||s==' ')||(f=='-'||s=='-'));}),s.end());

Del mismo modo, solo aumente el ||número de caracteres que desea eliminar no es 1

pero como lo mencionaron otros, el idioma de borrar borrado también parece estar bien.

RaGa__M
fuente
1
string removeSpaces(string word) {
    string newWord;
    for (int i = 0; i < word.length(); i++) {
        if (word[i] != ' ') {
            newWord += word[i];
        }
    }

    return newWord;
}

Este código básicamente toma una cadena e itera a través de cada carácter que contiene. Luego verifica si esa cadena es un espacio en blanco, si no lo es, el carácter se agrega a una nueva cadena.

Manzanas crujientes
fuente
1
   #include <algorithm>
   using namespace std;

   int main() {
       .
       .
       s.erase( remove( s.begin(), s.end(), ' ' ), s.end() );
       .
       .
   }

Fuente:

Referencia tomada de este foro.

Juan
fuente
1
Esto realmente no agrega nada más de lo que esta respuesta ya hace. ¿Hay más explicaciones o detalles que pueda agregar para que su respuesta sea de mayor calidad y valga la pena seguir con esta pregunta?
Das_Geek
Creo que es más simple , porque hace lo mismo en una declaración.
John
2
¡Excelente! Luego ponga ese razonamiento como una explicación directamente en su respuesta . La pregunta original tiene más de once años , y sin una justificación, su respuesta podría verse como ruido en comparación con las otras respuestas aceptadas y bien votadas. Tener esa explicación ayudará a evitar que su respuesta sea eliminada.
Das_Geek
Eso sería bueno, pero no pude entender eso, ¿cómo debería poner eso en mi respuesta ... que mi respuesta es mejor que esta respuesta . ? Sería un gran placer poder editar mi respuesta.
John
2
Desafortunadamente, editar su respuesta para agregar ese contenido iría en contra de las pautas de edición , y mi edición probablemente se rechazaría o se revertiría más tarde. Puede usar el primer enlace en este comentario para editar la respuesta usted mismo. Es totalmente aceptable afirmar que cree que su respuesta es mejor que otra, y justificarla. La comunidad decidirá si tienes razón votando a favor o en contra.
Das_Geek
0

En C ++ 20 puede usar la función gratuita std :: erase

std::string str = " Hello World  !";
std::erase(str, ' ');

Ejemplo completo:

#include<string>
#include<iostream>

int main() {
    std::string str = " Hello World  !";
    std::erase(str, ' ');
    std::cout << "|" << str <<"|";
}

Yo imprimo | para que sea obvio que también se elimina el espacio al principio.

nota: esto elimina solo el espacio, no todos los demás caracteres posibles que pueden considerarse espacios en blanco, consulte https://en.cppreference.com/w/cpp/string/byte/isspace

NoSenseEtAl
fuente
0

Elimina todos los caracteres de espacio en blanco , como tabulaciones y saltos de línea (C ++ 11):

string str = " \n AB cd \t efg\v\n";
str = regex_replace(str,regex("\\s"),"");
AnselmRu
fuente
¿Por qué recomendaría este enfoque sobre la respuesta aceptada de @ Matt-Price de hace más de una década?
Jeremy Caney
Deje que todas las soluciones se presenten aquí. Quizás alguien necesite esta solución.
AnselmRu
No estoy discutiendo en contra de eso. Estoy diciendo que facilite a las personas evaluar diferentes enfoques al explicar las diferencias y para qué escenarios podrían ser más adecuados.
Jeremy Caney
1
Probablemente esta solución no sea la más económica, pero le permite deshacerse de todos los caracteres de espacio en blanco '\ s', no solo espacios ''.
AnselmRu
0
  string str = "2C F4 32 3C B9 DE";
  str.erase(remove(str.begin(),str.end(),' '),str.end());
  cout << str << endl;

salida: 2CF4323CB9DE

Kerim FIRAT
fuente
-1
string removespace(string str)
{    
    int m = str.length();
    int i=0;
    while(i<m)
    {
        while(str[i] == 32)
        str.erase(i,1);
        i++;
    }    
}
prueba c
fuente
3
Generalmente se prefiere que agregue una breve explicación a las respuestas del código.
arcyqwerty
1
@test: length()devuelve un size_t, no un int. erase()toma un size_type, no un int. La función probablemente fallará si se encuentran dos espacios consecutivos ya que el índice siempre se incrementa. Si se elimina un espacio, el bucle leerá más allá de los límites de la cadena. Probablemente debería eliminar esta respuesta, ya que necesita mucha ayuda.
jww
-3

Me temo que es la mejor solución que se me ocurre. Pero puede usar reserve () para preasignar la memoria mínima requerida de antemano para acelerar un poco las cosas. Terminará con una nueva cadena que probablemente será más corta pero que ocupará la misma cantidad de memoria, pero evitará reasignaciones.

EDITAR: Dependiendo de su situación, esto puede generar menos gastos generales que los personajes confusos.

Debe probar diferentes enfoques y ver qué es lo mejor para usted: es posible que no tenga ningún problema de rendimiento.

Dave Van den Eynde
fuente
remove_if hace como máximo una copia de cada valor. Entonces, realmente no hay tanta sobrecarga en relación con lo que hay que hacer.
Matt Price