Probleme mit std::copy
-
Hallo,
folgender Code:#include <string> #include <iostream> #include <map> #include <sstream> #include <iterator> #include <fstream> #include <algorithm> using namespace std; struct myValue { string str; int val; }; istream& operator>>(istream& stream, myValue& mV) { string str; getline(stream,str); if(!stream.eof()) { mV.str = str.substr(0,str.find('=')); istringstream iss(str.substr(mV.str.size()+1,str.size() - mV.str.size())); iss >> mV.val; } return stream; } class Helper { private: static map<string,int> mV_map; public: Helper() {}; ~Helper() {}; Helper& operator*() { return *this; } Helper& operator++() { return *this; } //Helper& operator()() { return *this; } Helper& operator=(const myValue& mV) { mV_map.insert(make_pair(mV.str,mV.val)); return *this; } void show_map() { map<string,int>::const_iterator const_it = mV_map.begin(); while(const_it != mV_map.end()) { cout << const_it->first << " = " << const_it->second << endl; ++const_it; } cout << endl; } int getValueof(const string& s) { map<string,int>::const_iterator const_it = mV_map.find(s); if(const_it!=mV_map.end()) return const_it->second; return -1; } }; map<string,int> Helper::mV_map; int main() { ifstream file("fu.txt"); Helper helper; copy(istream_iterator<myValue>(file),istream_iterator<myValue>(),helper); file.close(); helper.show_map(); cout << helper.getValueof("u") << endl; cout << helper.getValueof("b") << endl; return 0; }Wie zu sehen ist muss ich leider eine statische Variable benutzen, da wenn ich helper an copy übergebe es nur kopiert wird und er das Objekt nicht wirklich ändert.
Daher meine Frage, was muss ich machen um dieses static zu vermeiden ???
Und gibt es auch eine Möglichkeit um das hier:
void show_map() { map<string,int>::const_iterator const_it = mV_map.begin(); while(const_it != mV_map.end()) { cout << const_it->first << " = " << const_it->second << endl; ++const_it; } cout << endl; }So umzuändern das ich es mit copy und nem Ostream_Iterator an cout übergebe und dabei das selbe Ausgabeformat wie oben bekomme ...
-
Du könntest statt der Helper-Klasse direkt mit einem set<myValue> arbeiten, dazu mußt du der Klasse nur noch einen passenden Vergleichs-Operator spendieren:
bool operator<(const myValue& l,const myValue r) { return l.str<r.str; }(die Struktur kannst du dann über einen insert-Iterator füllen und über normale Iteratoren schreiben (letzteres benötigt einen op<< für den ostream-Iterator)
-
Du könntest statt der Helper-Klasse direkt mit einem set<myValue>
Klar, aber ich habe das nur als Übung für mich im Bezug auf nen anderen Thread geschrieben.
Würde gerne Wissen wie ich die 2 Probleme so lösen könnte ...
-
Warum einfach, wenn's auch kompliziert geht? (scnr)
Ich suche normalerweise lieber nach einer möglichst einfachen Lösung für ein gegebenes Problem (in deinem Beispiel bietet sich ein set<> an), als mich durch irgendwelche komplexen Strukturen verwirren zu lassen. Aber ich versuch's trotzdem mal:
1. Da könnte explizite Instanziierung weiterhelfen:
copy<istream_iterator<myValue>,Helper&>(istream_iterator<myValue>(file),istream_iterator<myValue>(),helper);(Achtung: nicht getestet)
Auf diese Weise sagst du dem Compiler, welche Template-Parameter er für den Aufruf verwenden soll - besonders wichtig ist hier das Helper**&** für die Referenz-Übergabe.
2. Du brauchst einen "operator<<(ostream&,const pair<const string,int>&);", der die Wertepaare passend ausgibt und Zugriff auf mV_map.begin() und mV_map.end() von außen, dann kannst du diese beiden Iteratoren an copy() übergeben.
(ich bin mir aber nicht sicher, ob pair<> schon einen eigenen op<< definiert)
-
CStoll schrieb:
Warum einfach, wenn's auch kompliziert geht? (scnr)
Ich suche normalerweise lieber nach einer möglichst einfachen Lösung für ein gegebenes Problem (in deinem Beispiel bietet sich ein set<> an), als mich durch irgendwelche komplexen Strukturen verwirren zu lassen. Aber ich versuch's trotzdem mal:
Ist ja auch richtig was du sagst. Wie gesagt ich wollte selber was rumspielen und so die stl besser verstehen. Und da kann ich ja mein Problem nicht einfach ignorieren und mich was anderem zuwenden

CStoll schrieb:
1. Da könnte explizite Instanziierung weiterhelfen:
Hatte ich schon leider vergebens versucht
:/usr/lib/gcc/i686-pc-linux-gnu/3.4.6/include/g++-v3/bits/stl_algobase.h:358: Fehler: ungültige Initialisierung einer nicht-konstanten Referenz des Typs »Helper&« von temporärem Wert des Typs »Helper«CStoll schrieb:
2. Du brauchst einen "operator<<(ostream&,const pair<const string,int>&);", der die Wertepaare passend ausgibt und Zugriff auf mV_map.begin() und mV_map.end() von außen, dann kannst du diese beiden Iteratoren an copy() übergeben.
Ok danke, dann kann ich mir das ja sparen, dachte vielleicht es gibt ein paar geheime copy() tricks um aus der Funktion nur eine Zeile zu machen

-
Freak_Coder schrieb:
CStoll schrieb:
1. Da könnte explizite Instanziierung weiterhelfen:
Hatte ich schon leider vergebens versucht
:/usr/lib/gcc/i686-pc-linux-gnu/3.4.6/include/g++-v3/bits/stl_algobase.h:358: Fehler: ungültige Initialisierung einer nicht-konstanten Referenz des Typs »Helper&« von temporärem Wert des Typs »Helper«Args, das sieht übel aus. (nur wo ist in dem Aufruf ein temporärer Wert?)
*grübel* Vielleicht solltest du dir mal Gedanken über for_each() machen (Kapitel 5.7 in meinem Artikel Aufbau der STL 2 könnte als Ansatz dienen.
CStoll schrieb:
2. Du brauchst einen "operator<<(ostream&,const pair<const string,int>&);", der die Wertepaare passend ausgibt und Zugriff auf mV_map.begin() und mV_map.end() von außen, dann kannst du diese beiden Iteratoren an copy() übergeben.
Ok danke, dann kann ich mir das ja sparen, dachte vielleicht es gibt ein paar geheime copy() tricks um aus der Funktion nur eine Zeile zu machen

[/quote]Eigentlich nicht höchstens daß du einen eigenen Ausgabeiterator schreibst, der die Schlüssel/Wert-Paare in einen String im "richtigen" Format übersetzt.
(PS: Schau dir ruhig mal die Quellcodes der STL an - wenn du mit den Bezeichnern klarkommst, bringt das sicher einige Lichtblicke ;))
-
Ok, danke für die Antworten

Das mit for_each hat mich auch zur Lösung gebracht:
class Helper { ... Helper& operator()(const myValue& mV) { mV_map.insert(make_pair(mV.str,mV.val)); return *this; } ... }; ... Helper helper = for_each(istream_iterator<myValue>(file),istream_iterator<myValue>(),Helper()); ...