如何删除基于空格的字符串

时间:2019-10-29 06:42:49

标签: c++ c++11

我有一个std :: string 我想在Newa和Newb这样的两个空格之后保留字符串

std::string a = "Command send SET Command comes here";
std::string b = "Command GET Command comes here"; 

std::string Newa = "SET Command comes here";
std::string Newb = "Command comes here";

我想到的是,我可以做两次std::string::find(' ')并使用std::string::substr来获得理想的结果。

我们能以更精致的方式做到吗?

4 个答案:

答案 0 :(得分:5)

以下是更通用的方法。 find_n返回与需要搜索的第n个元素匹配的元素之后的迭代器。它可以用于在两个空格,三个空格等之间进行拆分。实际上,您可以将其用作其他算法的构造块。如果字符串包含的空格少于两个,则split函数将返回输入字符串。

#include <iostream>

template<class InputIt, class T>
InputIt find_n(InputIt first, InputIt last, const T& value, size_t n)
{
  size_t count{0};
  while (first != last && count < n) {
    if (*first++ == value) ++count;
  }
  return first;
}

std::string split_after_two_spaces(const std::string& s)
{
  const auto it{find_n(s.begin(), s.end(), ' ', 2)};
  if (it != s.end()) {
    return std::string(it, s.end());
  }

  return s;
}

int main()
{
  const std::string a = "Command send SET Command comes here";
  const std::string b = "Command GET Command comes here";
  const std::string c = "Command GET";

  std::cout << split_after_two_spaces(a) << '\n';
  std::cout << split_after_two_spaces(b) << '\n';
  std::cout << split_after_two_spaces(c) << '\n';

  return 0;
}

我想验证与简单的双find()substr()相比,此方法在性能方面有多糟,事实证明,对于较小的字符串,它要快一些,并且对于较长的输入字符串,速度较慢。 std::string::find()的速度将比std::find快,因为它可能已经过优化以专门处理字符串。

更新find_n的以下实现效率更高,但不幸的是,它也更加复杂。从某种意义上说,它具有更好的语义,即它将迭代器返回第n个匹配元素,而不是经过第n个匹配元素的迭代器。

template<class InputIt, class T>
InputIt find_n(InputIt first, InputIt last, const T& value, size_t n)
{
  if (first != last && n > 0)
  {
    size_t count{0};
    do
    {
      first = std::find(first, last, value);
    }
    while (first != last && ++count < n);
  }

  return first;
}

答案 1 :(得分:3)

您可以在sstreamgetline的帮助下进行尝试:

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

int main() {
    string a = "Command send SET Command comes here";
    stringstream ss(a);
    string w1, w2, w3, Newa;
    ss >> w1 >> w2 >> w3;
    getline(ss, Newa); //get rest of the string!
    cout << w3 + Newa << endl;
    return 0;
}
"SET Command comes here" 

答案 2 :(得分:3)

不需要构造sstream,只需使用find()函数两次即可。

下面的函数可以从字符串中删除n个开头的单词(基于空格,但也可以对其进行参数设置)。您所需要做的就是使用find查找第一个空格,用子字符串替换输入字符串(从该空格之后的下一个字符开始),然后根据要删除的单词数重复此过程。

#include <iostream>
#include <string>

std::string removeWords(std::string s, int n) {
    for(int i=0; i<n; ++i) {
        const auto spaceIdx = s.find(' ');
        s = s.substr(spaceIdx+1, s.length());
    }
    return s;
}

int main() {
    std::cout << removeWords("Command send SET Command comes here", 2) << '\n';
    std::cout << removeWords("Command GET Command comes here", 2) << '\n';

    return 0;
}

答案 3 :(得分:1)

嗯,也许我有点误会。我看到许多行的描述,许多行代码,投票和一个可以接受的答案。

但是通常这样的文本替换总是可以单行完成。有专门的功能可用于以下任务:std::regex_replace

对性能没有要求,所以我建议使用专用功能。请查看以下单行代码:

#include <iostream>
#include <iterator>
#include <string>
#include <regex>

int main()
{
    std::string a{"Command send SET Command comes here"};

    std::regex_replace(std::ostreambuf_iterator<char>(std::cout), a.begin(), a.end(), std::regex(R"(.*? .*? (.*$))"), "$1");

    return 0;
}

我想是因为如果它很简单,就不需要进一步的解释了。