从字符串中删除空格,不包括 " 和 ' C++ 对之间的部分

Remove whitespace from string excluding parts between pairs of " and ' C++

所以基本上我想做的是从 std::string 对象中删除所有空格,但是不包括语音标记和引号中的部分(所以基本上是字符串),例如:

Hello, World! I am a string

会导致:

Hello,World!Iamastring

但是语音 marks/quote 标记中的内容将被忽略:

"Hello, World!" I am a string

会导致:

"Hello, World!"Iamastring

或者:

Hello,' World! I' am a string

将是:

Hello,' World! I'amastring

是否有一个简单的例程来对字符串执行此操作,可以是内置到标准库中的例程,也可以是如何编写我自己的例程?它不一定是最有效的,因为每次程序 运行s.

时它只会 运行 一次或两次

没有,没有准备好这样的套路

不过您可以自己构建。

您必须遍历字符串并且要使用标志。如果标志为真,则删除空格,如果为假,则忽略它们。当您不在引号中时,该标志为真,否则为假。

这是一个天真的,没有广泛测试的例子:

#include <string>
#include <iostream>
using namespace std;

int main() {
    // we will copy the result in new string for simplicity
    // of course you can do it inplace. This takes into account only
    // double quotes. Easy to extent do single ones though!
    string str("\"Hello, World!\" I am a string");
    string new_str = "";
    // flags for when to delete spaces or not
    // 'start' helps you find if you are in an area of double quotes
    // If you are, then don't delete the spaces, otherwise, do delete
    bool delete_spaces = true, start = false;
    for(unsigned int i = 0; i < str.size(); ++i) {
        if(str[i] == '\"') {
            start ? start = false : start = true;
            if(start) {
                delete_spaces = false;
            }
        }
        if(!start) {
            delete_spaces = true;
        }
        if(delete_spaces) {
            if(str[i] != ' ') {
                new_str += str[i];
            }
        } else {
            new_str += str[i];
        }

    }
    cout << "new_str=|" << new_str << "|\n";
    return 0;
}

输出:

new_str=|"Hello, World!"Iamastring|

哎呀,我花时间写了这个(简单的)版本:

#include <cctype>
#include <ciso646>
#include <iostream>
#include <string>

template <typename Predicate>
std::string remove_unquoted_chars( const std::string& s, Predicate p )
{
  bool skip = false;
  char q = '[=10=]';
  std::string result;

  for (char c : s)
    if (skip) 
    {
      result.append( 1, c );
      skip = false;
    }
    else if (q)
    {
      result.append( 1, c );
      skip = (c == '\');
      if (c == q) q = '[=10=]';
    }
    else 
    {
      if (!std::isspace( c )) 
        result.append( 1, c );
      q = p( c ) ? c : '[=10=]';
    }

  return result;
}

std::string remove_unquoted_whitespace( const std::string& s )
{
  return remove_unquoted_chars( s, []( char c ) -> bool { return (c == '"') or (c == '\''); } );
}

int main()
{
  std::string s;
  std::cout << "s? ";
  std::getline( std::cin, s );
  std::cout << remove_unquoted_whitespace( s ) << "\n";
}

删除单引号或双引号 C 样式字符串中由给定谓词 除外 内容标识的所有字符,注意尊重转义字符。

我们开始吧。我最终遍历了字符串,如果它找到 "',它将翻转忽略标志。如果忽略标志为真且当前字符不是 "',迭代器只会递增,直到到达字符串末尾或找到另一个 "/'。如果忽略标志为 false,如果当前字符为白色space(space、换行符或制表符),它将删除当前字符。

编辑:此代码现在支持忽略转义字符(\"\')并确保以 " 开头的字符串以 " 结尾,并且以 ' 开头的字符串以 ' 结尾,忽略中间的任何其他内容。

#include <iostream>
#include <string>

int main() {
    std::string str("I am some code, with \"A string here\", but not here\\". 'This sentence \" should not end yet', now it should. There is also 'a string here' too.\n");
    std::string::iterator endVal = str.end(); // a kind of NULL pointer
    std::string::iterator type = endVal;      // either " or '
    bool ignore = false; // whether to ignore the current character or not
    for (std::string::iterator it=str.begin(); it!=str.end();)
    {
        // ignore escaped characters
        if ((*it) == '\')
        {
            it += 2;
        }
        else
        {
            if ((*it) == '"' || (*it) == '\'')
            {
                if (ignore) // within a string
                {
                    if (type != endVal && (*it) == (*type))
                    {
                        // end of the string
                        ignore = false;
                        type = endVal;
                    }
                }
                else // outside of a string, so one must be starting.
                {
                    type = it;
                    ignore = true;
                }
                it++;
                //ignore ? ignore = false : ignore = true;
                //type = it;
            }
            else
            {
                if (!ignore)
                {
                    if ((*it) == ' ' || (*it) == '\n' || (*it) == '\t')
                    {
                        it = str.erase(it);
                    }
                    else
                    {
                        it++;
                    }
                }
                else
                {
                    it++;
                }
            }
        }
    }
    std::cout << "string now is: " << str << std::endl;
    return 0;
}

你可以像这样使用 erase-remove 习语

#include <string>
#include <iostream>
#include <algorithm>


int main()
{
    std::string str("\"Hello, World!\" I am a string");

    std::size_t x = str.find_last_of("\"");
    std::string split1 = str.substr(0, ++x);
    std::string split2 = str.substr(x, str.size());

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

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

    std::cout << split1 + split2;
}