删除与另一个给定std :: string中的字符匹配的std :: vector <std :: string>中的元素

问题描述

如何删除向量alphabets中与字符串plaintext中的任何字符匹配的元素?

这是我的尝试:

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

当我尝试编译它时。但是我遇到了这个错误:

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,...

解决方法

*it的类型为char,而不是std::string。这就是编译器所抱怨的。因此,您需要按照以下方式将std::string传递给std::find

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

这里是a demo


另外,请注意以下几点:

  • 您可以将std::vector<std::string> alphabets更改为 std::vector<char> alphabets甚至一个std::string作为您的 alphabets包含/表示char为字符串。对于std::string(即alphabets),std::basic_string::find 更适合使用,而不是放在首位使用更一般的std::find
  • 要进行矢量擦除,可以使用erase–remove idiom,或者 从C ++ 20开始,使用std::vector本身的非成员函数,因此 叫 std::erase_if
,

std::find(alphabets.begin(),*it);

alphabets.begin()alphabets.end()std::vector迭代器中的std::string,但是itstd::string迭代器,它对字符进行迭代,这些参数不兼容,如果没有某种转换,则不能在std::find中一起使用。

那是纠正代码的更好方法,那就是将过于复杂的alphabets容器从std::vector<std::string>变成简单的std::string

Live demo

//init
std::string alphabets{"abcdefghiklmnopqrstuvwxyz"}; //<--- simple string

//input
std::string plaintext;
std::cout << "enter plain text: ";
std::cin >> plaintext;

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

这是我的理解:
您有一个说str1的字符串。现在,您又得到了另一个字符串,str2。现在,您要删除str1中存在的str2中的所有字符。

在这种情况下,我建议将输入扫描为字符串而不是向量,然后使用delete循环

for(auto it = str1.begin(); it != str1.end(); it++) {
    if(str2.find(std::string{*it}) != std::string::npos) {
        it = str1.erase(it);
    }
}
,

C ++ 20 oneliner解决方案。

它更多地关注您想要做什么 (它使用std::erase_if是因为我们要根据条件擦除元素,并且它使用std::find来检查该条件),而不是怎么做(实际上没有for循环。

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

int main() {

    // inputs
    // I don't like this alphabet; a std::vector<char> would have been much better
    // and it would allow to remove the ugly [0] in the std::find below
    std::vector<std::string> alphabet{"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
    std::string plaintext{"abcdefghijklmnopq"};


    // the solution is a oneliner
    std::erase_if(alphabet,[&plaintext](auto x){
        return !(std::find(std::begin(plaintext),std::end(plaintext),x[0]) == std::end(plaintext));
    });

    // output to verify the correct result
    for (auto& e : alphabet) { // prints r s t u v w x y z
        std::cout << e << ' ';
    }
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...