c - std::string 最好的方法修剪字符串

  显示原文与译文双语对照的内容

我目前正在使用以下代码来right-trim程序中的所有 std::strings:


std::string s;
s.erase(s.find_last_not_of(" nrt")+1);

它工作正常,但我想知道是否有end-cases可能会失败?

当然,优雅的替代品和left-trim解决方案也是欢迎的。

时间:

我倾向于使用这些 3中的一个来满足我的修剪需求:


#include <algorithm> 
#include <functional> 
#include <cctype>
#include <locale>

//trim from start
static inline std::string &ltrim(std::string &s) {
 s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
 return s;
}

//trim from end
static inline std::string &rtrim(std::string &s) {
 s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
 return s;
}

//trim from both ends
static inline std::string &trim(std::string &s) {
 return ltrim(rtrim(s));
}

它们是相当自我解释的并且工作非常好。

编辑:顺便说一句,这里有 std::ptr_fun 来帮助消除歧义,因为实际上有第二个定义支持区域设置。 这可能是一个完全相同的转换,但我倾向于这样做。

使用boost字符串算法的会很容易


#include <boost/algorithm/string.hpp>
using namespace std;
using namespace boost::algorithm;

string str1(" hello world!");
trim(str1);

//str1 is now"hello world!"
//Use trim_right() if only trailing whitespace is to be removed.

我一直在使用以下代码从 std::strings 中删除空格和制表符:


//trim trailing spaces
size_t endpos = str.find_last_not_of(" t");
if( string::npos!= endpos )
{
 str = str.substr( 0, endpos+1 );
}

为了平衡,我也将包括削减代码左边。


//trim leading spaces
size_t startpos = str.find_first_not_of(" t");
if( string::npos!= startpos )
{
 str = str.substr( startpos );
}

我喜欢tzaman的解决方案,惟一的问题是它不修剪包含空格的字符串。

正确, 1缺陷,添加一个 str.clear() 2高枝剪线之间


std::stringstream trimmer;
trimmer <<str;
str.clear();
trimmer>> str;

派对有点晚了,但还不清楚。 现在C++11在这里,我们有lambdas和auto变量。 所以我的版本,也处理all-whitespace和空字符串,是:


#include <cctype>
#include <string>
#include <algorithm>

inline std::string trim(const std::string &s)
{
 auto wsfront=std::find_if_not(s.begin(),s.end(),[](int c){return std::isspace(c);});
 auto wsback=std::find_if_not(s.rbegin(),s.rend(),[](int c){return std::isspace(c);}).base();
 return (wsback<=wsfront? std::string() : std::string(wsfront,wsback));
}

我们可以从 wsfront 生成一个反向迭代器,并将它的用作第二个 find_if_not的终止条件,但这只在all-whitespace字符串的情况下有用,而 gcc 4.8至少不足以推断反向迭代器的类型 std::string::const_reverse_iterator 使用 auto,我不知道构造反向迭代器有多昂贵,所以这里 YMMV 。 有了这种更改,代码如下所示:


inline std::string trim(const std::string &s)
{
 auto wsfront=std::find_if_not(s.begin(),s.end(),[](int c){return std::isspace(c);});
 return std::string(wsfront,std::find_if_not(s.rbegin(),std::string::const_reverse_iterator(wsfront),[](int c){return std::isspace(c);}).base());
}

对于空字符串,代码假定将 1添加到 string::npos 时给出 0. string::npos 类型为 string::size_type,它是无符号的。 因此,你依赖于加法的溢出行为。

Hacked Cplusplus.com


string choppa(const string &t, const string &ws)
{
 string str = t;
 size_t found;
 found = str.find_last_not_of(ws);
 if (found!= string::npos)
 str.erase(found+1);
 else
 str.clear();//str is all whitespace

 return str;
}

对于空情况也适用。 :- )

试试这个,它适合我。


inline std::string trim(std::string& str)
{
str.erase(0, str.find_first_not_of(' '));//prefixing spaces
str.erase(str.find_last_not_of(' ')+1);//surfixing spaces
return str;
}

我基于回答的基于 @Bill的蜥蜴

注意,如果输入字符串只包含空格,则这些函数将返回空字符串。


const std::string StringUtils::WHITESPACE =" nrt";

std::string StringUtils::Trim(const std::string& s)
{
 return TrimRight(TrimLeft(s));
}

std::string StringUtils::TrimLeft(const std::string& s)
{
 size_t startpos = s.find_first_not_of(StringUtils::WHITESPACE);
 return (startpos == std::string::npos)?"" : s.substr(startpos);
}

std::string StringUtils::TrimRight(const std::string& s)
{
 size_t endpos = s.find_last_not_of(StringUtils::WHITESPACE);
 return (endpos == std::string::npos)?"" : s.substr(0, endpos+1);
}

@tzaman 和 @Schoonbrood: 在将>> 操作符从stringstream转换为字符串时很小心,因为修剪的目的可能是剪切字符串。

例如:


string tm("nHello you tthere n");
stringstream mt;
mt <<tm;
tm.clear();
mt>> tm;
cout <<"size" <<tm.size() <<tm <<"n";

输出将是

 
size 5Hello

 

考虑,G 。

...