Iterator problem
-
Erstmal die Vorgeschichte: Haben als Aufgabe bekommen ein Brettspiel zu programmieren, also habe ich mir eine template Klasse spielbrett, eine template Klasse spielbrett_row_iterator(um das spielfeld zeilenweise zu durchlaufen), eine template Klasse spielbrett_column_iterator(um das spielfeld spaltenweise zu durchlaufen) erstellt.
Nun brauchte ich noch einen static set Container der mit spielbrett_row_iteratoren gefuellt ist(fuer meine Player Klasse), hier sind alle leeren Felder wo man einfuegen kann vertreten.
Jetzt aber zum Problem: Wenn ich einen Iterator vom set Container anlege und den iterator der funktion InsertEmptyFields uebergebe wird dieser iterator in der Funktion InsertEmptyFields geändert und zeigt nach der Funktion auf einen anderen spielbrett_row_iterator.
Frage: wie kann das sein?
#include <set> #include <iostream> #include "spielbrett_row_iterator.h" #include "spielbrett_column_iterator.h" #include "spielbrett.h" #include <string> using namespace std; static set<spielbrett_row_iterator<string> > emptyFields; void InsertEmptyFields(const spielbrett_row_iterator<string>& row_it) { spielbrett_row_iterator<string> row_it1(row_it); /*Fehler muß mit erase zusammen haengen, wenn ich emptyFields.erase(row_it) entferne geht es brauche es aber da ich diese Position aus den set loeschen muß.*/ emptyFields.erase(row_it); cout<<"*****1*****"<<row_it<<endl; //der Iterator it wird auf den wert von ++row_it1 geaendert. //Operator ++row_it siehe unten. if(++row_it1!=row_it1) { cout<<"*****2*******"<<row_it1<<endl; emptyFields.insert(row_it1); } cout<<"*****3*****"<<row_it<<endl; cout<<"set-Container--begin"<<endl; copy(emptyFields.begin(), emptyFields.end(), ostream_iterator<spielbrett_row_iterator<string> >(cout, ";")); cout<<endl; cout<<"set-Container--end"<<endl; } int main() { spielbrett<string> brett(11,11); spielbrett_row_iterator<string> tmp_it(brett,5,6); InsertEmptyFields(tmp_it); set<spielbrett_row_iterator<string> >::iterator it=emptyFields.begin(); for(unsigned int i=0;i<0;i++) { ++it; } //tmp_it=(*it); //Ursprungs Iterator cout<<"****4*****"<<"Iterator: "<<*it<<endl; InsertEmptyFields(*it); //Hier ist er geaendert. cout<<"****5*****"<<"Iterator: "<<*it<<endl; return 0; }
spielbrett_row_iterator& operator++() { //m_c entspricht x-Wert //m_r entspricht y-Wert //auf den spielbrett //m_columns anzahl der Spalten, m_rows anzahl der Zeilen auf //den Spielbrett if(m_c!=m_brett->m_columns-1) { m_c++; return *this; } else { if(m_r!=m_brett->m_rows-1) { m_r++; m_c=0; return *this; } else { return *this; } } }
-
mir kommt
if(m_c!=m_brett->m_columns-1) { m_c++; return *this; }
komisch vor
Kann sich die spalte nur um eins vergrösser!
Du könntest ja mit dem spalten iterator wo ich wo sein
Hab leider zu wenig code das ich hier ne konkretten lösungs vorschlag gäben könnte. Müsst ihr unbedingt zwei iteratorn verwenden. Mit einem wäres es leichter
-
den ++ operator kannst du auch einfacher schreiben:
spielbrett_row_iterator& operator++() { //m_c entspricht x-Wert //m_r entspricht y-Wert //auf den spielbrett //m_columns anzahl der Spalten, m_rows anzahl der Zeilen auf //den Spielbrett m_r += ++m_c >= m_brett->m_columns; m_c %= m_brett->m_columns; m_r %= m_brett->m_rows; return *this; }
wie sind denn < und != für deinen iterator definiert?
for(unsigned int i=0;i<0;i++) { ++it; }
was ist denn das??
-
for(unsigned int i=0;i<0;i++) { ++it; }
ist hier ueberflueßig, hab ich gebraucht damit der Computer sich eine Position aus dem set waehlt.
if(m_c!=m_brett->m_columns-1) { m_c++; return *this; }
das bedeutet wenn der row_iterator nicht am rechten spielfeldrand ist, dann zaehle die x-Position des row_it um eins hoch.
Habe mir gedacht, dass das vieleicht daran liegt das ich der erase methode vom set einen row_it uebergebe und keinen iterator vom set.
-
Hier noch <, >, !=, ==
bool operator<(const spielbrett_row_iterator<T> i) const { return((m_brett==i.m_brett) && (((m_c<i.m_c)&& ((m_r<i.m_r)||(m_r==i.m_r))) || (m_r<i.m_r))); } bool operator>(const spielbrett_row_iterator<T> i) const { return ((m_brett==i.m_brett) && *this!=i && !(*this<i)); } bool operator!=(const spielbrett_row_iterator<T> i) const { return((m_brett!=i.m_brett)||(m_c!=i.m_c)||(m_r!=i.m_r)); } bool operator==(const spielbrett_row_iterator<T> i) const { return((m_brett==i.m_brett)&&(m_c==i.m_c)&&(m_r==i.m_r)); }
-
Hab das Problem mal von meinen spielbrett Iteratoren abgekoppelt.
#include <set> #include <iterator> #include <iostream> #include <string> using namespace std; static set<int> s; int main() { s.insert(1); s.insert(2); set<int>::iterator s_it=s.begin(); ++s_it;//wenn mann ++s_it entfernt oder erase entfernt dann gehts. cout<<*s_it<<endl;//ausgabe des inhalts von s_it int tmp=*s_it; s.erase(tmp); tmp++; s.insert(tmp); copy(s.begin(), s.end(), ostream_iterator<int>(cout, ";")); cout<<endl; cout<<*s_it<<endl;//ausgabe des inhalts von s_it, sollte doch eigentlich die gleiche ausgabe wie oben sein oder? return 0; }
Hier die Ausgabe:
2
1;3;
3Das Problem muß irgendwie mit dem zusammenspiel von erase, ++s_it und vieleicht auch den static set liegen.
Vieleicht kann mir mal einer erklaeren was dagenau passiert, waere echt cool.
danke
-
s.insert(1); //--1 s.insert(2); //--1--2 set<int>::iterator s_it=s.begin(); ++s_it;//wenn mann ++s_it entfernt oder erase entfernt dann gehts. cout<<*s_it<<endl;//ausgabe des inhalts von s_it int tmp=*s_it; s.erase(tmp); //--1 tmp++; s.insert(tmp);//--1--3 copy(s.begin(), s.end(), ostream_iterator<int>(cout, ";")); cout<<endl; cout<<*s_it<<endl; //--1--3 (*a_it zeigt auf das 2 element was in dem fall 3 ist//ausgabe des inhalts von s_it, sollte doch eigentlich die gleiche ausgabe wie oben sein oder?
mfg
-
Ja, danke.
-
int tmp=*s_it; s.erase(tmp); //--1
ab hier hängt s_it sowieso in der luft. es gibt keine garantie, dass es nach dem einfügen eines weiteren elements wieder auf ein elemnt des sets zeigt. s_it danach zu dereferenzieren erzeugt also undefiniertes verhalten.
übrigens sind deine relationen fehlerhaft, wenn du mit mehreren spielbretten arbeiten würdest. set prüft gleichheit nähmlich nicht mit dem entsprechenden operator, sondern über die ordnungs relation, mit der es instanziert wurde (die bei dir nicht streng genug ist): a == b = !(a<b)&&!(b<a)du müsstest also noch nach spielbrettern sortieren, oder gleich ein einzelnes set für jedes spielbrett verwenden.