Comment supprimer des espaces d'un objet chaîne en C++.
Par exemple, comment supprimer les espaces de début et de fin de l'objet string ci-dessous.
//Original string: " This is a sample string "
//Desired string: "This is a sample string"
Autant que je sache, la classe string ne fournit aucune méthode pour supprimer les espaces de début et de fin.
Pour ajouter au problème, comment étendre cette mise en forme pour traiter des espaces supplémentaires entre les mots de la chaîne. Par exemple,
// Original string: " This is a sample string "
// Desired string: "This is a sample string"
En utilisant les méthodes de chaîne mentionnées dans la solution, je peux penser à effectuer ces opérations en deux étapes.
Ceci s'appelle le rognage. Si vous pouvez utiliser Boost , je le recommanderais.
Sinon, utilisez find_first_not_of
pour obtenir l'index du premier caractère autre qu'un espace, puis find_last_not_of
pour obtenir l'index de la fin qui n'est pas un espace. Avec ceux-ci, utilisez substr
pour obtenir la sous-chaîne sans espace blanc.
En réponse à votre modification, je ne connais pas le terme mais je suppose que quelque chose s'apparente à "réduire", c'est ce que j'ai appelé cela. :) (Remarque, j'ai modifié l'espace blanc en paramètre, pour plus de flexibilité)
#include <iostream>
#include <string>
std::string trim(const std::string& str,
const std::string& whitespace = " \t")
{
const auto strBegin = str.find_first_not_of(whitespace);
if (strBegin == std::string::npos)
return ""; // no content
const auto strEnd = str.find_last_not_of(whitespace);
const auto strRange = strEnd - strBegin + 1;
return str.substr(strBegin, strRange);
}
std::string reduce(const std::string& str,
const std::string& fill = " ",
const std::string& whitespace = " \t")
{
// trim first
auto result = trim(str, whitespace);
// replace sub ranges
auto beginSpace = result.find_first_of(whitespace);
while (beginSpace != std::string::npos)
{
const auto endSpace = result.find_first_not_of(whitespace, beginSpace);
const auto range = endSpace - beginSpace;
result.replace(beginSpace, range, fill);
const auto newStart = beginSpace + fill.length();
beginSpace = result.find_first_of(whitespace, newStart);
}
return result;
}
int main(void)
{
const std::string foo = " too much\t \tspace\t\t\t ";
const std::string bar = "one\ntwo";
std::cout << "[" << trim(foo) << "]" << std::endl;
std::cout << "[" << reduce(foo) << "]" << std::endl;
std::cout << "[" << reduce(foo, "-") << "]" << std::endl;
std::cout << "[" << trim(bar) << "]" << std::endl;
}
Résultat:
[too much space]
[too much space]
[too-much-space]
[one
two]
Suppression facile des espaces de début, de fin et extra de std :: string en une seule ligne
value = std::regex_replace(value, std::regex("^ +| +$|( ) +"), "$1");
supprimer uniquement les espaces de début
value.erase(value.begin(), std::find_if(value.begin(), value.end(), std::bind1st(std::not_equal_to<char>(), ' ')));
ou
value = std::regex_replace(value, std::regex("^ +"), "");
supprimer uniquement les espaces de fin
value.erase(std::find_if(value.rbegin(), value.rend(), std::bind1st(std::not_equal_to<char>(), ' ')).base(), value.end());
ou
value = std::regex_replace(value, std::regex(" +$"), "");
supprimer uniquement les espaces supplémentaires
value = regex_replace(value, std::regex(" +"), " ");
J'utilise actuellement ces fonctions:
// 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);
}
#include <boost/algorithm/string/trim.hpp>
[...]
std::string msg = " some text with spaces ";
boost::algorithm::trim(msg);
C'est ma solution pour éliminer les espaces de début et de fin ...
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);
Le résultat est "Plamen"
Voici comment vous pouvez le faire:
std::string & trim(std::string & str)
{
return ltrim(rtrim(str));
}
Et les fonctions de support sont implémentées comme:
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;
}
Et une fois que tous ces éléments sont en place, vous pouvez également écrire ceci:
std::string trim_copy(std::string const & str)
{
auto s = str;
return ltrim(rtrim(s));
}
Essaye ça
Exemple de réduction des espaces de début et de fin suivant la suggestion de jon-hanson d’utiliser le boost (ne supprime que les espaces de fin et en attente):
#include <boost/algorithm/string/trim.hpp>
std::string str = " t e s t ";
boost::algorithm::trim ( str );
Résultats en "t e s t"
Il y a aussi
trim_left
résulte en "t e s t "
trim_right
résulte en " t e s t"
/// 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);
}
Dans le code ci-dessus, la fonction isSpace () est une fonction booléenne qui indique si un caractère est un espace blanc, vous pouvez implémenter cette fonction pour refléter vos besoins ou simplement appeler isspace () depuis "ctype.h" si vous le souhaitez. .
L'utilisation de la bibliothèque standard présente de nombreux avantages, mais vous devez être conscient de certains cas particuliers qui provoquent des exceptions. Par exemple, aucune des réponses ne couvre le cas où une chaîne C++ contient des caractères Unicode. Dans ce cas, si vous utilisez la fonction isspace , une exception sera levée.
J'ai utilisé le code suivant pour couper les chaînes et d'autres opérations qui pourraient s'avérer utiles. Les principaux avantages de ce code sont les suivants: il est très rapide (plus rapide que tout code que j'ai jamais testé), il utilise uniquement la bibliothèque standard et ne provoque jamais d'exception:
#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;
}
}
Exemple de réduction des espaces de début et de fin
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);
OU
trimmedSring = aString.substr(aString.find_first_not_of(' '), (aString.find_last_not_of(' ') - aString.find_first_not_of(' ')) + 1);
J'ai testé cela, tout fonctionne. Donc, cette méthode processInput demandera simplement à l'utilisateur de taper quelque chose. Elle retournera une chaîne qui ne contient aucun espace supplémentaire en interne, ni d'espace supplémentaire au début ou à la fin. J'espère que cela t'aides. (mettez également un tas de commentaires pour le rendre simple à comprendre).
vous pouvez voir comment l'implémenter dans main () en bas
#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;
}
Cela pourrait être le plus simple de tous.
Vous pouvez utiliser string::find
et string::rfind
pour trouver des espaces des deux côtés et réduire la chaîne.
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);
}
}
Pourquoi se compliquer?
std::string removeSpaces(std::string x){
if(x[0] == ' '){ x.erase(0, 1); }
if(x[x.length()-1] == ' '){ x.erase(x.length()-1, x.length()); }
return x;
}
Cela fonctionne même si boost devait échouer, pas de regex, pas de choses étranges ni de bibliothèques.
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);
}
propre et net
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());
}
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());
}
Pour les espaces de début et de fin, que diriez-vous:
string string_trim(const string& in) {
stringstream ss;
string out;
ss << in;
ss >> out;
return out;
}
Ou pour une phrase:
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);
}
Non boost
, pas regex
, juste la bibliothèque string
. C'est si simple.
string trim(const string s) { // removes whitespace characters from beginnig and end of string s
string x = s;
for(int i=0; i<(int)s.length(); i++) {
const int l = (int)x.length()-1;
if(x[l]==' '||x[l]=='\t'||x[l]=='\n'||x[l]=='\v'||x[l]=='\f'||x[l]=='\r'||x[l]=='\0') x.erase(l, 1);
if(x[0]==' '||x[0]=='\t'||x[0]=='\n'||x[0]=='\v'||x[0]=='\f'||x[0]=='\r'||x[0]=='\0') x.erase(0, 1);
}
return x;
}
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);