terminate after std::out_of_range, what erase();

In my code there are three uses of the erase function in my procedures. But I keep getting the following error message.

terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::erase
Abort

I have fiddled around with all of them but haven't been able to figure out which one is causing the problem.

trim - - meant to remove num_chars from beginning and end of a string
remove - - remove the to_remove string at all locations in a string
reverse - - reverse the characters in a string

I would really appreciate any help!

void trim(string & line, int num_chars)
{
//Declare Variables
int size;

//Remove beginning characters
line = line.erase(0, num_chars);

//Find line size after removing beginning characters
size= line.size();
size= size-num_chars;

//Remove ending characters
line.erase(size, num_chars);
}

void remove(string & line, string to_remove)
{
//Declare Variables
int size=0, location=0, length=0;
size=line.size();

length=to_remove.size();

//Loop through erasing to_remove string at all locations
while(line.find(to_remove)!= string::npos)
{
//Find location of to_remove string
location = line.find(to_remove);

//Erase to_remove string at location
line.erase(location, length);
}
}

void reverse(string & line)
{
//Declare Variables
int i=0;
int size;
char letter;

//Find size
size=line.size();

//Loop through character movement
while(i<size)
{
//Find initial letter
letter = line.at(0);

//Push back letter to end
line.push_back(letter);

//Remove letter
line.erase(0, 1);

//Increment i
i++;
}
}
Last edited on
I'm sure you realize that the exception is telling you that position + num_char is greater than the length of the string.

If you're using an IDE, you should be able to do two things:
1) When you get the exception, the debugger should display the call stack. That should tell you which function called erase. By setting your stack frame to the calling function, you should be able to examine the contents of position, num_char and the string.
2) You should be able to set a breakpoint on each call to erase and check the values of position, num_char and the string before executing the call.

If you're not using an IDE, then you will need to put some cout statements before each call to erase displaying the value of postion, num_char and string.size().

PLEASE USE CODE TAGS (the <> formatting button) when posting code. It makes your code more readable and makes it easier to respond to your post.
Last edited on
It appears that the function is failing in trim. It repeatedly outputs:

trim info begin chars 20
line size 420
trim info end chars 20size 400

then on the last one it outputs

trim info begin chars 20
line size 0
trim info end chars 20size -20

So is there anyway I can just get it to run through the procedure once?

Also I'm not really sure how to use code tags, so info on that would be appreciated as well.

void trim(string & line, int num_chars)
{
//Declare Variables
int size;

//Remove beginning characters

cout<<"trim info begin "<<"chars "<<num_chars<<endl;

line = line.erase(0, num_chars);

//Find line size after removing beginning characters
size= line.size();

cout<<"line size "<<size<<endl;

size= size-num_chars;

cout<<"trim info end"<<" chars "<<num_chars<< "size "<<size<<endl;

//Remove ending characters
line = line.erase(size, num_chars);
}
Last edited on
I set up a while loop that would only execute one time but it still gave me the same outputs before the error message
I don't see any calls to trim in the code you posted, so if you're calling trim too many times, the problem has to be where you're calling trim.

Two ways to use code tags.
1) With your mouse, highlight your code, then click the <> button to the right of the message box.
2) Type
[code]
place your code here
[/code]

You can use either method to go back and edit your original post.

edit: In the last example, you're trying to remove 20 characters from an empty line. Obviously that's not going to work. You either need to check inside trim if the line is empty and return immediately, or you need to not call trim if the line is empty.
Last edited on
The trim procedure operates inside a while loop that continues until the file fails. I think the problem is that it is accessing one more line of code than it should be. However, I'm not sure how to prevent it from accessing this last line

while(!infile2.fail())

is the set up for the while loop I'm currently using.
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

//Created function
string decodeFile(string line, string Sender, string Receiver);
//Given procedures
void swap(string & line, int len);
void subtract(string & line, int val);
void trim(string & line, int num_chars);
void remove(string & line, string to_remove);
void reverse(string & line);

int main()
{
	//Declare Variables
	int size;
	string Sender, Receiver, filename;
	string line, NewFile;

	//Open the file stream for comm_log.txt
	ifstream infile("comm_log.txt");

	//Bring in first line
	infile>>Sender>>Receiver>>filename;				

	while(!infile.fail())
	{
		//Open ifstream
		ifstream infile2(filename.c_str());
		//Change filename
		size=filename.size();
		size=size-4;
		NewFile= filename.insert(size, "_decoded");
		//Open ofstream
		ofstream outfile(NewFile.c_str());
		while(!infile2.fail())
		{
			//Get line of code to decode
			getline(infile2, line);
			//Decode line
			line = decodeFile(line, Sender, Receiver);
			//Output line to _decoded.txt
			outfile<<line<<endl;
		}
		//Close filestreams
		infile2.close();
		outfile.close();

		//Output to terminal
		cout<<"Communications from "<<Sender<<" to "<<Receiver<<" in "<<filename<<endl;
		//Bring in following lines
		infile>>Sender>>Receiver>>filename;
	}
	//Close filestreams
	infile.close();

	return 0;
}

string decodeFile(string line, string Sender, string Receiver)
{
		//Let the decoding begin!
		if(Sender=="Lion")
		{	
			//Decode Sender
			swap(line, 10);
			swap(line, 20);
			//Decode Receiver
			if(Receiver=="Lion")
			{ swap(line, 10); swap(line, 20);}
			else if(Receiver=="Baboon")
			{ subtract(line, 5); trim(line, 40); remove(line, "%%%"); }
			else if(Receiver=="Hyena")
			{ trim(line, 20); subtract(line, 3); }
			else if(Receiver=="Warthog")
			{ reverse(line); swap(line, 10); reverse(line); }
			else
			{ reverse(line); remove(line, "SSS"); }
		}
		else if(Sender=="Baboon")
		{
			//Decode Sender
			subtract(line, 5);
			trim(line, 40);
			remove(line, "%%%");
			//Decode Receiver
			if(Receiver=="Lion")
			{ swap(line, 10); swap(line, 20);}
			else if(Receiver=="Baboon")
			{ subtract(line, 5); trim(line, 40); remove(line, "%%%"); }
			else if(Receiver=="Hyena")
			{ trim(line, 20); subtract(line, 3); }
			else if(Receiver=="Warthog")
			{ reverse(line); swap(line, 10); reverse(line); }
			else
			{ reverse(line); remove(line, "SSS"); }
		}
		else if(Sender=="Hyena")
		{
			//Decode Sender
			trim(line, 20);
			subtract(line, 3);
			//Decode Receiver
			if(Receiver=="Lion")
			{ swap(line, 10); swap(line, 20);}
			else if(Receiver=="Baboon")
			{ subtract(line, 5); trim(line, 40); remove(line, "%%%"); }
			else if(Receiver=="Hyena")
			{ trim(line, 20); subtract(line, 3); }
			else if(Receiver=="Warthog")
			{ reverse(line); swap(line, 10); reverse(line); }
			else
			{ reverse(line); remove(line, "SSS"); }
		}
		else if(Sender=="Warthog")
		{
			//Decode Sender
			reverse(line);
			swap(line, 10);
			reverse(line);
			//Decode Receiver
			if(Receiver=="Lion")
			{ swap(line, 10); swap(line, 20);}
			else if(Receiver=="Baboon")
			{ subtract(line, 5); trim(line, 40); remove(line, "%%%"); }
			else if(Receiver=="Hyena")
			{ trim(line, 20); subtract(line, 3); }
			else if(Receiver=="Warthog")
			{ reverse(line); swap(line, 10); reverse(line); }
			else
			{ reverse(line); remove(line, "SSS"); }
		}
		else
		{
			//Decode Sender == Meerkat
			reverse(line);
			remove(line, "SSS");
			//Decode Receiver
			if(Receiver=="Lion")
			{ swap(line, 10); swap(line, 20);}
			else if(Receiver=="Baboon")
			{ subtract(line, 5); trim(line, 40); remove(line, "%%%"); }
			else if(Receiver=="Hyena")
			{ trim(line, 20); subtract(line, 3); }
			else if(Receiver=="Warthog")
			{ reverse(line); swap(line, 10); reverse(line); }
			else
			{ reverse(line); remove(line, "SSS"); }
		}
	return line;
}

void swap(string & line, int len)
{
	//Declare Variables
	string change, initial;
	int i=0;
	int size;
	//Find size
	size = line.size();
	//Loop through switching strings
	while(i<size)
	{
		//Determine line segments
		initial = line.substr(i, len);
		change = line.substr(len, len);
		//Swap line segments
		line = line.replace(i, len, change);
		line = line.replace(len, len, initial);
		//Move location past first swap
		i=i+(2*len);
	}
}

void subtract(string & line, int val)			
{
	//Declare Variables
	int i=0;
	int size;
	char letter;
	string replace;
	//Determine line size
	size = line.size();
	//Loop through each letter for subtraction
	while(i<size)
	{
		//Determine letter
		letter = line.at(i);
		replace = letter-val;
		//Placing new letter to replace old version
		line = line.replace(i, 1, replace);
		//Increment i
		i= i+1;
	}
}

void trim(string & line, int num_chars)
{
	//Declare Variables
	int size, i=0;
	while(i<1)
	{
		//Remove beginning characters
		cout<<"trim info begin "<<"chars "<<num_chars<<endl;
		line = line.erase(0, num_chars);
		//Find line size after removing beginning characters
		size= line.size();
		cout<<"line size "<<size<<endl;
		size= size-num_chars;

		cout<<"trim info end"<<" chars "<<num_chars<< "size "<<size<<endl;
		//Remove ending characters
		line = line.erase(size, num_chars);

		i=i+1;
	}
}

void remove(string & line, string to_remove)		
{
	//Declare Variables
	int location=0, length=0;

	length=to_remove.size();

	//Loop through erasing to_remove string at all locations
	while(line.find(to_remove)!= string::npos)
	{
		//Find location of to_remove string
		location = line.find(to_remove);
		cout<<"remove info "<<"location "<<location<<" length "<<length<<endl;
		//Erase to_remove string at location
		line = line.erase(location, length);
	}
}

void reverse(string & line)
{
	//Declare Variables
	int i=0;
	int size;
	char letter;
	//Find size
	size=line.size();
	//Loop through character movement
	while(i<size)
	{
		//Find initial letter
		letter = line.at(0);
		//Push back letter to end
		line.push_back(letter);
		//Remove letter
		line = line.erase(0, 1);
		//Increment i
		i++;
	}
}
So here's everything that I have. Basically the function decodeFile calls the procedure trim while inside a while loop.

From the outputs given by cout, it would appear that one extra line of code is being brought in. So how do I fix this?
What happens at line 42 if when getline encounters eof?
Last edited on
I don't understand what you mean...

create an if / else statement?
one extra line of code is being brought in. So how do I fix this?

Write your input loop correctly, of course.

This is wrong:
1
2
3
4
while(!infile2.fail())
{
    //Get line of code to decode
    getline(infile2, line);

This is right:
1
2
3
//Get line of code to decode
while(getline(infile2, line))
{

Last edited on
Thank you @Cubbi that worked great!
Topic archived. No new replies allowed.