Search code examples
c++algorithmstdvectorstdstringstd

Delete elements in a std::vector<std::string> which matches with the characters in another given std::string


How can I remove elements in the vector alphabets which matches with any of the characters in the string plaintext?

Here's my attempt:

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

int main()
{
   //init
   std::vector<std::string> alphabets{ "a", "b", "c", "d", "e", "f", "g", "h", "i", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };
   //input
   std::string plaintext;
   std::cout << "enter plain text: ";
   std::cin >> plaintext;

   for (std::string::iterator it = plaintext.begin(); it != plaintext.end(); it++)
   {
      std::vector<std::string>::iterator toErase;
      toErase = std::find(alphabets.begin(), alphabets.end(), *it);
      if (toErase != alphabets.end())
      {
         alphabets.erase(toErase);
      }
   }
}

When I tried to compile it. But I got this error:

17: note:   'std::__cxx11::basic_string<char>' is not derived from
'const std::istreambuf_iterator<_CharT, _Traits>' { return *__it == _M_value; }
...

203 : 5 : note : candidate : 'template<class _CharT, class _Traits> bool 
std::operator==(const std::istreambuf_iterator<_CharT, _Traits>&, const
   std::istreambuf_iterator<_CharT, _Traits>&)'
   operator==(const istreambuf_iterator<_CharT, _Traits> & __a,
      ...

Solution

  • The *it has a type of char not std::string. This is what the compiler complaining about. Therefore you need to pass a std::string to the std::find as follows.

    auto toErase = std::find(alphabets.begin(), alphabets.end(), std::string{ *it });
     //                                                          ^^^^^^^^^^^^^^^^^^
    

    Here is a demo.


    Also, note the followings:

    • You can change the std::vector<std::string> alphabets to a std::vector<char> alphabets or even a single std::string as your alphabets containes/ represents chars as strings. In the case of std::strings (i.e. alphabets), the std::basic_string::find is more appropriate to use, rather than having more general std::find at first place.
    • For vector erase, you could use erase–remove idiom, or since C++20, using non-member function of std::vector itself, so called std::erase_if.