从string中删除前导和尾随空格

如何从C ++中的string对象中删除空格。
例如,如何从下面的string对象中删除前导和尾随空格。

//Original string: " This is a sample string " //Desired string: "This is a sample string" 

据我所知,string类没有提供任何删除前导和尾随空格的方法。

要增加这个问题,如何扩展这个格式来处理string之间的额外空格。 例如,

 // Original string: " This is a sample string " // Desired string: "This is a sample string" 

使用解决scheme中提到的string方法,我可以想到分两步做这些操作。

  1. 删除前导和尾随空格。
  2. 在单词边界重复使用find_first_of,find_last_of,find_first_not_of,find_last_not_of和substr ,以获得所需的格式。

这就是所谓的修剪。 你想使用find_first_not_of来得到第一个非空白字符的索引,然后find_last_not_of从非空白的结尾得到索引。 有了这些,使用substr获取没有周围空白的子string。

为了回应你的编辑,我不知道这个术语,但是我会猜测一些与“减less”有关的东西,所以这就是我所说的。 :)(注意,我已经改变了空白是一个参数,为了灵活性)

 #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; } 

结果:

 [太多空间]  
 [太多空间]  
 [太太多空间]  
 [一  
二]  

虽然如果你可以提升 ,我会推荐它。

从一行std :: string中轻松删除前导,尾随和额外的空格

 value = std::regex_replace(value, std::regex("^ +| +$|( ) +"), "$1"); 

只去除前导空格

 value.erase(value.begin(), std::find_if(value.begin(), value.end(), std::bind1st(std::not_equal_to<char>(), ' '))); 

要么

 value = std::regex_replace(value, std::regex("^ +"), ""); 

只去除尾随空格

 value.erase(std::find_if(value.rbegin(), value.rend(), std::bind1st(std::not_equal_to<char>(), ' ')).base(), value.end()); 

要么

 value = std::regex_replace(value, std::regex(" +$"), ""); 

只删除额外的空间

 value = regex_replace(value, std::regex(" +"), " "); 

提升string修剪algorithm

我目前正在使用这些function:

 // 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); } 

这是我的解决scheme,剥离的领先和尾随空间…

 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); 

结果是“Plamen”

jon-hansonbuild议使用boost的修剪前后空格示例(仅删除尾随和空格):

 #include <boost/algorithm/string/trim.hpp> std::string str = " test "; boost::algorithm::trim ( str ); 

结果在"test"

也有

  • trim_left导致"test "
  • trim_right导致" test"
 /// 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); } 

在上面的代码中,isSpace()函数是一个布尔函数,它告诉一个字符是否是一个空格,你可以实现这个函数来反映你的需要,或者只需要从“ctype.h”中调用isspace() 。

使用标准库有很多好处,但必须注意一些导致exception的特殊情况。 例如,没有一个答案涵盖了C ++string有一些Unicode字符的情况。 在这种情况下,如果使用函数isspace ,将抛出exception。

我一直在使用下面的代码来修剪string和其他一些可能派上用场的操作。 这个代码的主要优点是:速度非常快(比我所testing过的任何代码都快),它只使用标准库,并且不会导致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; } } 

这里是你如何做到这一点:

 std::string & trim(std::string & str) { return ltrim(rtrim(str)); } 

支持function是:

 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; } 

一旦你把所有的东西都放好了,你也可以这样写:

 std::string trim_copy(std::string const & str) { auto s = str; return ltrim(rtrim(s)); } 

尝试这个

我已经testing了这一切,这一切工作。 所以这个方法的processInput只是要求用户input一些东西,它会返回一个内部没有多余空格的string,在开始或结束时也没有额外的空格。 希望这可以帮助。 (也放了一堆评论,使其易于理解)。

你可以看到如何在底部的main()中实现它

 #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; } 
  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); 

删除成语呢?

 std::string s("..."); s.erase( std::remove(s.begin(), s.end(), ' '), s.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()); } 
 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); } 

对于前后空格,如何:

 string string_trim(const string& in) { stringstream ss; string out; ss << in; ss >> out; return out; } 

或者为了一句话:

 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); } 

修剪前导和尾随空格的示例

 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); 

要么

 trimmedSring = aString.substr(aString.find_first_not_of(' '), (aString.find_last_not_of(' ') - aString.find_first_not_of(' ')) + 1); 

我的这个问题的解决scheme不使用任何STL方法,但只有C ++string自己的方法如下:

 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; } 

我已经使用这个方法来传递LeetCode问题在一个string中的反向字

 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"); }