Reputation: 55
I am new to C++. I am having trouble outputting data to a file. I am using an iterator to print out a map. The print method takes i, a key value, and prints out it's corresponding vector. Now, this works perfectly fine when I output normally using cout<< but when I try to put the same output into a file, my program crashes. I know it is the *it that in the outfile<< line that is crashing it, because if I replace it with some random string it outputs it to the file fine. Also, I know the parameters in the print method are not causing any problems, because I can transfer that method directly to the main function of the program and get the same error. Any help would be greatly appreciated on how to fix this, thank you! Here is my print method where the error is happening:
public: void print(int i, vector<string> in, ostream& outfile) // print method for printing a vector and it's key
{
sort(in.begin(), in.end()); // sort the vector alphabetically first
vector<string>::iterator it;
it= unique(in.begin(), in.end()); // makes sure there are no duplicate strings
in.resize( distance(in.begin(),it) );
for( it = in.begin(); it != in.end(); it++ ) // iterate through it
cout << i << ": "<< *it<<endl; // and print out the key value and each string in the vector
// outfile<< i << ":" << *it<< endl; // prints to file
}
Upvotes: 2
Views: 475
Reputation: 126442
@slugonamission already gave you the correct answer, so I'm just going to point out that your function can actually be simplified and made less error-prone. I am writing this as an answer just because code formatting is required, otherwise I would post it in a comment:
void print(int i, vector<string> v, ostream& o)
{
sort(begin(v), end(v));
v.erase(unique(begin(v), end(v))); // Do this in one step, no iterator mess
for (auto const& s : v) // Avoid manual iteration cycles if you can
{
o << i << ":" << s << endl;
...
}
}
EDIT:
As @juanchopanza correctly points out, an even quicker way to achieve the same would be to transfer the vector's content into an associative container to ensure uniqueness. This would allow you to pass the vector by const &
:
void print(int i, vector<string> const& v, ostream& o)
{
unordered_set<string> c(begin(v), end(v));
for (auto const& s : c)
{
o << i << ":" << s << endl;
}
}
Upvotes: 2
Reputation: 9642
Are you using the cout
line at the same time? If so, I think I know what it is.
The for
loop, without braces will execute the next statement as its loop body. If you use both the cout
line and the outfile
line, you will print everything, then after the loop, it
will be located just past the end of the array. You then try and dereference this and write it to a file, which of course fails since you're dereferencing an invalid iterator.
Short answer, wrap the statements in your for loop with braces.
For example, you have the following (when indented properly):
for( it = in.begin(); it != in.end(); it++ ) // iterate through it
cout << i << ": "<< *it<<endl;
outfile<< i << ":" << *it<< endl; // prints to file
On the last line of that, it = in.end()
, where in.end()
is the element just past the end of the vector. You then try and access the element at that location which doesn't exist (and is invalid), and hence it fails. Instead, you need to move that inside the loop, which should read
for( it = in.begin(); it != in.end(); it++ ) // iterate through it
{
cout << i << ": "<< *it<<endl; // and print out the key value and each string in the vector
outfile<< i << ":" << *it<< endl; // prints to file
}
Upvotes: 2