修剪std :: string的最佳方法是什么?

我目前使用下面的代码来修剪我的程序中的所有std::strings

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

它工作正常,但我想知道是否有一些可能会失败的最终情况?

当然,欢迎使用优雅的替代方案和左修剪解决方案。


编辑自c ++ 17以来,标准库的某些部分被删除。 幸运的是,从c ++ 11开始,我们有lambda,这是一个优秀的解决方案。

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

// trim from start (in place)
static inline void ltrim(std::string &s) {
    s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
        return !std::isspace(ch);
    }));
}

// trim from end (in place)
static inline void rtrim(std::string &s) {
    s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
        return !std::isspace(ch);
    }).base(), s.end());
}

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

// trim from start (copying)
static inline std::string ltrim_copy(std::string s) {
    ltrim(s);
    return s;
}

// trim from end (copying)
static inline std::string rtrim_copy(std::string s) {
    rtrim(s);
    return s;
}

// trim from both ends (copying)
static inline std::string trim_copy(std::string s) {
    trim(s);
    return s;
}

感谢https://stackoverflow.com/a/44973498/524503提出了现代解决方案。

原始答案:

我倾向于使用以下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在那里帮助歧义std::isspace因为实际上有第二个定义支持语言环境。 这可能是一个演员阵容,但我更喜欢这个。

编辑 :要解决一些关于通过引用接受参数,修改并返回它的意见。 我同意。 我可能更喜欢的一个实现是两套函数,一个用于实现,另一个用于复制。 一套更好的例子是:

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

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

// trim from end (in place)
static inline void 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());
}

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

// trim from start (copying)
static inline std::string ltrim_copy(std::string s) {
    ltrim(s);
    return s;
}

// trim from end (copying)
static inline std::string rtrim_copy(std::string s) {
    rtrim(s);
    return s;
}

// trim from both ends (copying)
static inline std::string trim_copy(std::string s) {
    trim(s);
    return s;
}

我保留上面的原始答案,但是为了保持高投票答案仍然可用。


使用Boost的字符串算法将是最简单的:

#include <boost/algorithm/string.hpp>

std::string str("hello world! ");
boost::trim_right(str);

str现在是"hello world!" 。 还有trim_lefttrim ,修剪两边。


如果您将_copy后缀添加到上述任何函数名称(例如trim_copy ,该函数将返回字符串的修剪副本,而不是通过引用修改它。

如果将_if后缀添加到上述任何函数名称(例如trim_copy_if ,则可以修剪所有满足您自定义谓词的字符,而不仅仅是空格。


使用以下代码从std::strings (ideone)中修剪(尾随)空格和制表符:

// trim trailing spaces
size_t endpos = str.find_last_not_of(" t");
size_t startpos = str.find_first_not_of(" t");
if( std::string::npos != endpos )
{
    str = str.substr( 0, endpos+1 );
    str = str.substr( startpos );
}
else {
    str.erase(std::remove(std::begin(str), std::end(str), ' '), std::end(str));
}

为了平衡事情,我还会包含左边的修剪码(ideone):

// trim leading spaces
size_t startpos = str.find_first_not_of(" t");
if( string::npos != startpos )
{
    str = str.substr( startpos );
}
链接地址: http://www.djcxy.com/p/49665.html

上一篇: What's the best way to trim std::string?

下一篇: Enable session cookies for iframe in page in WkWebView / mobile Safari