찾다

 >  Q&A  >  본문

C++使用STL遇到的问题

目的:去掉std::deque中不符合条件的元素,在下面的代码中,是把大写转成小写,把其他符号去掉。

#include "iostream"
#include "deque"
using namespace std;

int main ()
{
    deque<char> string;
    char ch;
    while((ch = getchar()) != EOF)
        string.push_back(ch);
    
    for (deque<char>::iterator it = string.begin(); it != string.end(); ++it)
    {
        if ('a' <= *it && *it <= 'z')
            continue;
        else if ('A' <= *it && *it <= 'Z')
            *it = tolower(*it);
        else
            string.erase(it);
    }
    
    while (!string.empty())
    {
        cout << string.front();
        string.pop_front();
    }
}

输入:

das ;ds;a ;das; d;as
d;as ;das; ;das

输出:

dasdsadasdasdas;das das

请教下一为何会漏掉某些字符?

阿神阿神2804일 전606

모든 응답(3)나는 대답할 것이다

  • 天蓬老师

    天蓬老师2017-04-17 13:04:06

    迭代器失效,移除容器里不匹配的元素可以先remove_if移动到容器最后然后再调用容器自身的erase批量删除

      using namespace std;
    
      deque<char> in;
      transform(istream_iterator<char>(cin), istream_iterator<char>(), back_inserter(in), tolower);
      in.erase(remove_if(begin(in), end(in), not1(ptr_fun(isalpha))), end(in));
      copy(begin(in), end(in), ostream_iterator<char>(cout));

    如果不需要真正的删除,可以这样

      using namespace std;
    
      deque<char> in;
      transform(istream_iterator<char>(cin), istream_iterator<char>(), back_inserter(in), tolower);
      copy(begin(in), remove_if(begin(in), end(in), not1(ptr_fun(isalpha))), ostream_iterator<char>(cout));

    remove_if、remove返回值是可以删除的元素开始位置

    회신하다
    0
  • PHP中文网

    PHP中文网2017-04-17 13:04:06

    我来跟你解释一下,在两个号的地方,假如现在it指向第一个; 那么它符合删除的条件 erase(it) 。此时it++,但是此时it不再指向第二个; 而是后面的d。因为你erase(it)时,it后的指针都会前移it已经指向第二个; 你在it++怎么可能还指向第二个; 呢。 你在空格分号连用的地方也是因为这个。所以你的程序本身就是错误的,因为它并不会检查每一个字符,每次你erase(it)操作后,其后面的字符不管合不合法都不会进行检查。正确的写法,可以参照如下(仅作为参考依据):

    deque<char>::iterator it = string.begin();
    while(it!= string.end() )
    {
         if ('a' <= *it && *it <= 'z')
            continue;
        else if ('A' <= *it && *it <= 'Z')
            *it = tolower(*it);
        else 
        {
            string.erase(it);
            continue;
        }
        it++;    
    }

    회신하다
    0
  • ringa_lee

    ringa_lee2017-04-17 13:04:06

    调用erase函数后,原来的迭代器it失效,对其的++操作不可预期。

    회신하다
    0
  • 취소회신하다