Problem mit Stringstream und String
-
Wie ich vermutete - Der Typ const char* ist ein Zeiger - die Map sortiert mit operator< - ein const char* ist kleiner als ein anderes wenn die Speicheradresse kleiner ist.
Mach die Map vom Typ std::string wenn Du lexikalische Vergleiche der Keys haben möchtest.
-
daran liegt es leider nicht, ich habe auch folgenden Code getestet der den vergleichsoperator implementiert.. diese methode vergleicht die Strings oder const char* arrays schon inhaltlich...
hash_map<const char*, float, hash<const char*>, eqstr> connections; struct eqstr { bool operator()(const char* s1, const char* s2) const{ return strcmp(s1, s2) == 0; } };
Hat evtl jamend eine andere Idee? Was ist mit dem pair als key fuer die map?
Danke!
-
Ja, nimm std::string als Key. Das wurde dir aber auch schon in der ersten Antwort gesagt. Ich kann mir ehrlich gesagt nicht vorstellen wie eine Map mit const char * als Key funktionieren soll.
Du sagst, du baust deine Key-Strings mit Stringstreams zusammen. Etwa so?
std::ostringstream Stream; Stream << irgendwas; Map[Stream.str().c_str()] = irgendwas_anderes;
Ist jetzt einfach mal so geraten, denn den relevanten Code hast du uns leider unterschlagen.
Der obige Code-Ausschnitt funktioniert nicht. Und das hat nichts mit dem Stringstream zu tun. In dem Moment, wo der []-Operator der Map abgearbeitet worden ist, existiert der von c_str() zurückgegebene String nicht mehr und dein Schlüssel in der Map zeigt ins Nirvana.
-
Ja, nimm std::string als Key. Das wurde dir aber auch schon in der ersten Antwort gesagt.
--> es waere bei mir evtl auch gut gewesen direkt ein pair als key zu nutzen, deshalb die frage!
Ist jetzt einfach mal so geraten, denn den relevanten Code hast du uns leider unterschlagen
--> Der code steht oben, ist also nicht unterschlagen
Die Methode stringGenerator erledigt das ganze fuer mich und schreibt den stream-inhalt ueber ein referenzobjekt in einen string. Dieser wird spaeter imt c_str() in die hash-map gepackt.. Hier nochmal die beiden Code-elemente:
Hier der Map-Hinzufuegen-Code
std::string temp; makeStringFromKeysP(key1,key2,temp); return connections[temp.c_str()];
und der string generator:
void meineKlasse::stringGenerator(int key1, int key2, std::string& strng) { std::stringstream stream; stream << key1 << ":" << key2; strng = stream.str(); //strng += '\0'; }
Der obige Code-Ausschnitt funktioniert nicht. Und das hat nichts mit dem Stringstream zu tun. In dem Moment, wo der []-Operator der Map abgearbeitet worden ist, existiert der von c_str() zurückgegebene String nicht mehr und dein Schlüssel in der Map zeigt ins Nirvana.
--> AHA... nun wird es hier interessant! Kann es sein dass bei meinem Ansatz (siehe hier oben) das selbe passiert dass ich ins nirvana verweise?
Danke fuer eure Hilfe
-
Sorry, hatte den relevanten Code-Abschnitt übersehen.
Falls du mit obigem Ansatz das hier meinst:
std::map<std::pair<int,int>*, float, hash<const char*>, eqstr> connections;
Ja, das geht hunderprozentig schief. Zeiger und STL-Container sind ein Thema für sich. Zeiger als Schlüssel für eine Map sind eigentlich nie ein Thema, weil das gewöhnlich nicht funktioniert.
-
ganz im Grunde meinte ich jenes:
hash_map<const char*, float> connections;
in kombination mit der stringgenerator-methodesorry wenn das falsch ruebergekommen ist...
-
Hm, hash_map ist nicht Teil des Standards und ich kenne mich nicht wirklich damit aus. Aber unter der Annahme, daß das Interface äquivalent zu einer gewöhnlichen std::map ist (man möge mich bitte berichtigen, wenn das nicht so ist), gilt das, was ich oben schon geschrieben habe. Zeiger als Schlüssel zu verwenden ist schlecht. Nimm den std::string.
-
Z2! hash_map ist evtl. die std::ext::hash_map und erlaubt halt nur eine schnellere Suche im Gegensatz zur std::map. Aber es gelten die gleichen Regeln für jeden anderen Container.
mefirst! Benutze doch einfach std::string anstatt const char*. Hilft doch nichts, immer wieder die Frage zu stellen. Denn es geht nunmal ums Prinzip.
-
ich habe mich nun entschieden einfach pair (int,int) als key zu benutzen, das erlaubt mir auch etwas effizienteren zugriff auf die beiden werte des keys.. Mit dem string habt ihr recht, die Frage schien eh nicht beantwortbar zu sein, auch wenn ich den unterschied gern gewusst haette ;P
Das problem bei der Nutzung von pair als key ist lediglich die hash_funktion die ich dann wohl selber schreiben muss.. aber das waere hier offtopic, gell? (falls aber doch jemand weiss wie,... bitte melden)
Danke fuer eure Hilfe soweit
-
std::string s1 = "Hallo"; std::string s2 = "Hallo"; std::cout << (s1 < s2) << std::endl; // ergibt false const char* p1 = s1.c_str(); const char* p2 = s2.c_str(); std::cout << (p1 < p2) << std::endl; // ergibt einen zufälligen Wert
Das ist genau das, was eine std::map<const char*, int> verwenden würde. Über den kleiner-als-Operator wird die Reihenfolge bestimmt und auch die Gleichheit ermittelt. Nämlich die Schlüssel sind gleich, wenn folgendes gilt: !(p1 < p2 || p2 < p1). Wenn Du als Schlüssel jetzt eine String-Konstante übergibst (also keinen std::string), dann erhälst Du wahrscheinlich immer eine Ungleichheit.
Du hattest den richtigen Ansatz schon geliefert, indem Du ein eigenes Prädikatobjekt angelegt hast. Allerdings hast Du diesen falsch implementiert. Richtig wäre zumindest für die std:
struct cmpstr { bool operator()(const char* s1, const char* s2) const{ return strcmp(s1, s2) < 0; } }; std::map<const char*, float, cmpstr> connections;
Ich nehme an, daß das mit der hash_map ähnlich ist.
Eine andere Sache ist auch noch falsch. Wenn Du mit stringstream einen String anlegst und über c_str() den Zeiger holst, wird der Zeiger ungültig, sobald der stringstream ungültig wird. Den als Schlüssel in einem Container zu verwenden, wäre ungünstig.
Und noch was: Du schreibst:
std::map<std::pair<int,int>*, float, hash<const char*>, eqstr> connections;
Warum willst Du immer Pointer verwenden? Nimm doch einfach:
std::map<std::pair<int,int>, float> > connections;
Das entspricht dem Standard (im Gegensatz zu hash_map) und ist effizienter als einen std::string zu verwenden.
-
Danke fuer die Hilfe, besonders die info ueber den StringStream hilft mir sehr...
Die standard Map laeuft jetzt (wenn auch es eine normale map ist und keine hash-map,..). Nun kann ich mich also mit den anderen neueren Problemen des Image-Processing widmen..