Cómo eliminar espacios de un objeto de cadena en C ++.
Por ejemplo, cómo eliminar los espacios iniciales y finales del objeto de cadena siguiente.
//Original string: " This is a sample string "
//Desired string: "This is a sample string"
La clase de cadena, hasta donde yo sé, no proporciona ningún método para eliminar los espacios iniciales y finales.
Para aumentar el problema, cómo extender este formato para procesar espacios adicionales entre palabras de la cadena. Por ejemplo,
// Original string: " This is a sample string "
// Desired string: "This is a sample string"
Usando los métodos de cadena mencionados en la solución, puedo pensar en hacer estas operaciones en dos pasos.
- Elimine los espacios iniciales y finales.
- Utilice find_first_of, find_last_of, find_first_not_of, find_last_not_of y substr , repetidamente en los límites de palabras para obtener el formato deseado.
site_t
sersize_t
? Y creo que donde tienes el comentariono whitespace
significa que la cadena está en blanco o vacía.size_t
error tipográfico y uno por uno en la edición, pero no noté que mi comentario estaba invertido, gracias.Elimina fácilmente los espacios iniciales, finales y adicionales de una cadena std :: en una línea
value = std::regex_replace(value, std::regex("^ +| +$|( ) +"), "$1");
eliminar solo los espacios iniciales
value.erase(value.begin(), std::find_if(value.begin(), value.end(), std::bind1st(std::not_equal_to<char>(), ' ')));
o
value = std::regex_replace(value, std::regex("^ +"), "");
eliminar solo los espacios finales
value.erase(std::find_if(value.rbegin(), value.rend(), std::bind1st(std::not_equal_to<char>(), ' ')).base(), value.end());
o
value = std::regex_replace(value, std::regex(" +$"), "");
eliminando solo espacios adicionales
value = regex_replace(value, std::regex(" +"), " ");
fuente
substr
oerase
).Actualmente estoy usando estas funciones:
// trim from left inline std::string& ltrim(std::string& s, const char* t = " \t\n\r\f\v") { s.erase(0, s.find_first_not_of(t)); return s; } // trim from right inline std::string& rtrim(std::string& s, const char* t = " \t\n\r\f\v") { s.erase(s.find_last_not_of(t) + 1); return s; } // trim from left & right inline std::string& trim(std::string& s, const char* t = " \t\n\r\f\v") { return ltrim(rtrim(s, t), t); } // copying versions inline std::string ltrim_copy(std::string s, const char* t = " \t\n\r\f\v") { return ltrim(s, t); } inline std::string rtrim_copy(std::string s, const char* t = " \t\n\r\f\v") { return rtrim(s, t); } inline std::string trim_copy(std::string s, const char* t = " \t\n\r\f\v") { return trim(s, t); }
fuente
Impulsar el algoritmo de recorte de cuerdas
#include <boost/algorithm/string/trim.hpp> [...] std::string msg = " some text with spaces "; boost::algorithm::trim(msg);
fuente
Esta es mi solución para eliminar los espacios iniciales y finales ...
std::string stripString = " Plamen "; while(!stripString.empty() && std::isspace(*stripString.begin())) stripString.erase(stripString.begin()); while(!stripString.empty() && std::isspace(*stripString.rbegin())) stripString.erase(stripString.length()-1);
El resultado es "Plamen"
fuente
Aquí sabrás como podrás hacerlo:
std::string & trim(std::string & str) { return ltrim(rtrim(str)); }
Y las funciones de apoyo se implementan como:
std::string & ltrim(std::string & str) { auto it2 = std::find_if( str.begin() , str.end() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } ); str.erase( str.begin() , it2); return str; } std::string & rtrim(std::string & str) { auto it1 = std::find_if( str.rbegin() , str.rend() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } ); str.erase( it1.base() , str.end() ); return str; }
Y una vez que tenga todo esto en su lugar, puede escribir esto también:
std::string trim_copy(std::string const & str) { auto s = str; return ltrim(rtrim(s)); }
Prueba esto
fuente
Ejemplo para recortar espacios iniciales y finales siguiendo la sugerencia de jon-hanson de usar boost (solo elimina los espacios finales y pendientes):
#include <boost/algorithm/string/trim.hpp> std::string str = " t e s t "; boost::algorithm::trim ( str );
Resultados en
"t e s t"
También hay
trim_left
resultados en"t e s t "
trim_right
resultados en" t e s t"
fuente
/// strip a string, remove leading and trailing spaces void strip(const string& in, string& out) { string::const_iterator b = in.begin(), e = in.end(); // skipping leading spaces while (isSpace(*b)){ ++b; } if (b != e){ // skipping trailing spaces while (isSpace(*(e-1))){ --e; } } out.assign(b, e); }
En el código anterior, la función isSpace () es una función booleana que indica si un carácter es un espacio en blanco, puede implementar esta función para reflejar sus necesidades, o simplemente llamar a isspace () desde "ctype.h" si lo desea .
fuente
Ejemplo para recortar los espacios iniciales y finales
std::string aString(" This is a string to be trimmed "); auto start = aString.find_first_not_of(' '); auto end = aString.find_last_not_of(' '); std::string trimmedString; trimmedString = aString.substr(start, (end - start) + 1);
O
trimmedSring = aString.substr(aString.find_first_not_of(' '), (aString.find_last_not_of(' ') - aString.find_first_not_of(' ')) + 1);
fuente
El uso de la biblioteca estándar tiene muchas ventajas, pero hay que tener en cuenta algunos casos especiales que provocan excepciones. Por ejemplo, ninguna de las respuestas cubrió el caso en el que una cadena C ++ tiene algunos caracteres Unicode. En este caso, si usa la función isspace , se lanzará una excepción.
He estado usando el siguiente código para recortar las cadenas y algunas otras operaciones que pueden resultar útiles. Los principales beneficios de este código son: es realmente rápido (más rápido que cualquier código que haya probado), solo usa la biblioteca estándar y nunca causa una excepción:
#include <string> #include <algorithm> #include <functional> #include <locale> #include <iostream> typedef unsigned char BYTE; std::string strTrim(std::string s, char option = 0) { // convert all whitespace characters to a standard space std::replace_if(s.begin(), s.end(), (std::function<int(BYTE)>)::isspace, ' '); // remove leading and trailing spaces size_t f = s.find_first_not_of(' '); if (f == std::string::npos) return ""; s = s.substr(f, s.find_last_not_of(' ') - f + 1); // remove consecutive spaces s = std::string(s.begin(), std::unique(s.begin(), s.end(), [](BYTE l, BYTE r){ return l == ' ' && r == ' '; })); switch (option) { case 'l': // convert to lowercase std::transform(s.begin(), s.end(), s.begin(), ::tolower); return s; case 'U': // convert to uppercase std::transform(s.begin(), s.end(), s.begin(), ::toupper); return s; case 'n': // remove all spaces s.erase(std::remove(s.begin(), s.end(), ' '), s.end()); return s; default: // just trim return s; } }
fuente
Este podría ser el más simple de todos.
Puede usar
string::find
ystring::rfind
para buscar espacios en blanco de ambos lados y reducir la cadena.void TrimWord(std::string& word) { if (word.empty()) return; // Trim spaces from left side while (word.find(" ") == 0) { word.erase(0, 1); } // Trim spaces from right side size_t len = word.size(); while (word.rfind(" ") == --len) { word.erase(len, len + 1); } }
fuente
He probado esto, todo funciona. Entonces, este método processInput solo le pedirá al usuario que escriba algo. Devolverá una cadena que no tiene espacios adicionales internamente, ni espacios adicionales al principio o al final. Espero que esto ayude. (también agregue un montón de comentarios para que sea fácil de entender).
puedes ver cómo implementarlo en main () en la parte inferior
#include <string> #include <iostream> string processInput() { char inputChar[256]; string output = ""; int outputLength = 0; bool space = false; // user inputs a string.. well a char array cin.getline(inputChar,256); output = inputChar; string outputToLower = ""; // put characters to lower and reduce spaces for(int i = 0; i < output.length(); i++){ // if it's caps put it to lowercase output[i] = tolower(output[i]); // make sure we do not include tabs or line returns or weird symbol for null entry array thingy if (output[i] != '\t' && output[i] != '\n' && output[i] != 'Ì') { if (space) { // if the previous space was a space but this one is not, then space now is false and add char if (output[i] != ' ') { space = false; // add the char outputToLower+=output[i]; } } else { // if space is false, make it true if the char is a space if (output[i] == ' ') { space = true; } // add the char outputToLower+=output[i]; } } } // trim leading and tailing space string trimmedOutput = ""; for(int i = 0; i < outputToLower.length(); i++){ // if it's the last character and it's not a space, then add it // if it's the first character and it's not a space, then add it // if it's not the first or the last then add it if (i == outputToLower.length() - 1 && outputToLower[i] != ' ' || i == 0 && outputToLower[i] != ' ' || i > 0 && i < outputToLower.length() - 1) { trimmedOutput += outputToLower[i]; } } // return output = trimmedOutput; return output; } int main() { cout << "Username: "; string userName = processInput(); cout << "\nModified Input = " << userName << endl; }
fuente
¿Por qué complicar?
std::string removeSpaces(std::string x){ if(x[0] == ' ') { x.erase(0, 1); return removeSpaces(x); } if(x[x.length() - 1] == ' ') { x.erase(x.length() - 1, x.length()); return removeSpaces(x); } else return x; }
Esto funciona incluso si el impulso fallara, sin expresiones regulares, sin cosas raras ni bibliotecas.
EDITAR: Corrección para el comentario de MM.
fuente
Se introdujo C ++ 17
std::basic_string_view
, una plantilla de clase que se refiere a una secuencia contigua constante de objetos tipo char, es decir, una vista de la cadena. Además de tener una interfaz muy similar astd::basic_string
, tiene dos funciones adicionales:,remove_prefix()
que encoge la vista moviendo su inicio hacia adelante; yremove_suffix()
, que encoge la vista moviendo su extremo hacia atrás. Estos se pueden usar para recortar el espacio inicial y final:#include <string_view> #include <string> std::string_view ltrim(std::string_view str) { const auto pos(str.find_first_not_of(" \t")); str.remove_prefix(pos); return str; } std::string_view rtrim(std::string_view str) { const auto pos(str.find_last_not_of(" \t")); str.remove_suffix(str.length() - pos - 1); return str; } std::string_view trim(std::string_view str) { str = ltrim(str); str = rtrim(str); return str; } int main() { std::string str = " hello world "; auto sv1{ ltrim(str) }; // "hello world " auto sv2{ rtrim(str) }; // " hello world" auto sv3{ trim(str) }; // "hello world" //If you want, you can create std::string objects from std::string_view objects auto s1{ sv1 }; auto s2{ sv2 }; auto s3{ sv3 }; }
Nota:
std::string_view
es una referencia no propietaria, por lo que solo es válida mientras la cadena original aún exista.fuente
char *str = (char*) malloc(50 * sizeof(char)); strcpy(str, " some random string (<50 chars) "); while(*str == ' ' || *str == '\t' || *str == '\n') str++; int len = strlen(str); while(len >= 0 && (str[len - 1] == ' ' || str[len - 1] == '\t' || *str == '\n') { *(str + len - 1) = '\0'; len--; } printf(":%s:\n", str);
fuente
void removeSpaces(string& str) { /* remove multiple spaces */ int k=0; for (int j=0; j<str.size(); ++j) { if ( (str[j] != ' ') || (str[j] == ' ' && str[j+1] != ' ' )) { str [k] = str [j]; ++k; } } str.resize(k); /* remove space at the end */ if (str [k-1] == ' ') str.erase(str.end()-1); /* remove space at the begin */ if (str [0] == ' ') str.erase(str.begin()); }
fuente
string trim(const string & sStr) { int nSize = sStr.size(); int nSPos = 0, nEPos = 1, i; for(i = 0; i< nSize; ++i) { if( !isspace( sStr[i] ) ) { nSPos = i ; break; } } for(i = nSize -1 ; i >= 0 ; --i) { if( !isspace( sStr[i] ) ) { nEPos = i; break; } } return string(sStr, nSPos, nEPos - nSPos + 1); }
fuente
Para espacios iniciales y finales, ¿qué tal:
string string_trim(const string& in) { stringstream ss; string out; ss << in; ss >> out; return out; }
O para una oración:
string trim_words(const string& sentence) { stringstream ss; ss << sentence; string s; string out; while(ss >> s) { out+=(s+' '); } return out.substr(0, out.length()-1); }
fuente
void trimLeftTrailingSpaces(string &input) { input.erase(input.begin(), find_if(input.begin(), input.end(), [](int ch) { return !isspace(ch); })); } void trimRightTrailingSpaces(string &input) { input.erase(find_if(input.rbegin(), input.rend(), [](int ch) { return !isspace(ch); }).base(), input.end()); }
fuente
No
boost
, noregex
, solo lastring
biblioteca. Es así de simple.string trim(const string s) { // removes whitespace characters from beginnig and end of string s const int l = (int)s.length(); int a=0, b=l-1; char c; while(a<l && ((c=s.at(a))==' '||c=='\t'||c=='\n'||c=='\v'||c=='\f'||c=='\r'||c=='\0')) a++; while(b>a && ((c=s.at(b))==' '||c=='\t'||c=='\n'||c=='\v'||c=='\f'||c=='\r'||c=='\0')) b--; return s.substr(a, 1+b-a); }
fuente
En realidad, este es un caso más simple que tener en cuenta varios caracteres de espacios en blanco iniciales y finales. Todo lo que necesita hacer es eliminar los caracteres de espacio en blanco adyacentes duplicados de toda la cadena.
El predicado para el espacio en blanco adyacente sería simplemente:
auto by_space = [](unsigned char a, unsigned char b) { return std::isspace(a) and std::isspace(b); };
y luego puede deshacerse de esos caracteres de espacio en blanco adyacentes duplicados con
std::unique
, y el modismo borrar-eliminar:// s = " This is a sample string " s.erase(std::unique(std::begin(s), std::end(s), by_space), std::end(s)); // s = " This is a sample string "
Esto potencialmente deja un carácter de espacio en blanco adicional en la parte delantera y / o trasera. Esto se puede eliminar con bastante facilidad:
if (std::size(s) && std::isspace(s.back())) s.pop_back(); if (std::size(s) && std::isspace(s.front())) s.erase(0, 1);
Aquí tienes una demostración .
fuente
Mi solución para este problema que no utiliza ningún método STL sino solo los métodos propios de la cadena C ++ es la siguiente:
void processString(string &s) { if ( s.empty() ) return; //delete leading and trailing spaces of the input string int notSpaceStartPos = 0, notSpaceEndPos = s.length() - 1; while ( s[notSpaceStartPos] == ' ' ) ++notSpaceStartPos; while ( s[notSpaceEndPos] == ' ' ) --notSpaceEndPos; if ( notSpaceStartPos > notSpaceEndPos ) { s = ""; return; } s = s.substr(notSpaceStartPos, notSpaceEndPos - notSpaceStartPos + 1); //reduce multiple spaces between two words to a single space string temp; for ( int i = 0; i < s.length(); i++ ) { if ( i > 0 && s[i] == ' ' && s[i-1] == ' ' ) continue; temp.push_back(s[i]); } s = temp; }
He usado este método para pasar un problema de LeetCode Palabras inversas en una cadena
fuente
void TrimWhitespaces(std::wstring& str) { if (str.empty()) return; const std::wstring& whitespace = L" \t"; std::wstring::size_type strBegin = str.find_first_not_of(whitespace); std::wstring::size_type strEnd = str.find_last_not_of(whitespace); if (strBegin != std::wstring::npos || strEnd != std::wstring::npos) { strBegin == std::wstring::npos ? 0 : strBegin; strEnd == std::wstring::npos ? str.size() : 0; const auto strRange = strEnd - strBegin + 1; str.substr(strBegin, strRange).swap(str); } else if (str[0] == ' ' || str[0] == '\t') // handles non-empty spaces-only or tabs-only { str = L""; } } void TrimWhitespacesTest() { std::wstring EmptyStr = L""; std::wstring SpacesOnlyStr = L" "; std::wstring TabsOnlyStr = L" "; std::wstring RightSpacesStr = L"12345 "; std::wstring LeftSpacesStr = L" 12345"; std::wstring NoSpacesStr = L"12345"; TrimWhitespaces(EmptyStr); TrimWhitespaces(SpacesOnlyStr); TrimWhitespaces(TabsOnlyStr); TrimWhitespaces(RightSpacesStr); TrimWhitespaces(LeftSpacesStr); TrimWhitespaces(NoSpacesStr); assert(EmptyStr == L""); assert(SpacesOnlyStr == L""); assert(TabsOnlyStr == L""); assert(RightSpacesStr == L"12345"); assert(LeftSpacesStr == L"12345"); assert(NoSpacesStr == L"12345"); }
fuente
¿Qué pasa con el modismo borrar-eliminar ?
std::string s("..."); s.erase( std::remove(s.begin(), s.end(), ' '), s.end() );
Lo siento. Vi demasiado tarde que no quieres quitar todo espacios en blanco.
fuente