TheByteMonster
TheByteMonster

Reputation: 21

c++ STL linked list

Hey guys there seems to be an error with my code.

My main problem is with the section where I want to change any occurrence of 'p' followed by a 'h'. In my testing it changes it to a 'q' for some reason, when I want it to change to 'f'.

For convenience the method with the problem is the void change(), in the second for loop.

Can someone please help?

#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

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

    for (itr = myList.begin(); itr != myList.end(); itr++ ) {
        if((*itr == 'p' && ++*itr == 'h')){// rule incomplete ask!
            *itr = 'f';
        }
    }


}

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

    fillList(myList);
    printList(myList);

    change(myList);
    printList(myList);

    return 0;
}

Upvotes: 1

Views: 1336

Answers (2)

ar1a
ar1a

Reputation: 374

It's because you were incrementing the pointers character and not the iterator. You could fix this by doing *++itr instead of ++*itr

I've changed your code up, you can easily make new rules.

//we copy the string because we want to modify it without modifying the original
// http://stackoverflow.com/a/14679003/4376737
std::string find_and_replace(string str, const string& find, const string& replace)
{
  size_t pos = 0;
  while ((pos = str.find(find, pos)) != string::npos) {
    str.replace(pos, find.length(), replace);
    pos += replace.length();
  }

  return std::move(str);
}
void change(list <char> &myList)
{
  list<char> newlist;

  std::stringstream ss;
  for (auto&& it = myList.begin(); it != myList.end(); ++it) {
    if (*it != ' ') {
      ss << *it;
    } else {
      auto&& newstr = find_and_replace(ss.str(), "ph", "f");
      newstr = find_and_replace(newstr, "w", "v");
      for (auto&& ch : newstr) {
        newlist.push_back(ch);
      }
      newlist.push_back(' ');
      std::stringstream().swap(ss); //this clears the stringstream
    }
  }

  myList = newlist;
}

Output:

hamper moshpit phile wwwphwwwf

hamper moshpit file vvvfvvvf

Upvotes: 1

CJCombrink
CJCombrink

Reputation: 3950

The code if((*itr == 'p' && ++*itr == 'h')) does the following:

  1. if value at itr is p
  2. take the value at itr and increment it
    • p + 1 = q

what you need to do is increase the iterator, not the value

if(*itr == 'p') {
    if(itr == myList.end()) break;  // return or do something else
    std::list<char>::iterator itr2 = itr;
    if(*(++itr2) == 'h') {
        // do what you need to 
    }
}

Edit: Fixed issue with random iterator and check if p is last char as pointed out in the comments.

Upvotes: 1

Related Questions