Trim / 从字符串中删除无用的空格和制表符

Trim / Remove useless whitespace and tab from a string

谁能建议一种从字符串中去除制表符 ("\t"s) 的方法? (std::string)

我知道我可以做很多事情:

str.erase (std::remove (str.begin(), str.end(), ' '), str.end());

但是它去掉了所有的空格。

例如我想要这个:

push int32(45)__WT__ push int32(45) __WT__

变成这样:

push int32(45)

关键字之间只有一个空格的字符串。

感谢期待。

如果您想用单个 space 替换所有连续的白色 space,您可以使用简单的正则表达式轻松实现。如果你的编译器支持当前标准,它应该在标准库中有正则表达式实用程序,但如果你仅限于 c++98,你可以改用外部库。这是一个使用此类库的解决方案:

test = boost::regex_replace(test, boost::regex("\s+"), " ");

I can only use C++98, regex are for C++11

这是一个超高效的就地解决方案,它不需要任何库并在 C++98 中工作:

template<typename FwdIter>
FwdIter replace_whitespace_by_one_space(FwdIter begin, FwdIter end)
{
    FwdIter dst = begin;
IGNORE_LEADING_WHITESPACE:
    if (begin == end) return dst;
    switch (*begin)
    {
    case ' ':
    case '\t':
        ++begin;
        goto IGNORE_LEADING_WHITESPACE;
    }
COPY_NON_WHITESPACE:
    if (begin == end) return dst;
    switch (*begin)
    {
    default:
        *dst++ = *begin++;
        goto COPY_NON_WHITESPACE;
    case ' ':
    case '\t':
        ++begin;
        // INTENTIONAL FALLTHROUGH
    }
LOOK_FOR_NEXT_NON_WHITESPACE:
    if (begin == end) return dst;
    switch (*begin)
    {
    case ' ':
    case '\t':
        ++begin;
        goto LOOK_FOR_NEXT_NON_WHITESPACE;
    default:
        *dst++ = ' ';
        *dst++ = *begin++;
        goto COPY_NON_WHITESPACE;
    }
}

请注意,gotos 通常被认为在有限自动机的生成代码中是完全可以接受的,尽管在这种情况下,我必须承认代码是由我的大脑和手指生成的;)

下面是您可以如何使用建议的解决方案的示例:

int main()
{
    std::string example = "\t\t\tpush \t \t42\t\t\t";
    auto new_end = replace_whitespace_by_one_space(example.begin(), example.end());
    example.erase(new_end, example.end());
    std::cout << "[" << example << "]\n";
}

您可以创建模板 trim 函数,其实现方式与 remove_if

类似
#include <string>
#include <iterator>
#include <iostream>
#include <ctype.h>
#include <sstream>
using namespace std;

template <class ForwardIterator, class OutputIterator, class UnaryPredicate>
void trim (
  ForwardIterator first, ForwardIterator last, OutputIterator result,
  UnaryPredicate pred
) {
  while (first != last && pred(*first))
    first++;
  for (ForwardIterator p = last; first != last; first++) {
    if (pred(*first))
      p = first;
    else {
      if (p != last) {
        *result = *p;
        p = last;
      }
      *result = *first; 
    }
  }
}

inline bool isJunk(char c) {
  return isspace(c);
}

inline string trim_string(string s) {
  ostringstream result;
  trim(s.begin(), s.end(), ostream_iterator<char>(result, ""), isJunk);
  return result.str();
}

int main() {
  cout << trim_string(" What     the    fraaak    ") << "." << endl;
}

输出:

What the fraaak.

对于那些不能使用 C++11 的人,这里有一个简单的非正则表达式解决方案:

void RemoveWhitespace(std::string *str)
{
    // all tabs to spaces
    ReplaceString(str, "\t", " ");

    // all double spaces to single spaces
    while (ReplaceString(str, "  ", " ") != 0); 

    // trim the string
    if (!s.empty())
    {
        if (s.back() == ' ') s.pop_back();
        if (s.front() == ' ') s.erase(s.begin());
    }
}

其中 ReplaceString 可以实现为

// returns the number of replaced substrings
unsigned int ReplaceString(std::string &str, const std::string &search,
                           const std::string &replace)
{
    unsigned int count = 0;

    size_t pos = 0;
    while ((pos = str.find(search, pos)) != std::string::npos)
    {
        str.replace(pos, search.length(), replace);
        pos += replace.length();
        ++count;
    }

    return count;
}