我目前正在使用以下代码在我的程序中右修剪所有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);
它工作得很好,但我想知道是否有一些最终情况下它可能会失败?
当然,有优雅的选择和左修剪解决方案的答案是受欢迎的。
当前回答
我知道这是一个非常老的问题,但我已经为您的问题添加了几行代码,它从两端删除了空白。
void trim(std::string &line){
auto val = line.find_last_not_of(" \n\r\t") + 1;
if(val == line.size() || val == std::string::npos){
val = line.find_first_not_of(" \n\r\t");
line = line.substr(val);
}
else
line.erase(val);
}
其他回答
我想如果你开始询问修剪字符串的“最佳方式”,我会说一个好的实现将是:
不分配临时字符串 有过载的地方修剪和复制修剪 可以很容易地定制接受不同的验证序列/逻辑
显然,有太多不同的方法来解决这个问题,这绝对取决于你真正需要什么。然而,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;
}
我喜欢tzaman的解决方案,唯一的问题是它不修剪只包含空格的字符串。
为了纠正这1个缺陷,在2个微调行之间添加str.clear()
std::stringstream trimmer;
trimmer << str;
str.clear();
trimmer >> str;
str.erase(0, str.find_first_not_of("\t\n\v\f\r ")); // left trim
str.erase(str.find_last_not_of("\t\n\v\f\r ") + 1); // right trim
在网上试试!
这太烦人了,我
必须谷歌它 发现我必须使用火箭科学 字符串中没有简单的trim/toupper函数
对我来说,这是最快的解决方法:
CString tmp(line.c_str());
tmp = tmp.Trim().MakeLower();
string buffer = tmp;
我可以使用lambda ops,迭代器,以及所有的东西,这很酷。但我只需要处理一个字符串而不是一个字符…
For what it's worth, here is a trim implementation with an eye towards performance. It's much quicker than many other trim routines I've seen around. Instead of using iterators and std::finds, it uses raw c strings and indices. It optimizes the following special cases: size 0 string (do nothing), string with no whitespace to trim (do nothing), string with only trailing whitespace to trim (just resize the string), string that's entirely whitespace (just clear the string). And finally, in the worst case (string with leading whitespace), it does its best to perform an efficient copy construction, performing only 1 copy and then moving that copy in place of the original string.
void TrimString(std::string & str)
{
if(str.empty())
return;
const auto pStr = str.c_str();
size_t front = 0;
while(front < str.length() && std::isspace(int(pStr[front]))) {++front;}
size_t back = str.length();
while(back > front && std::isspace(int(pStr[back-1]))) {--back;}
if(0 == front)
{
if(back < str.length())
{
str.resize(back - front);
}
}
else if(back <= front)
{
str.clear();
}
else
{
str = std::move(std::string(str.begin()+front, str.begin()+back));
}
}