我目前正在使用以下代码在我的程序中右修剪所有std::字符串:

std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);

它工作得很好,但我想知道是否有一些最终情况下它可能会失败?

当然,有优雅的选择和左修剪解决方案的答案是受欢迎的。


当前回答

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());
}

其他回答

我认为在这个例子中使用宏是一个很好的实践:(适用于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!!"
}

http://ideone.com/nFVtEo

std::string trim(const std::string &s)
{
    std::string::const_iterator it = s.begin();
    while (it != s.end() && isspace(*it))
        it++;

    std::string::const_reverse_iterator rit = s.rbegin();
    while (rit.base() != it && isspace(*rit))
        rit++;

    return std::string(it, rit.base());
}

我的答案是对这篇文章的顶部答案的改进,它修剪了控制字符和空格(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的参考页面来探索这个选项)。

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());
}
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

在网上试试!