Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to delete a string based on spaces

Tags:

c++

c++11

I have a std::string I want to keep the string after two spaces like in Newa and 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";

what comes to my mind is that i can do std::string::find(' ') two times and use std::string::substr to get the desired result.

Can we do it in more refined manner.


2 Answers

The following is a more generalized approach. find_n returns an iterator past the element that matches the n-th element that needs to be searched for. It can be used to split after two spaces, three spaces, etc. You can in fact use it as a building block for other algorithms. The split function will return the input string in case the string contains less than two spaces.

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

I wanted to verify how much worse this approach would be in terms of performance compared to the straightforward double find() and substr() approach, and it turns out to be a bit faster for small strings, and it is slower for longer input strings. std::string::find() is going to be faster than std::find since it is likely to be optimized to deal with strings specifically.

  • Short string benchmark: http://quick-bench.com/sgKeT333zoXYBQS_1EXFzprCNrY
  • Longer string benchmark: http://quick-bench.com/FEhPTU4YfDPvemWMqgg4oTHZlLU

Update: The following implementation of find_n is more efficient, but also a bit more complex unfortunately. It has nicer semantics in the sense that it returns an iterator to the n-th matching element, instead of an iterator one past the n-th matching element.

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;
}
like image 174
Ton van den Heuvel Avatar answered Nov 27 '25 15:11

Ton van den Heuvel


There's no need to construct sstream, you can just use find() function twice.

The function below can remove n first words from your string (based on spaces, but it can also be parametrized). All you need is to find the first space occurence using find, replace input string with a substring (starting from a next character after that space) and repeat the procedure depending on number of words you want to remove.

#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;
}
like image 42
mtszkw Avatar answered Nov 27 '25 17:11

mtszkw



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!