我目前正在使用以下代码在我的程序中右修剪所有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);
它工作得很好,但我想知道是否有一些最终情况下它可能会失败?
当然,有优雅的选择和左修剪解决方案的答案是受欢迎的。
当前回答
我认为在这个例子中使用宏是一个很好的实践:(适用于c++ 98)
#define TRIM_CHARACTERS " \t\n\r\f\v"
#define TRIM_STRING(given) \
given.erase(given.find_last_not_of(TRIM_CHARACTERS) + 1); \
given.erase(0, given.find_first_not_of(TRIM_CHARACTERS));
例子:
#include <iostream>
#include <string>
#define TRIM_CHARACTERS " \t\n\r\f\v"
#define TRIM_STRING(given) \
given.erase(given.find_last_not_of(TRIM_CHARACTERS) + 1); \
given.erase(0, given.find_first_not_of(TRIM_CHARACTERS));
int main(void) {
std::string text(" hello world!! \t \r");
TRIM_STRING(text);
std::cout << text; // "hello world!!"
}
其他回答
std::string trim( std::string && str )
{
size_t end = str.find_last_not_of( " \n\r\t" );
if ( end != std::string::npos )
str.resize( end + 1 );
size_t start = str.find_first_not_of( " \n\r\t" );
if ( start != std::string::npos )
str = str.substr( start );
return std::move( str );
}
下面是一个简单的实现。对于这样一个简单的操作,您可能不应该使用任何特殊的构造。内置的isspace()函数负责处理各种形式的白色字符,因此我们应该充分利用它。您还必须考虑字符串为空或只是一堆空格的特殊情况。向左或向右修剪可以从下面的代码派生。
string trimSpace(const string &str) {
if (str.empty()) return str;
string::size_type i,j;
i=0;
while (i<str.size() && isspace(str[i])) ++i;
if (i == str.size())
return string(); // empty string
j = str.size() - 1;
//while (j>0 && isspace(str[j])) --j; // the j>0 check is not needed
while (isspace(str[j])) --j
return str.substr(i, j-i+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,你可以修剪所有满足自定义谓词的字符,而不是只有空白。
一种优雅的方法可以是
std::string & trim(std::string & str)
{
return ltrim(rtrim(str));
}
支持功能实现为:
std::string & ltrim(std::string & str)
{
auto it = std::find_if( str.begin() , str.end() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
str.erase( str.begin() , it);
return str;
}
std::string & rtrim(std::string & str)
{
auto it = std::find_if( str.rbegin() , str.rend() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
str.erase( it.base() , str.end() );
return str;
}
一旦你把这些都准备好了,你也可以这样写:
std::string trim_copy(std::string const & str)
{
auto s = str;
return ltrim(rtrim(s));
}
我已经阅读了大部分答案,但没有发现任何人使用istringstream
std::string text = "Let me split this into words";
std::istringstream iss(text);
std::vector<std::string> results((std::istream_iterator<std::string>(iss)),
std::istream_iterator<std::string>());
结果是单词的向量,它可以处理有内部空白的字符串,希望这有帮助。