My find-replace function is broken

6. Write a find-and-replace operation for Documents based on ยง20.6.2.
I've tried to make a find and replace function but it doesn't work. Here's the full code with my own code at the bottom:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190

//
// This is example code from Chapter 20.6.2 "Iteration" of
// "Programming -- Principles and Practice Using C++" by Bjarne Stroustrup
//

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cmath>
#include<sstream>
#include<fstream>
#include<list>


using namespace std;
//------------------------------------------------------------------------------

typedef vector<char> Line;    // a line is a vector of characters

//------------------------------------------------------------------------------

class Text_iterator { // keep track of line and character position within a line
    list<Line>::iterator ln;
    Line::iterator pos;
public:
    typedef forward_iterator_tag iterator_category;
    typedef char value_type;
    typedef size_t difference_type;
    typedef char* pointer;
    typedef char& reference;

    // start the iterator at line ll's character position pp:
    Text_iterator(list<Line>::iterator ll, Line::iterator pp)
        :ln(ll), pos(pp) { }

    char& operator*() { return *pos; }
    list<Line>::iterator getln(){return ln;}
    Text_iterator& operator++();
    Text_iterator& operator+=(int n);
    Text_iterator operator+(int n);
    Text_iterator& operator--();
    bool operator==(const Text_iterator& other) const;
    bool operator!=(const Text_iterator& other) const { return !(*this==other); }
};

//------------------------------------------------------------------------------

Text_iterator& Text_iterator::operator++()
{
    if (pos==(*ln).end()) {
        ++ln;            // proceed to next line
        pos = (*ln).begin();
    }
    ++pos;                // proceed to next character
    return *this;
}
Text_iterator& Text_iterator::operator--(){//my operator
    if(pos==(*ln).begin()){
        --ln;
        pos=(*ln).end();
    }
    --pos;
    return *this;
}
Text_iterator& Text_iterator::operator+=(int n){//my opeartor
    for(int i=0; i<n; ++i)
        ++(*this);
    return *this;
};

Text_iterator Text_iterator::operator+(int n){//my operator
    Text_iterator rvalue=*this;
    for(;n>0; --n){
        ++rvalue;
    }
    return rvalue;
}
//------------------------------------------------------------------------------

bool Text_iterator::operator==(const Text_iterator& other) const
{
    return ln == other.ln && pos == other.pos;
}

//------------------------------------------------------------------------------

struct Document {
    list<Line> line;
    Document() { line.push_back(Line()); }
    Text_iterator begin()      // first character of first line
    { return Text_iterator(line.begin(), line.begin()->begin()); }
    Text_iterator end()        // one beyond the last line
    {
        list<Line>::iterator last = line.end();
        --last;
        return Text_iterator(last, last->end());
    }
};

//------------------------------------------------------------------------------

void print(Document& d)
{
    for (Text_iterator p = d.begin(); p!=d.end(); ++p) cout << *p;
}

//------------------------------------------------------------------------------

template<class Iter> Iter advance(Iter p, int n)
{
    while (n>0) { ++p; --n; }    // go forwards
    return p;
}

//------------------------------------------------------------------------------

void erase_line(Document& d, int n)
{
    if (n<0 || d.line.size()<=n) return;    // ignore out-of-range lines
    d.line.erase(advance(d.line.begin(), n));
}

//------------------------------------------------------------------------------

bool match(Text_iterator first, Text_iterator last, const string& s)
{
    string::const_iterator p;

    for(p = s.begin();
        p != s.end() && first != last && *p == *first;
        ++p, ++first)
    {}

    return p == s.end(); // if we reached end of string, we matched it all
}

//------------------------------------------------------------------------------

Text_iterator find_text(Text_iterator first, Text_iterator last, const string& s)
{
    if (s.size()==0) return last;    // can't find an empty string
    char first_char = s[0];
    while (true) {
        Text_iterator p = find(first,last,first_char);
        if (p==last || match(p,last,s)) return p;
    }
}

//------------------------------------------------------------------------------



istream& operator>>(istream& is, Document &d){
    char c;
    while(is.get(c)){
        d.line.back().push_back(c);
        if(c=='\n'){
            d.line.push_back(Line{});
        }
    }
    if(d.line.back().size())d.line.push_back(Line{});
    return is;
}

Text_iterator find_replace(Text_iterator first, Text_iterator last, const string& s1, const string& s2){//broke
    if(s1.size()==0)return last;
    if(s1==s2)return last;
    Text_iterator p=last;
    while((first=find_text(first,last,s1))!=last){
        p=first;
        list<Line>::iterator ln=p.getln();
        int index=&*p-&(ln->front());
        ln->erase(ln->begin()+index,ln->begin()+index+s1.size());//erase

        for(int i=0;p!=first+s2.size();++p,++i){
            ln->insert(ln->begin()+(&*p-&(ln->front())),s2[i]);//insert
        }
    }
    return p;
}
int main()
{
    ifstream ifs{"doc.txt"};
    Document my_doc;
    while(ifs>>my_doc){}
    find_replace(my_doc.begin(),my_doc.end(),"the","xx");
    print(my_doc);
}
I've tried to make a find and replace function but it doesn't work.

What exactly do you mean by "it doesn't work"?

If the program compiles correctly, please show an example of your input file, what the program outputs with that input, and your desired output.

Otherwise post the complete compile/link errors, all of them, exactly as they appear in your development environment.


I just copied something random from wikipedia to my input file:
"Please use the search box at the top of this page or the links to the right. Feel free to subscribe to our syndicated feeds.
Using?
To fulfill the free license requirements, please read our Reuse guide. You can also request a picture.
Identifying?
Have a browse through Category:Unidentified subjects. If you find something you can identify, write a note on the item's talk page.
Creating?
Check out all you need to know at our Contributing your own work guide.
and more!
To explore more ways you can contribute to this project, check out the Community Portal."
It outputs nothing and freezes the console. My desired output is for it to replace the first string given with the 2nd string given (In this case "the" and "xx").
Also most of the code isn't mine, I just copy and pasted it from the book. The operators I added are +,+=,--.
Use your debugger to step through the code, to find out where it's hanging, and to look at the contents of the memory so that you can figure out why.
@johndoeisabro,
Your code fails whether you call your find and replace function or not - so that isn't the only error. You should fix other things first.

When I tried it it crashed in
void print(Document& d)
... after (successfully) outputting all the text. I suspect that it never stopped at the
p!=d.end()
condition.


Did you write this routine?
1
2
3
4
5
6
7
8
9
Text_iterator& Text_iterator::operator++()
{
    if (pos==(*ln).end()) {
        ++ln;            // proceed to next line
        pos = (*ln).begin();
    }
    ++pos;                // proceed to next character
    return *this;
}

Let's suppose pos==(*ln).end() is true ... you are one beyond the end of the line ... and suppose that is the last actual line of the file.
Then you do
++ln;
taking you one beyond the end of the lines. Then you try to do
pos = (*ln).begin();
I just can't see how that will work.


Topic archived. No new replies allowed.