Reputation: 61
implementing this simple program I found out, in runtime, an error that occurs when i type the eof at the end of the FIRST while. The error says "vector iterator not dereferencable". Is that possible? The iterators are declared after the while cycles! I still cannot understand what i misspelled. Can someone help me? Ps. The program should check if a vector is a prefix for the other. Thank you! Here's the main function:
int main(){
vector<int> v1, v2;
cout << "1st vector: enter integers" << endl;
int i, j;
while (cin >> i){
v1.push_back(i);
}
cout << "2nd vector: enter integers" << endl;
while (cin >> j){
v2.push_back(j);
}
vector<int>::const_iterator i1 = v1.begin();
vector<int>::const_iterator i2 = v2.begin();
while ((*i1) && (*i2) && ((*i1) == (*i2))){
++i1; ++i2;
}
if ((*i1) && (*i2))
cout << "Vectors not compatible." << endl;
else
if (!(*i1))
cout << "The 1st vector is a prefix for the 2nd." << endl;
else
cout << "The 2nd vector is a prefix for the 1st." << endl;
return 0;
}
Upvotes: 0
Views: 2226
Reputation: 3977
vector<int>
is not a null-terminated c-style string. So to check whether an iterator reached the end, you need to compare it with the end iterator. So instead of (*i1) && (*i2)
you should write (i1 != v1.end()) && (i2 != v2.end())
in both cases. Same goes for !(*i1)
. You should change it to i1 == v1.end()
.
@RSahu describes the first problem you hit. You will hit the problem that I described once you fix the first one.
To fix the problem he described, you should clear the bad bits and ignore whatever is left in cin
's buffer. Add the following lines before your second while
loop:
cin.clear();
cin.ignore();
Upvotes: 1
Reputation: 303047
Once you get the first eof on cin
, it stays there. The second while loop effectively becomes a noop, since cin
thinks it's done. From there, we run through:
vector<int>::const_iterator i1 = v1.begin();
vector<int>::const_iterator i2 = v2.begin();
while ((*i1) && (*i2) && ((*i1) == (*i2))){
^^^
UB!
And you're dereferencing i2
without checking v2
's size.
First, you have to clear std::cin
:
std::cin.clear();
And then, the right way to check if you're done with a vector is to compare the iterator to end()
(as opposed to simply dereferencing):
while (i1 < v1.end() && i2 < v2.end() && *i1 == *i2) {
++i1;
++i2;
}
Though if you have access to a C++14 compiler, you could simply use std::mismatch
:
auto res = std::mismatch(v1.begin(), v1.end(), v2.begin(), v2.end());
if (res.first < v1.end()) {
if (res.second < v2.end()) {
std::cout << "Not compatible!" << std::endl;
}
else {
std::cout << "The 2nd vector is a prefix for the 1st." << std::endl;
}
}
else {
std::cout << "The 1st vector is a prefix for the 2nd." << std::endl;
}
Upvotes: 0
Reputation: 206597
The following block:
while (cin >> i){
v1.push_back(i);
}
makes sure that cin >> j
fails. Hence, nothing gets added to v2
in the block:
while (cin >> j){
v2.push_back(j);
}
Since v2
is empty, using *i2
leads to undefined behavior.
Upvotes: 0