我目前正在使用以下代码在我的程序中右修剪所有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);
它工作得很好,但我想知道是否有一些最终情况下它可能会失败?
当然,有优雅的选择和左修剪解决方案的答案是受欢迎的。
当前回答
使用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,你可以修剪所有满足自定义谓词的字符,而不是只有空白。
其他回答
我的答案是对这篇文章的顶部答案的改进,它修剪了控制字符和空格(ASCII表上的0-32和127)。
isgraph确定一个字符是否有图形表示,因此您可以使用它来更改Evan的答案,以从字符串的两侧删除任何没有图形表示的字符。结果是一个更优雅的解决方案:
#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));
}
注意:如果你需要支持宽字符,你也可以使用std::iswgraph,但是你也必须编辑这段代码来启用std::wstring操作,这是我还没有测试过的东西(请参阅std::basic_string的参考页面来探索这个选项)。
下面是一个通道(可能是两个通道)的解决方案。它遍历字符串的空白部分两次,非空白部分一次。
void trim(std::string& s) {
if (s.empty())
return;
int l = 0, r = s.size() - 1;
while (l < s.size() && std::isspace(s[l++])); // l points to first non-whitespace char.
while (r >= 0 && std::isspace(s[r--])); // r points to last non-whitespace char.
if (l > r)
s = "";
else {
l--;
r++;
int wi = 0;
while (l <= r)
s[wi++] = s[l++];
s.erase(wi);
}
return;
}
Trim c++ 11实现:
static void trim(std::string &s) {
s.erase(s.begin(), std::find_if_not(s.begin(), s.end(), [](char c){ return std::isspace(c); }));
s.erase(std::find_if_not(s.rbegin(), s.rend(), [](char c){ return std::isspace(c); }).base(), s.end());
}
在空字符串的情况下,你的代码假设将1添加到string::npos得到0。String::npos的类型是String::size_type,无符号。因此,您依赖于加法的溢出行为。
s.erase(0, s.find_first_not_of(" \n\r\t"));
s.erase(s.find_last_not_of(" \n\r\t")+1);