删除匹配的字符

时间:2016-05-04 02:29:27

标签: c++

对某些代码有些麻烦。规则是如果两个字符必须匹配,则必须删除重复的字母。因此,例如“通常”将更改为“Usualy”。

代码确实有效,但它没有按照上面提到的那样做。

我将在下面发布代码,评论在问题点上方发表评论。

#include <iostream>
#include <list>
#include <ctype.h>
#include <fstream>

using namespace std;

void printList(const list<char> &myList);
void fillList(list<char> &myList);
void change(list <char> &myList);

void printList(const list<char> &myList)
{
    list<char>::const_iterator itr;
    for (itr = myList.begin(); itr != myList.end(); itr++ )
    {
        cout <<*itr;
    }
    cout << '\n' << endl;
}

void fillList(list<char> &myList)
{
    ifstream file("test.txt");
    string print;
    while(file >> print)
    {
        for (int i = 0; i<=print.length(); i++)
        {
            myList.push_back(print[i]);
        }
        myList.push_back(' ');
    }
}

void change(list <char> &myList)
{
    list<char>::iterator itr;

    //rules are as follows

    //change w with v
    for (itr = myList.begin(); itr != myList.end(); itr++ )
    {
        if (*itr == 'w')
        {
            *itr = 'v';
        }
    }

    // double letter become single letter here
    //PROBLEM IS HERE!
    for (itr = myList.begin(); itr != myList.end(); itr++ )
    {
        std::list<char>::iterator itr2 = itr;
        if(*(++itr2) == *itr)
        {
            myList.remove(*itr);
        }
    }
}

int main ()
{
    list<char> myList;
    ifstream file("test.txt");
    const string print;
    fillList(myList);
    printList(myList);
    change(myList);
    printList(myList);

    return 0;
}

2 个答案:

答案 0 :(得分:-1)

问题是你在使用相同的迭代器遍历它时修改列表:

for (itr = myList.begin(); itr != myList.end(); itr++ )
{
    std::list<char>::iterator itr2 = itr;
    if(*(++itr2) == *itr)
    {
        myList.remove(*itr);
    }
}

你想做更像这样的事情:

for (itr = myList.begin(); itr != myList.end(); )
{
    std::list<char>::iterator before = itr++;
    if(*itr != myList.end() && *before == *itr)
    {
        myList.erase(before);
    }
}

答案 1 :(得分:-1)

list中的第二个循环正在修改iterator,同时迭代它,但您没有更新循环list::erase()来解释它。删除指定的项目后,iterator会向列表中的下一个项目返回++itr2

您也没有考虑到end()可以生成#include <algorithm> void change(std::list<char> &myList) { //rules are as follows //change w with v std::replace(myList.begin(), myList.begin(), 'w', 'v'); // double letter become single letter here list<char>::iterator itr = myList.begin(); while (itr != myList.end()) { std::list<char>::iterator itr2 = itr++; if ((itr != myList.end()) && (*itr2 == *itr)) { myList.erase(itr2); // or: itr = myList.erase(itr); } } } 迭代器,这种取消引用是不安全的。

请改为尝试:

#include <algorithm>

void change(std::list<char> &myList)
{
    //rules are as follows

    //change w with v
    std::replace(myList.begin(), myList.begin(), 'w', 'v');

    // multiple letter become single letter here
    std::list<char>::iterator itr = std::unique(myList.begin(), myList.end());
    myList.erase(itr, myList.end()); 
}

更简单的解决方案是使用std::unique()代替(如果您不介意一次删除3个以上的重复项):

  

从[first,last]范围中删除所有连续的重复元素,并返回范围的新逻辑结尾的过去的迭代器。

<access origin="*" />
<access origin="*://*.googleapis.com/*" subdomains="true" />
<access origin="*://*.gstatic.com/*" subdomains="true" />
<access origin="*://*.google.com/*" subdomains="true" />
<access origin="*://*.googleusercontent.com/*" subdomains="true" />