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

时间:2015-02-17 12:37:18

标签: c++ string trim c++98

有人可以建议从字符串中删除制表符(“\ 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)

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

  • __WT__ =无用的空格或标签。

感谢您的期待。

4 个答案:

答案 0 :(得分:2)

  

我只能使用C ++ 98,正则表达式适用于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;
    }
}

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

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

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";
}

答案 1 :(得分:1)

您可以使用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.

答案 2 :(得分:0)

如果要用一个空格替换所有连续的空格,可以使用简单的正则表达式轻松完成。如果您的编译器支持当前标准,它应该在标准库中具有regexp实用程序,但如果您仅限于c ++ 98,则可以使用外部库。这是使用一个这样的库的解决方案:

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

答案 3 :(得分:0)

对于那些不能使用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;
}