c++ - Cómo crear una nueva cadena sin espacios desde otra cadena usando un bucle
string (3)
Sugiero no usar un lazo hecho a mano.
Puede usar
std::copy_if
en combinación con una expresión lambda para formular su condición.
Esto será más estable que su implementación (¿qué sucede si la longitud de su cadena
s
excede la capacidad de un
int
?).
Creo que también mejora la legibilidad.
#include <algorithm>
#include <iostream>
#include <string>
int main() {
std::string s = "here is some text";
std::string t = "";
auto comp = [&](const char c) { return std::isalpha(c); };
std::copy_if(s.begin(), s.end(), std::back_inserter(t), comp);
std::cout << t << std::endl;
}
Comencé tratando de escribir una función que eliminaría espacios de una cadena, pero ahora que he visto una serie de soluciones de otras personas para ese problema, estoy tratando de entender exactamente qué salió mal en mi código / por qué
std::cout << t << std::endl;
al final no da salida a nada.
Cuando
std::cout << t[count];
durante el ciclo (la declaración que se comenta a continuación) saldría correctamente a la consola:
hereissometext
sin espacios.
Cuando tengo
std::cout << t[0] << std::endl;
al final, genera correctamente
h
,
t[1]
como
e
,
t[2]
como
r
, y así sucesivamente.
Sin embargo, cuando intento generar
t
al final, genera un espacio en blanco y
t.size()
genera
0
.
Soy bastante nuevo en la codificación, así que perdóname si esta es una pregunta completamente obvia.
std::string s = "here is some text";
std::string t = "";
int count = 0;
for (int i = 0; i < s.size(); i++) {
if (std::isalpha(s[i])) {
t[count]+=s[i];
// std::cout << t[count];
count++;
}
}
std::cout << t << std::endl;
Tiene un comportamiento indefinido en su bucle, ya que inserta en una
std::string
usando su
operator[]
sin asegurarse de que tenga el tamaño correcto.
En su lugar, puede usar
t.push_back(s[i]);
que no solo inserta un
char
, sino que también se asegura de que el búfer interno se (re) asigne cuando es demasiado pequeño para la nueva cadena.
Tenga en cuenta además que realmente no necesita la variable de
count
.
std::string
siempre realiza un seguimiento de su longitud, por lo que
t.size()
siempre generará el valor de su
count
actual (una vez que arregle el UB, por supuesto).
Por otro lado, copiar las partes de una secuencia que coinciden con un determinado criterio es una tarea común, y existe una plantilla de biblioteca específica que hace exactamente esto y lo libera de un bucle hecho a mano:
#include <algorithm>
std::copy_if(s.cbegin(), s.cend(), std::back_inserter(t),
[](char c){ return std::isalpha(c); });
Finalmente, también tenga en cuenta el comentario de @MatthieurFoltzer sobre el comportamiento de
std::isalpha
, que podría valer la pena tener en cuenta.
t[count]+=s[i];
Esto no funciona así. Con esto puede cambiar los caracteres existentes de la cadena. Pero como su cadena está vacía, eso causa un comportamiento indefinido. Para agregar a la cadena, cambie esa línea a esto en su lugar:
t += s[i];
E imprimirá la salida deseada de
hereissometext
.
Puede encontrar la documentación del operador
+=
para cadenas
here
.