修剪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 <rim(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_left
和trim
,修剪两边。
如果您将_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