-1

My logic seems to be wrong in my code. The rule states that for every "e" at the end of a 3 or more letter word, the "e" must be removed. So for example "remove" would be changed to "remov" or another example is "ease" would be changed to "eas". I tried using myList.size -1 but i got a compilation error. Can somebody please help?

I will mark down the error spot for convenience.

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

    }

    //remove e at the end of a 3+ letter word
    //PROBLEM HERE
    for (itr = myList.begin(); itr != myList.end(); itr++ )
    {
        std::list<char>::iterator itr2 = myList.size() - 1;
        if(myList.size() > 3 && itr2 == 'e')
        {
            myList.erase(itr2);
        }
    }
}

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

    return 0;
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270

1 Answers1

2

You are using the following logic to remove es.

for (itr = myList.begin(); itr != myList.end(); itr++ )
{
    std::list<char>::iterator itr2 = myList.size() - 1;
    if(myList.size() > 3 && itr2 == 'e')
    {
        myList.erase(itr2);
    }
}

The line

    std::list<char>::iterator itr2 = myList.size() - 1;

leads to compiler error since the RHS of the assignment operator is of type size_t. You cannot use a size_t to initialize an object of type std::list<char>::iterator.

More importantly, you don't seem to have thought through the logic clearly.

To remove an item from the list, it has to meet three criteria.

  1. The item is e.
  2. The item is the last letter of a word.
  3. The word must be of length 3 or greater.

The first check is simple.

if ( *itr == 'e' )

The second check is a little more complex.

auto next = std::next(itr);
if ( *next == '\0' )

The third check is a little bit more complex than either of the first two. Since your list has embedded null characters followed by a space character before the next word starts, you'll need to keep a counter for word length and reset it when you see a space character.

Here's a block of code that implements the above logic:

int wordLength = 1;

// Don't use ++iter in the last clause of the for statement.
// iter is incremented only when the item is not removed.
// It is updated differently when the item is removed.

for (itr = myList.begin(); itr != myList.end(); )
{
   if ( needToRemove(itr, wordLength) )
   {
      // Remove the item.          
      itr = myList.erase(itr);
   }
   else
   {
      ++itr;
      ++wordLength;
   }
   if ( *itr == ' ' )
   {
      // Reset word length. The next character is
      // going to be the start of the next word.
      wordLength = 0;
   }
}

where needToRemove is defined as:

bool needToRemove(list<char>::iterator itr,
                  int wordLength) 
{
   if ( *itr != 'e' || wordLength < 3)
   {
      return false;
   }

   auto next = std::next(itr);
   return (*next == '\0');
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • @R Sahu Can you please explain the second check? That one auto next = std::next(itr); if ( *next == '\0' ) – TheByteMonster May 05 '16 at 04:18
  • @TheByteMonster, `std::next(itr)` returns an iterator that points to the next item of the list. If the next item is not the null character, then the `e` is not the last character of a word. – R Sahu May 05 '16 at 04:21
  • I think you should be checking for ' ' as well as '\0' as each line (and the indiviual words) are space separated. – The Dark May 05 '16 at 04:48
  • @R Sahu I am getting an error on the line where auto next = std::next(itr); return (*next == '\0'); It is telling me next isn't declared in the scope and has no type. While I've got your attention what is the keyword auto mean? – TheByteMonster May 05 '16 at 04:49
  • @TheByteMonster, make sure you use `#include ` and you are compiler is enabled for C++11 features. – R Sahu May 05 '16 at 04:50
  • @R Sahu Sorry but i am still getting thrown an error,even after including the algorithm library. I am using codeblocks with the mingW compiler – TheByteMonster May 05 '16 at 04:53
  • @TheByteMonster, can't help you there. It works for me using g++ 4.8.4 on a Linux desktop. – R Sahu May 05 '16 at 05:01
  • @RSahu so are you saying changing my compiler to g++ would work? – TheByteMonster May 05 '16 at 05:02
  • @TheByteMonster, you'll have to figure out how to enable C++11 features in CodeBlocks. This might help. http://stackoverflow.com/questions/18174988/how-can-i-add-c11-support-to-codeblocks-compiler – R Sahu May 05 '16 at 05:08
  • @RSahu Ahh ok thank you soo much! I managed to get the code running. I never even knew that C++ uses different compilers. I come from a java and vb background – TheByteMonster May 05 '16 at 05:11
  • @TheDark, the newlines are skipped when getting input since the OP uses `file >> print` to read the input. – R Sahu May 05 '16 at 05:24