std::isgraph确定角色是否具有图形表示,因此您可以使用它来改变Evan 's answer to remove any character that doesn' t从字符串的任一侧获得图形表示 . 结果是一个更优雅的解决方案:
#include <algorithm>
#include <functional>
#include <string>
/**
* @brief Left Trim
*
* Trims whitespace from the left end of the provided std::string
*
* @param[out] s The std::string to trim
*
* @return The modified std::string&
*/
std::string& ltrim(std::string& s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
std::ptr_fun<int, int>(std::isgraph)));
return s;
}
/**
* @brief Right Trim
*
* Trims whitespace from the right end of the provided std::string
*
* @param[out] s The std::string to trim
*
* @return The modified std::string&
*/
std::string& rtrim(std::string& s) {
s.erase(std::find_if(s.rbegin(), s.rend(),
std::ptr_fun<int, int>(std::isgraph)).base(), s.end());
return s;
}
/**
* @brief Trim
*
* Trims whitespace from both ends of the provided std::string
*
* @param[out] s The std::string to trim
*
* @return The modified std::string&
*/
std::string& trim(std::string& s) {
return ltrim(rtrim(s));
}
我们可以从 wsfront 创建一个反向迭代器,并将其用作第二个 find_if_not 中的终止条件,但's only useful in the case of an all-whitespace string, and gcc 4.8 at least isn' t足够聪明,可以用 auto 推断反向迭代器( std::string::const_reverse_iterator )的类型 . 我不知道构造反向迭代器有多贵,所以YMMV在这里 . 通过此更改,代码如下所示:
30 回答
由于添加了back()和pop_back(),因此可以在C 11中更简单地完成此操作 .
我的解决方案基于answer by @Bill the Lizard .
请注意,如果输入字符串只包含空格,则这些函数将返回空字符串 .
EDIT 从第17页开始,删除了标准库的某些部分 . 幸运的是,从c 11开始,我们有lambda这是一个很好的解决方案 .
感谢https://stackoverflow.com/a/44973498/524503提出现代解决方案 .
原始答案:
我倾向于使用这些中的一个来满足我的修剪需求:
他们相当自我解释,工作得很好 .
EDIT :顺便说一句,我在那里有
std::ptr_fun
来帮助消除std::isspace
的歧义,因为实际上有第二个定义支持语言环境 . 这可能是一个演员也一样,但我倾向于更喜欢这个 .EDIT :解决有关通过引用接受参数,修改并返回参数的一些注释 . 我同意 . 我可能更喜欢的实现是两组函数,一组用于就地,另一组用于复制 . 一组更好的例子是:
我保留上面的原始答案,但是为了保持高投票的答案仍然可用 .
我不确定你的环境是否相同,但在我的情况下,空字符串大小写会导致程序中止 . 我会用if(!s.empty())包装那个erase调用,或者如前所述使用Boost .
这是我的版本:
对于它的 Value ,这里是一个关注性能的修剪实现 . 它比我见过的许多其他修剪程序快得多 . 它使用原始c字符串和索引,而不是使用迭代器和std :: finds . 它优化了以下特殊情况:size 0 string(什么都不做),没有要修剪的空格的字符串(什么也不做),只有尾随空格的字符串要修剪(只调整字符串大小),字符串完全是空格(只是清除字符串) . 最后,在最坏的情况下(带有前导空格的字符串),它会尽最大努力执行有效的复制构造,只执行1个副本,然后移动该副本来代替原始字符串 .
上面的方法很棒,但有时候你想要使用函数的组合来实现你的例程所认为的空格 . 在这种情况下,使用仿函数来组合操作会变得混乱,所以我更喜欢一个简单的循环,我可以修改为修剪 . 这是在SO上从C版本复制的略微修改的修剪函数 . 在此示例中,我正在修剪非字母数字字符 .
http://ideone.com/nFVtEo
使用以下代码从
std::strings
(ideone)右侧修剪(尾随)空格和制表符:只是为了 balancer 问题,我也会包含左边的修剪代码(ideone):
这样做的优雅方式可能就像
支持功能实现如下:
一旦你完成所有这些,你也可以这样写:
试试这个,它对我有用 .
由于我想用C 11方法更新我的旧C修剪功能,我已经测试了很多已发布的问题答案 . 我的结论是我保留了旧的C解决方案!
它是最快的一个,甚至添加更多的字符来检查(例如\ r \ n我看到没有用于\ f \ v的用例)仍然比使用算法的解决方案更快 .
此版本修剪内部空白和非字母数字:
在空字符串的情况下,您的代码假定向
string::npos
添加1给出了0.string::npos
是string::size_type
类型,它是无符号的 . 因此,您依赖于添加的溢出行为 .被黑客攻击Cplusplus.com
这适用于null情况 . :-)
c 11:
输出:
使用空字符串也可以正常工作
为噪音贡献我的解决方案 .
trim
默认创建一个新字符串并返回修改后的字符串,而trim_in_place
修改传递给它的字符串 .trim
函数支持c 11移动语义 .我想如果你开始要求修剪字符串的“最好的方法”,我会说一个好的实现将是:
不分配临时字符串
具有就地修剪和复制修剪的重载
可以轻松定制以接受不同的验证序列/逻辑
显然,有太多不同的方法可以解决这个问题,这绝对取决于你实际需要什么 . 但是,C标准库在<string.h>中仍然有一些非常有用的函数,就像memchr一样 . 有一个原因使C仍然被认为是IO的最佳语言 - 它的stdlib是纯粹的效率 .
随着C 11也出现了regular expression模块,当然可以用来修剪前导或尾随空格 .
也许是这样的:
这就是我使用的 . 只需继续从前面移除空间,然后,如果还剩下任何东西,请从后面做同样的事情 .
使用Boost's string algorithms将是最简单的:
str
现在"hello world!"
. 还有trim_left
和trim
,它们修剪两边 .如果您将
_copy
后缀添加到上述任何功能名称,例如trim_copy
,该函数将返回字符串的修剪副本,而不是通过引用修改它 .如果将
_if
后缀添加到上述任何函数名称,例如trim_copy_if
,您可以修剪满足自定义谓词的所有字符,而不仅仅是空格 .我的回答是对这篇文章的top answer进行了改进,修改了控制字符和空格(ASCII table上的0-32和127) .
std::isgraph确定角色是否具有图形表示,因此您可以使用它来改变Evan 's answer to remove any character that doesn' t从字符串的任一侧获得图形表示 . 结果是一个更优雅的解决方案:
Note: 或者你应该能够使用std::iswgraph,如果你需要支持宽字符,但是你还必须编辑这段代码来启用
std::wstring
操作,这是我没有测试的东西(参见std::basic_string的参考页面来探索这个选项) .这就是我想出的:
流提取自动消除空白,因此这就像一个魅力 .
如果我自己这么说的话,也很干净优雅 . ;)
我喜欢tzaman的解决方案,唯一的问题是它不修剪只包含空格的字符串 .
要纠正1个缺陷,请在2条修剪线之间添加str.clear()
修剪C 11实施:
另一种选择 - 从两端删除一个或多个字符 .
派对迟到了,但没关系 . 现在C 11在这里,我们有lambdas和auto变量 . 所以我的版本,也处理所有空格和空字符串,是:
我们可以从
wsfront
创建一个反向迭代器,并将其用作第二个find_if_not
中的终止条件,但's only useful in the case of an all-whitespace string, and gcc 4.8 at least isn' t足够聪明,可以用auto
推断反向迭代器(std::string::const_reverse_iterator
)的类型 . 我不知道构造反向迭代器有多贵,所以YMMV在这里 . 通过此更改,代码如下所示:你在做什么是好的和强大的 . 我已经使用了相同的方法很长一段时间,我还没有找到一个更快的方法:
通过提供要修剪的字符,您可以灵活地修剪非空白字符,并且只能修剪您想要修剪的字符 .
那这个呢...?
注意:我还是比较新的C,所以如果我不在这里,请原谅我 .