Shangru Li Shangru Li - 2 months ago 15
C++ Question

Why are the iterators not compatible?

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <iomanip>
using namespace std;

vector<string>::iterator findString(vector<string> word, string x)
{
auto beg = word.begin();
for ( ; beg != word.end() && x != *beg; beg++);
return beg;
}

vector<int>::iterator convert(vector<string>::iterator &t, vector<string> &word, vector<int> &amount)
{
vector<int>::iterator count = amount.begin();
vector<string>::iterator beg = word.begin();
for (; beg != word.end() && beg != t; count++, beg++);
return count;
}
int main()
{
vector<string> word;
vector<int> amount;

string x;

cout << "Please enter words list:" << endl;

cin >> x;
word.push_back(x);
amount.push_back(1);

while (cin >> x)
{
vector<string>::iterator t = findString(word, x);

if (t != word.end()) //A: Error happens in this line.
{
vector<int>::iterator i = convert(t,word,amount);
(*i) ++;
}
else
{
word.push_back(x);
amount.push_back(1);
}
}

for (auto r : word)
cout << setw(4) << r;
cout << endl;

for (auto r : amount)
cout << setw(4) << r;
cout << endl;

return 0;
}


In this program I want to count the number of each word input.
I wrote a conversion function from string iterator to int iterator. But it still doesn't work and says the iterators are not compatible. Is there something wrong? Moreover, I'm confused why iterators can't be converted into the corresponding integers. And why there is 'ptrdiff_t', wouldn't it be easier if it's just 'int'?
It's the first time I use this website. And I'd be grateful if someone can answer my questions. Thanks.

-It's a run-time error, after inputting two strings. Debug assertion failed. File: vector, line 248. Expression: vector iterators incompatible. I ran it on VS2015.

-Error happens in line A.

I understand finally. Thanks everyone. Thank you so much and wish y'all a good day!

Answer

Your error doesn't have anything to do with strings or ints or conversions. It's because you're creating a new copy of vector<string> word every time you call findString, and so its returned iterator is an iterator of a different vector (it's an iterator into a copy). You have:

vector<string>::iterator findString(vector<string> word, string x)
{
    ...
}

And then later, where the error is:

vector<string>::iterator t = findString(word, x);

if (t != word.end()) //A: Error happens in this line.

And so findString is returning an iterator into a copy of word instead of word itself, and MS' vector implementation has an assertion failure when you try to compare it with an iterator from a different vector, because it figures you most likely made a mistake. Instead pass your vectors by reference, for example:

vector<string>::iterator findString(vector<string> & word, string x)
{
    ...
}

Note that word is now passed by reference, and so won't be copied.

That said, you should fix your error first as an exercise, of course, but after you've got your own code working, consider replacing findString with std::find (since it already exists). Also it seems you can simplify your code greatly by using a map<string,int> to maintain word counts. And a few other things.