I'm trying to check if the given relations are transitive and if not, add new pairs of relations to make it transitive. Example input:
aa ab ad be
Function should make this:
aa ab ad be ae
because in order to be transitive, if ab
and bc
exists, ac
must exist too. But I get a segmentation fault whatever I try.
I'm new to C++ programming and trying to learn about iterators. Here is my function:
vector<string> isTransitive(vector<string> relations){
bool flag;
for(auto it=relations.begin();it != relations.end(); ++it){
for(auto it2=relations.begin();it2 != relations.end(); ++it2){
if((*it)[1] == (*it2)[0] && (*it)[0] != (*it)[1] && (*it2)[0]!=(*it2)[1]){ //if there exists ab and bc
string newRelation; //if there is a (a,b) (b,c) holds (a,c)
newRelation.push_back((*it)[0]);
newRelation.push_back((*it2)[1]);
flag=false;
for(auto it3=relations.begin();it3 != relations.end(); ++it3){
if(*it3==newRelation){
flag=true;
it3=relations.end(); //break the loop
it2=relations.end(); //break the loop
}
}
if(flag==false){
relations.push_back(newRelation);
}
}
}
}
return relations;
}
if(*it3==newRelation)
when this statement is true
, I get the segfault.
A for loop is equivalent to a while loop (from cppreference):
{
init_statement
while ( condition ) {
statement
iteration_expression ;
}
}
With this two lines:
it3=relations.end(); //break the loop
it2=relations.end(); //break the loop
You are not breaking the loop, but you cause undefined behavior. Both iterators will be incremented first, then the loop condition is checked. At that point it3
is no longer relations.end()
. It is more or less like this:
{
auto it = relations.begin();
while (it != relations.end()) {
it = relations.end();
++it;
}
}
The condition will never be true
and you run beyond the end of relations
.
To break out of loops use break
. To break out of nested loops, you can put them in a function and use return
.