简体   繁体   中英

C++ “vector iterator not dereferencable” in runtime

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;
    }

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();

LIVE

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;
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM