Forum » Programiranje » 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š.
Ne vem, zakaj brišeš iz vektorja "brisi". Kaj pa, če se elementi v temp ponavljajo?
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.
@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.
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 ()
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:
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.
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 ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | [Python] Weighted randomOddelek: Programiranje | 1052 (892) | FrEaKmAn |
» | Vodenje videoteke v C++Oddelek: Programiranje | 1785 (1605) | Tutankhamun |
» | [C#] IndexOutOfRange ExceptionOddelek: Programiranje | 1307 (1152) | ql000 |
» | std containers vs. own custom containersOddelek: Programiranje | 3812 (3633) | Mmm'Aah |
» | [C++] Galerija kodeOddelek: Programiranje | 4096 (3201) | 64202 |