Set aus String-Elementen bei C++
-
Servus,
ich will ein Set aus strings anlegen - wie macht man das in C++ und wie definiert c++ den Unterschied zwischen Objekt- und Wertgleichheit?
Danke vorab.
-
brauchst du wirklich ein lmgtfy.com-link dafür? Google "c++ std::set" nimm was wo c++reference drin steht und lies .... ::kopfschüttel::
Falls du std::set noch nicht kanntest, sorry. Dann google am besten gleich noch "standard template library c++" bzw "STL c++" und schmöker da ein bisschen rum, das lohnt sich.
Was die Objekt und Wertgleichheit angeht ... bei String sind werden Werte (voreingestellt, aber änderbar) meist lexigrafisch gechecket. Objektgleichheit geht zB so:
#include <string> std::string a = "eins"; std::string b = "auch eins"; std::string c = "eins"; std::string & d = a; bool gleicherTextAB = a == b; bool gleicherTextAC = a == c; bool gleichesObjektAB = &a == &b; bool gleichesObjektAD = &a == &d; // ausgaben darfst du selbst machen
-
Jay1980 schrieb:
ich will ein Set aus strings anlegen - wie macht man das in C++
#include <set> #include <string> using namespace std; int main () { set<string> s; return 0; }Jay1980 schrieb:
wie definiert c++ den Unterschied zwischen Objekt- und Wertgleichheit?
Wertgleichzeit kannst du mit == überprüfen. Den Operator kannst du natürlich auch überladen.
Falls du mit Objektgleichzeit meinst, dass Zeiger auf das gleiche Objekt im Speicher zeigen, kannst du das überprüfen, indem du die Adressen der Objekte vergleichst.#include <iostream> using namespace std; int main () { int i(0); int j(0); int* p1(&i); int* p2(&i); if (i==j) cout << "1) gleicher Wert" << endl; if (&i==&j) cout << "2) gleiche Adresse" << endl; if (p1==p2) cout << "3) gleiche Adresse" << endl; return 0; }Ausgabe:
1) gleicher Wert 3) gleiche AdresseEdit: Mist, war zu lahm.

-
-
Danke, es hat geklappt, ich schau schon oft bei Google vorher, aber oft bleib ich dann hängen wie gerade: ich schaffe es nicht ein string-set via Iterator abzulaufen, wie macht ihr das?
-
Jay1980 schrieb:
Danke, es hat geklappt, ich schau schon oft bei Google vorher, aber oft bleib ich dann hängen wie gerade: ich schaffe es nicht ein string-set via Iterator abzulaufen, wie macht ihr das?
Genauso wie bei allen anderen STL-Containern auch. Zeig mal was du gemacht hast. Ich kann mir nämlich nicht vorstellen, wie man dies nicht schaffen kann, wenn man auch nur irgendwelche Initiative zeigt. Das ganze klingt doch zu sehr nach Hausaufgabe und du nach faulem Schüler.
-
Kann sein, dass das so ankommt, ist aber nicht so. Dein entscheidender Tipp war aber, dass es so geht wie bei allen Containern ... wie auch schon oben ... ich kannte das Set nicht und ich wusste nicht, dass Iteratoren für alle Container sehr ähnlich sind. Die Tutorials die ich zum anderen Iterator-Container-Abwandern fand konnte ich leicht adaptieren - mit den Tutorials zu Sets hatte ich Probleme.
Das ist nun mein Code:
cout << "Iterator:\n"; set<string>::iterator iteratorObject; for ( iteratorObject = filteredSeqSet.begin(); iteratorObject != filteredSeqSet.end(); iteratorObject++ ) { cout << *iteratorObject << endl; } cout << " --- Iterator-Objekt ---\n";In diesem Fall war es also schlicht ein Nichthinbekommen, oft kommt es aber auch anders vor, dass ich einige Wege zum Ziel finde und nicht einschätzen kann, was für meine Herangehensweise wohl das beste ist, das hatte ich beim Zahlen-String-konvertieren - da frage ich auch gern einfach: 'wie macht ihr das?'
Danke für den Tipp mit 'ist wie bei allen Containern'.
-
knivil schrieb:
lexigrafisch
http://www.duden.de/definition/lexigrafisch

Ich finde finde das gerade das schöne an der STL und Iteratoren, kannst du eins, kannste (fast) alle ... bei dir würde auch ein const_iterator reichen

-
Ui, mit Strings hat es ja noch geklappt, mit eigenen Strukturen pack ich das gerade nicht:
int i = 0; set<singleColumnEntropySetItem>::iterator it = g_singleEntropies.begin(); while ( it != g_singleEntropies.end() ) { cout << it->column << "; " << it->entropy << "; (" << i << ");\n"; ++it; i++; }Struktur:
struct singleColumnEntropySetItem { int column; double entropy; };Wie läuft man ein Set mit eigenen Strukturen ab?
Danke vorab.
-
... wenn ich die Sache richtig einschätze, liegt es vor allem am fehlenden Vergleich ... mal schauen, wie man dem Set einen Comparator wie in Java mitgibt.
-
Jay1980 schrieb:
Ui, mit Strings hat es ja noch geklappt, mit eigenen Strukturen pack ich das gerade nicht
Was passiert denn?
-
Steht wie alles auch in der C++ Reference...
http://www.cplusplus.com/reference/stl/set/key_comp/
http://www.cplusplus.com/reference/stl/set/value_comp/
-
-
Schaffe es immer noch nicht und ja, ich weiß, dass es in der Referenz steht. Leider klappt es halt immer noch nicht, auch wenn ich mir die Referenz schon angesehen habe.
Ich kam schon etwas weiter, ich wollte die Variante nehmen, dass ich zum Vergleichen ein Funktionsobjekt mitgebe, wie es in diesem Thread beschrieben ist: http://www.c-plusplus.net/forum/269486
Ich erhalte folgende Fehlermeldung:
/usr/include/c++/4.4/bits/stl_function.h: In member function ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = singleColumnEntropySetItem]’:
In file included from /usr/include/c++/4.4/string:50,
/usr/include/c++/4.4/bits/stl_tree.h:1170: instantiated from ‘std::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = singleColumnEntropySetItem, _Val = singleColumnEntropySetItem, _KeyOfValue = std::_Identity<singleColumnEntropySetItem>, _Compare = std::less<singleColumnEntropySetItem>, _Alloc = std::allocator<singleColumnEntropySetItem>]’
/usr/include/c++/4.4/bits/stl_set.h:411: instantiated from ‘std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const _Key&) [with _Key = singleColumnEntropySetItem, _Compare = std::less<singleColumnEntropySetItem>, _Alloc = std::allocator<singleColumnEntropySetItem>]’
h2r.cpp:465: instantiated from here
/usr/include/c++/4.4/bits/stl_function.h:230: error: no match for ‘operator<’ in ‘__x < __y’
make[2]: *** [build/Debug/GNU-Linux-x86/h2r.o] Fehler 1So hier sind die Dateien:
global.h... struct singleColumnEntropySetItemComparator { // siehe Breymann S. 761 bool operator()( const singleColumnEntropySetItem& lhs, const singleColumnEntropySetItem& rhs ) { return lhs.column < rhs.column; } }; ... // Globale Variablen ... extern std::stringstream g_conversionHelperStringStream; ... // Set samt Comparator extern std::set<singleColumnEntropySetItem> g_singleEntropies;global.cpp
... singleColumnEntropySetItemComparator seComp; set<singleColumnEntropySetItem, seComp> g_singleEntropies; ...anders.cpp
... singleColumnEntropySetItem seItem; seItem.column = colToCompute; seItem.entropy = entropy; g_singleEntropies.insert( seItem ); ...Danke vorab für den Hinweis, was daran noch falsch läuft ... wenn die Kompilierung mal läuft kann ich mir einen Kopf machen, das Set auch auszugeben.
-
Mittlerweile läufts, aber eher durch Zufall statt durch bewusstes Ändern, naja, wenn ich die nächsten Sets implementiere wird es dann schon zeitnah schnackeln vermute ich ...
-
Das std::set hat drei tmeplate Parameter. Key, Compare, Allokator. Key ist der Typ der gespeichert wird und gelichzeitig als Schlüssel verwendet wird. Compare ist irgendetwas das man mit zwei Keys aufrufen kann und das true zurückgibt, wenn der erste kleiner als der zweite ist. Standard für Compare ist
std::less<Key>. Allokator ist für die Speicherverwaltung und hier uninteressant.
Wenn du also einstd::set<MyClass>hast, wird zum Vergleichen zweierMyClassObjektestd::less<MyClass>verwendet. Da es dafür keine Spezialisierung gibt, wirdMyClass::operator<(const MyClass&)aufgerufen. Du hast also zwei Möglichkeiten umMyClassiin einemstd::setzu verwenden:
Du definierst den < Operator oder du gibst fürCompareeinen anderen Vergleichstypen an.class MyClass { public: MyClass(int i) : i_(i) {} int I() const { return i_; } // nur für set1 bool operator<(const MyClass& r) const { return i_ < r.i_; } private: int i_; }; struct MyClassLess { bool operator()(const MyClass& lh, const MyClass& rh) const { return lh.I() < rh.I(); } }; struct MyClassGreater { bool operator()(const MyClass& lh, const MyClass& rh) const { return lh.I() > rh.I(); } }; int main() { std::set<MyClass> set1; // std::set<A, std::less<A> > std::set<MyClass, MyClassLess> set2; std::set<MyClass, MyClassGreater> set3; return 0; }
