我目前正在使用以下代码在我的程序中右修剪所有std::字符串:
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);
它工作得很好,但我想知道是否有一些最终情况下它可能会失败?
当然,有优雅的选择和左修剪解决方案的答案是受欢迎的。
我目前正在使用以下代码在我的程序中右修剪所有std::字符串:
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);
它工作得很好,但我想知道是否有一些最终情况下它可能会失败?
当然,有优雅的选择和左修剪解决方案的答案是受欢迎的。
当前回答
你所做的是好的,是稳健的。我用同样的方法已经很长时间了,我还没有找到一个更快的方法:
const char* ws = " \t\n\r\f\v";
// trim from end of string (right)
inline std::string& rtrim(std::string& s, const char* t = ws)
{
s.erase(s.find_last_not_of(t) + 1);
return s;
}
// trim from beginning of string (left)
inline std::string& ltrim(std::string& s, const char* t = ws)
{
s.erase(0, s.find_first_not_of(t));
return s;
}
// trim from both ends of string (right then left)
inline std::string& trim(std::string& s, const char* t = ws)
{
return ltrim(rtrim(s, t), t);
}
通过提供要修剪的字符,您可以灵活地修剪非空白字符,并高效地只修剪您想修剪的字符。
其他回答
我想如果你开始询问修剪字符串的“最佳方式”,我会说一个好的实现将是:
不分配临时字符串 有过载的地方修剪和复制修剪 可以很容易地定制接受不同的验证序列/逻辑
显然,有太多不同的方法来解决这个问题,这绝对取决于你真正需要什么。然而,C标准库在<string.h>中仍然有一些非常有用的函数,比如memchr。C仍然被认为是IO的最佳语言是有原因的——它的标准库是纯粹的效率。
inline const char* trim_start(const char* str)
{
while (memchr(" \t\n\r", *str, 4)) ++str;
return str;
}
inline const char* trim_end(const char* end)
{
while (memchr(" \t\n\r", end[-1], 4)) --end;
return end;
}
inline std::string trim(const char* buffer, int len) // trim a buffer (input?)
{
return std::string(trim_start(buffer), trim_end(buffer + len));
}
inline void trim_inplace(std::string& str)
{
str.assign(trim_start(str.c_str()),
trim_end(str.c_str() + str.length()));
}
int main()
{
char str [] = "\t \nhello\r \t \n";
string trimmed = trim(str, strlen(str));
cout << "'" << trimmed << "'" << endl;
system("pause");
return 0;
}
我不确定您的环境是否相同,但在我的环境中,空字符串情况将导致程序中止。我要么用if(!s.empty())包装这个擦除调用,要么像前面提到的那样使用Boost。
你所做的是好的,是稳健的。我用同样的方法已经很长时间了,我还没有找到一个更快的方法:
const char* ws = " \t\n\r\f\v";
// trim from end of string (right)
inline std::string& rtrim(std::string& s, const char* t = ws)
{
s.erase(s.find_last_not_of(t) + 1);
return s;
}
// trim from beginning of string (left)
inline std::string& ltrim(std::string& s, const char* t = ws)
{
s.erase(0, s.find_first_not_of(t));
return s;
}
// trim from both ends of string (right then left)
inline std::string& trim(std::string& s, const char* t = ws)
{
return ltrim(rtrim(s, t), t);
}
通过提供要修剪的字符,您可以灵活地修剪非空白字符,并高效地只修剪您想修剪的字符。
我喜欢tzaman的解决方案,唯一的问题是它不修剪只包含空格的字符串。
为了纠正这1个缺陷,在2个微调行之间添加str.clear()
std::stringstream trimmer;
trimmer << str;
str.clear();
trimmer >> str;
c++ 11中还加入了正则表达式模块,当然可以用它来修饰开头或结尾的空格。
也许是这样的:
std::string ltrim(const std::string& s)
{
static const std::regex lws{"^[[:space:]]*", std::regex_constants::extended};
return std::regex_replace(s, lws, "");
}
std::string rtrim(const std::string& s)
{
static const std::regex tws{"[[:space:]]*$", std::regex_constants::extended};
return std::regex_replace(s, tws, "");
}
std::string trim(const std::string& s)
{
return ltrim(rtrim(s));
}