» »

vector::iterator problemi, brisanje podatkov iz vektorja

vector::iterator problemi, brisanje podatkov iz vektorja

NSA Agent ::

vector<int> brisi; // vektor števil ki jih hočem izbrisat iz temp
vector<int> temp; // vektor števil
vector<int>::iterator it;
vector<int>::iterator it2;
for(it=brisi.begin(); it!=brisi.end() ;it++)
{
     for(it2=temp.begin(); it2!=temp.end() ;it2++)
     {
         if( *it == *it2 )
         {
               temp.erase(it2);
               brisi.erase(it);
         }
     }
}
if(brisi.size()==0)
{
 return true;
}
else
{
return false;
}

Fajn bi blo če bi tole delal sam ne dela. Napaka nastane ko izbrišem zadnji element iz "brisi" vektorja in potem se izvrši ukaz it2++. Ki povsej verjetnosti sproži napako.
Prevajalnik ne javi nobene napake ali opozorila.
Tako me zanima, kako bi ta problem bol elegantno rešu?

Process terminated with status -1073741819 (0 minutes, 1 seconds)
  • spremenilo: NSA Agent ()

Senitel ::

Ne. Problem imaš že takoj na začetku, ko pobrišeš it2 iz temp in potem poskušaš naredit it2++. Iterator ni več veljaven, ko ga pobrišeš iz vektorja.

mallard ::

vector::erase() ti vrne iterator, ki sledi zadnjemu izbrisanemu elementu. Od tu naprej potem nadaljuješ sprehajanje, brez da bi premaknil iterator naprej. Premakneš ga le, ko ne brišeš.

if (*it == *it2) {
    it2 = temp.erase(t2);
} else {
    ++it2;
}


Ne vem, zakaj brišeš iz vektorja "brisi". Kaj pa, če se elementi v temp ponavljajo?

mallard ::

Pozabil sem dodat, da moraš "increment" del for zanke pustiti prazen.

Zgodovina sprememb…

  • spremenilo: mallard ()

mn ::

Jaz bi raje naredil nekako takole:
struct IsEq { 
 explicit IsEq(int i):m(i){};
 bool operator()(int i){return i==m;}
private:
int m;
};
bool main(){
bool result = true;
vector<int> brisi; // vektor števil ki jih hočem izbrisat iz temp
vector<int> temp; // vektor števil
vector<int>::iterator it;
vector<int>::iterator it2;
for(it=brisi.begin(); it!=brisi.end() ;it++)
{
 size_t oldSize = temp.size();
 std::remove_if(temp.begin(), temp.end(), IsEq(*it));
 if(oldSize==temp.size()){
  result = false;
 }
}
brisi.clean();
return result;
}

NSA Agent ::

Hvala za odgovore.

Problem sem rešil bol špartansko in sicer tako da sem naredil takole.
 
vector<int> brisi; // vektor števil ki jih hočem izbrisat iz temp 
vector<int> temp; // vektor števil 
vector<int>::iterator it; 
vector<int>::iterator it2; 
for(it=brisi.begin(); it!=brisi.end() ;it++) 
{      
for(it2=temp.begin(); it2!=temp.end() ;it2++)      
{          
if( *it == *it2 )          
{                
temp.erase(it2);                
brisi.erase(it);
it--;
it2--;          
}      
} 
} 
if(brisi.size()==0) {  return true; } 
else{ return false; } 



@mallard s to kodo preverjam če sta vektorja identična, če imata enako število elementov v njem in če so isti elementi. Ja koda ni vredu ker imam dvojno zanko torej ko grem preverjat v prvi zaniki če je not 2 mi pol iz druge zanke izbriše vse 2 ke čeprav bi moglo izbrisat samo eno. Ampak koda čudezno dela.

Zgodovina sprememb…

  • spremenilo: NSA Agent ()

Senitel ::

NSA Agent je izjavil:

Ampak koda čudezno dela.

Mhm... Tako kodo imamo vsi najraje... 8-O

mallard ::

To, da koda čudežno dela, čeprav ne veš kako, ni prav dobra tolažba, se ti ne zdi? :) Zna se zgodit, da se ti bo enkrat program čudežno sesul.

Za preverjanje, če sta vektorja identična, obstaja precej bolj elegantna rešitev:
template<typename T>
bool sta_enaka(const vector<T>& v1, const vector<T>& v2)
{
    return v1 == v2;
}


Da sta vektorja enaka, morajo biti elementi v enakem vrstnem redu. Če ti vrstni red ni pomemben, potem vektorja pred preverjanjem sortiraj (std::sort). Če nočeš spreminjat vrstnega reda elementov v vektorjih, ki jih prevejaš, potem naj tvoja funkcija parametre vzame po vrednosti, ne po referenci. Je pa to lahko pri velikih vektorjih precej neučinkovito.

Zgodovina sprememb…

  • spremenilo: mallard ()

mn ::

Ja koda ni vredu ker imam dvojno zanko torej ko grem preverjat v prvi zaniki če je not 2 mi pol iz druge zanke izbriše vse 2 ke čeprav bi moglo izbrisat samo eno.

To enostavno rešiš takole:
{                
temp.erase(it2);                
brisi.erase(it);
it--;
it2--;          
break;
}      

Ampak koda čudezno dela.

Ampak ne bodi presenečen, če na kakem drugem računalniku ali kakšnem drugačnem naboru podatkov ne bo več! Koda je napačna in predlagam da jo popraviš!


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[Python] Weighted random

Oddelek: Programiranje
12945 (785) FrEaKmAn
»

Vodenje videoteke v C++

Oddelek: Programiranje
51673 (1493) Tutankhamun
»

[C#] IndexOutOfRange Exception

Oddelek: Programiranje
81243 (1088) ql000
»

std containers vs. own custom containers

Oddelek: Programiranje
93559 (3380) Mmm'Aah
»

[C++] Galerija kode

Oddelek: Programiranje
283965 (3070) 64202

Več podobnih tem