Poldi Geschrieben 18. September 2001 Geschrieben 18. September 2001 Hallo, ich mal wieder ... ich möchte, daß eine Funktion einen Vektor zurückgibt, also ungefähr so: vector<string> meineFunktion() { vector<string> meinVektor; ... return meinVektor; } So weit so gut, aber irgendwie will das nicht. Warum? Müßte doch eigentlich gehen, oder? Zitieren
multimac Geschrieben 18. September 2001 Geschrieben 18. September 2001 Meine persönliche Meinung dazu: Mit Call by Reference hast du viel weniger Sorgen <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR> #include <iostream> #include <vector> #include <string> template <class T> int function(T& container) { typename T::iterator pos; int vector_size = container.size(); for(int i = 0; i<vector_size; ++i) { cout << container << endl; } return(0); } int main() { vector<string> MeinVector; MeinVector.push_back("Alles "); MeinVector.push_back("klar ?"); function(MeinVector); exit(0); } Zitieren
Crush Geschrieben 18. September 2001 Geschrieben 18. September 2001 Man kann Vektoren scheinbar nicht als Rückgabetyp verwenden - ich bekomme auch immer Fehlermeldungen, probiere aber mal weiter und wühl mich noch durch ein paar Bücher. Entweder man arbeitet mit Referenzen, globalen Vektoren oder vielleicht die beste Lösung: Eine Klasse diesen Vektor als Instanzvariable mitgeben und mit allen notwendigen Funktionen versehen (Copy-Konstruktor, Operatoren, etc.). Diese Objekte sollten problemlos hin- und hergereicht werden könnn. Hier kann man dann auch Friend-Klassen definieren, die dann mit dem Vektor direkt hantieren können. Eventuell (hat aber irgendwie noch nicht geklappt) könnte man mit void* arbeiten und diese static casten (muß ich auch noch austesten) - mal sehen. Eventuell sind solche Vektoren als Member-Variablen public zu machen. Also ich lerne auch erst mit der STL umzugehen und deshalb bin ich da gerade ziemlich hinterher - ist ja schon wichtig zu wissen. Es sind nicht allzu viel Leute da draußen, die sich mit der STL intensiv befassen, doch hier kann halt C++ besonders seine Muskeln zeigen und beschleunigter Code ist garantiert. Das Push_back muß ich mir auch nochmal anschauen, denn das war auch ziemlich wichtig, falls (wenn ich mich recht erinnere) Bereichsüberschreitungen von Containern mit eigenen Allokatoren gemacht werden. Ist ja auch ein ziemlich interessantes Thema. Ich hatte auch noch vergessen zu sagen, daß vector<dingsbums> meinvektor(x); die Größe x der leeren im Voraus allozierten Einträge vom Typ dingsbums mitgegeben werden. Also x=10 bedeutet es wird grundsätzlich Speicher für 10 dingsbums reserviert. Ist Dieser gefüllt werden die nächsten 10 im Speicher angefordert und der Erste belegt. <FONT COLOR="#a62a2a" SIZE="1">[ 18. September 2001 23:16: Beitrag 5 mal editiert, zuletzt von Crush ]</font> Zitieren
gajUli Geschrieben 18. September 2001 Geschrieben 18. September 2001 Interessantes Thema hier. @Crush, Poldi Bei mir funktioniert es: #include <iostream> vector<string> foo(); vector<string> foo() { vector<string> vi(10); vi[3]="pillepalle"; vi[5]="pollepulle"; return vi; } int main() { vector<string> vj(10); vj=foo(); cout << vj[3] << vj[5]<< endl; cout << vj.size(); return 0; } liefert ganz brav die Ausgabe "pillepallepollepulle" und "10". @multimac Klar uebergibt man normalerweise Referenzen. Interessant ist aber hier die Frage, warum sich bei Poldi Probleme ergeben, wenn er als return-value einen vector liefert. Ansonsten: Bis morgen. ;-) Uli Zitieren
multimac Geschrieben 18. September 2001 Geschrieben 18. September 2001 EisenUli: Ein Problem hat diese Lösung allerdings. Der erstellte Container aus der "foo"-Funktion wird beim "return" komplett gekopiert. Ich habe mir gerade folgendes Programm geschrieben, das mit Pointern und Templates arbeitet. <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR> #include <iostream> #include <vector> #include <string> template <class T> T * function2() { T *myvector = new T; myvector->push_back("Compiliert mit"); myvector->push_back("gcc 2.95.3 ."); return myvector; } template <class T> int function(T& container) { typename T::const_iterator pos; int vector_size = container.size(); for(int i = 0; i<vector_size; ++i) { cout << container << endl; } return(0); } int main() { vector<string> *Box = function2<vector< string > >(); function(*Box); exit(0); } Zitieren
Poldi Geschrieben 19. September 2001 Autor Geschrieben 19. September 2001 habt erbarmen mit mir, ich kann doch gar kein c++ ... den kram mit den templates kann ich noch nicht mal lesen. ich war zwar auf ner java schulung, aber irgendwie scheint mir das nicht wirklich zu helfen ... aber danke an eisen uli, ich habs nochmal versucht und jetzt läufts, vielleicht war ich gestern schon zu gestreßt um denken zu können ... mal ne andere frage: wenn es methoden wie vector.insert() oder vector.push_back() und so gibt, dann gibt es doch auch sicherlich methoden, um elemente wieder auszulesen, oder? da ich nie weiß, wie groß die drecksdinger werde, ist der direktzugriff ohne prüfung gefäääährlich, daher denke ich, daß es eine methode mit prüfung schon gibt, oder? danke für eure hilfe, ihr habt alle einen nervenretter orden verdient!! fröhlichst, eure poldi Zitieren
haddock Geschrieben 19. September 2001 Geschrieben 19. September 2001 @poldi: <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR> da ich nie weiß, wie groß die drecksdinger werde, ist der direktzugriff ohne prüfung gefäääährlich, daher denke ich, daß es eine methode mit prüfung schon gibt, oder? Zitieren
gajUli Geschrieben 19. September 2001 Geschrieben 19. September 2001 <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR>Original erstellt von captain haddock: <STRONG>@poldi: Ja, schau mal was du zu iteratoren findest, außerdem gibt es zusätzlich zu [] eine Zugriffsmethode mit Prüfung, die meines Wissens elementAt(int pos) heißt. </STRONG> Zitieren
Crush Geschrieben 19. September 2001 Geschrieben 19. September 2001 So Poldi: Dies ist eine einfachere Lösung ohne Templates einmal mit static und einmal mit new: vector<string>* getvec() { static vector<string> gv; // mit dem Static sollte es keine Probleme bei versehentlich erneutem Aufruf geben gv.insert(gv.end(),"Erster Satz"); gv.insert(gv.end(),"Zweiter Satz"); gv.insert(gv.end(),"Dritter Satz"); return &gv; } vector<string>* getvec2() { vector<string>*pvec=new vector<string>; // jedesmal ein neuer Vektor pvec->insert(pvec->end(),"Pvecs Erster Satz"); pvec->insert(pvec->end(),"Pvecs Zweiter Satz"); pvec->insert(pvec->end(),"Pvecs Dritter Satz"); return pvec; } void Vektortest() { string x,y,z; vector<string>*pvj=getvec(); x=pvj->at(0); // über at() kein Problem y=pvj->at(1); z=pvj->at(2); //z=pvj->[2]; // klappt so nicht mehr (obwohl er eigentlich sollte) //z=*pvj[2]; // und so auch nicht pvj=getvec2(); x=pvj->at(0); y=pvj->at(1); z=pvj->at(2); delete pvj; // auf keinen Fall vergessen! } Gestern habe ich das alles nicht hinbekommen aus einem guten Grund: Man muß den at() Operator anscheinend verwenden. Über den []-Operator konnte ich nur Fehler erzeugen und sonst nix. Vielleicht weiß ja Multimac, wie man das hinbekommen könnte falls überhaupt. Templates sind etwas wichtiges um Zeit und Codezeilen zu sparen, aber man kann im Zweifelsfall auch anders ans Ziel gelangen. Die STL ist jedoch eine pure Template-Klasse mit 1000 Inline-Funktionen und man sollte wenigstens wissen, wie man die Templates einsetzt. Auch Stroutrup meint es wäre am Besten die ganzen Container in Klassen als Elementvariablen zu kapseln (erscheint mir auch sinnvoller als sie hin- und herzureichen oder gar rum- und numzukopieren - abgesehen davon, daß die Daten eigentlich gar nicht geschützt werden). Es gibt aber auch noch die Möglichkeit sich "künstliche Templates" als Makros zu definieren (#define) dann geht aber die Laufzeitpolymorphie zugrunde, weil praktisch vor dem Compilieren im Sourcecode Zeilen erzeugt werden (und ein erfahrener Programmierer hat mir gesagt, daß man das nur noch für kleine Sachen - am besten aber überhaupt nicht mehr nach den Programmierrichtlinien verwenden sollte). Ihn hat bei Templates das Debuggen ein wenig erschreckt und deshalb verwendet er diese nur, wenn es wirklich sein muß. Interessant sind auch Funktionstemplates, allerdings erlauben die es aus Compilergründen nicht virtuell zu sein (schade). <FONT COLOR="#a62a2a" SIZE="1">[ 19. September 2001 12:04: Beitrag 1 mal editiert, zuletzt von Crush ]</font> Zitieren
maddin Geschrieben 19. September 2001 Geschrieben 19. September 2001 ich halte die erste funktion für wenig sinnvoll. dabei habe ich keine chance diese zweimal aufzurufen und den selben effekt zu erzielen. <FONT COLOR="#a62a2a" SIZE="1">[ 19. September 2001 12:23: Beitrag 4 mal editiert, zuletzt von maddin ]</font> Zitieren
Poldi Geschrieben 19. September 2001 Autor Geschrieben 19. September 2001 das mit dem elementAt muß doch so aussehen, oder?: --------------------------------- string test; vector<string> myVek; ... test = myVek.elementAt(20); ... --------------------------------- was ist denn er rückgabetyp von elementAt? doch der typ des vektors, oder? naja mein dummer compiler mag das nicht, der sagt mir no matching function .... Zitieren
Crush Geschrieben 19. September 2001 Geschrieben 19. September 2001 @Maddin: Sollte ja auch nur eine Alternative zum Klassenverpacken sein, weil ich´s halt vorher mal angesprochen habe habe ich es auch gleich mit reingenommen. Man kann das ganze ja auch als globales Array verwenden. @Poldi: Huhu das Ding heißt nicht elementAt() sondern nur at() schau doch mal oben in den Source. Da habe ich halt anstatt den . einen -> weil´s halt Zeiger sind. Mit Deinem Source: string test; vector<string> myVek; test = myVek.at(20); Ich weiß ja nicht welchen Compiler Du verwendest, aber wenn Du den . beim Studio benutzt werden alle verfügbaren Funktionen dargestellt und da findet man auch nur das .at()! no matching function heißt ja auch: keine passende Funktion gefunden (existiert so halt nicht unter diesem Namen oder mit diesen Parametern)! Zitieren
Poldi Geschrieben 19. September 2001 Autor Geschrieben 19. September 2001 nein, das tuts auch nicht. ich programmier unter unix mit dem g++ ... das mit dem at scheint was vc++ spezifisches zu sein. in meiner literatur hab ich folgendes gefunden: Object elementAt(int index) was ist denn Object für ein Datentyp? Hat doch irgendwas mit Klassen und so zu tun, oder? aber selbst wenn ich die funktion aufrufe, ohne den rückgabewert irgendwohin zu lenken, compiliert der nicht. menno. ich hab mir jetzt ne eigene funktion dafür geschrieben ... danke leute, ihr habt mir sehr weitergeholfen ... ) mfg -poldi- Zitieren
gajUli Geschrieben 19. September 2001 Geschrieben 19. September 2001 <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR>Original erstellt von Poldi: <STRONG> Object elementAt(int index) was ist denn Object für ein Datentyp? Hat doch irgendwas mit Klassen und so zu tun, oder? </STRONG> Zitieren
multimac Geschrieben 19. September 2001 Geschrieben 19. September 2001 <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR>Gestern habe ich das alles nicht hinbekommen aus einem guten Grund: Man muß den at() Operator anscheinend verwenden. Über den []-Operator konnte ich nur Fehler erzeugen und sonst nix. Zitieren
Crush Geschrieben 19. September 2001 Geschrieben 19. September 2001 "Beim Stöbern im Netz habe ich vorhin folgenden Satz gefunden: "Never return containers! Return iterators!" :-) " Klingt vernünftig. Container sollten meiner Meinung nach immer irgenwo fest verankert sein und nicht bewegt werden. Zugriffe von außen sollten am besten über eigens dafür vorgesehene Methoden ablaufen, damit kein Unfug damit angestellt werden kann. "Wir haben doch noch einen anderen Template-Guru hier, ich glaube Crush... " Ich sehe mich schon im Jogasitz über meinem Nagelbrett schweben (grins)! Nein, ernsthaft: Ich habe selber noch nicht eine eigene Template-Klasse erstellt - bin doch selbst noch beim Lernen! Aber so unheimlich kompliziert ist´s wirklich nicht wie man´s gerne darstellt - wenn man nur versteht, wie´s geschrieben werden soll (Platzhalter für den Datentyp: Das ist doch so extrem abstraktes Denken nun auch wieder nicht). In billigem C-Code habe ich schon wesentlich abstrakteres gesehen (rekursive Lösung der Türme von Hanoi oder (auch rekursiv) das 8-Damen-Problem zum Beispiel hab ich bis heute noch nicht gerafft). Rekursion in der Praxis wäre auch mal einen Thread wert. Ich persönlich halte Multimac für den Erfahrensten dem ich hier im Forum bisher begegnet bin! (ok, vielleicht noch 1-2 andere kann man noch dazunehmen) Zitieren
gajUli Geschrieben 19. September 2001 Geschrieben 19. September 2001 <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR>Original erstellt von multimac: <STRONG> lol - Du siehst ja, ich habe mehr Fragen als Antworten </STRONG> Zitieren
Crush Geschrieben 20. September 2001 Geschrieben 20. September 2001 Ach soooo ist das! Und ich dachte schon, daß der []-Operator als protected deklariert ist und deshalb keine Referenzzugriffe erlaubt! Man soll wohl lieber mit dem Iterator oder at() arbeiten, dann gibt´s auch keinen Ärger. Zitieren
gajUli Geschrieben 20. September 2001 Geschrieben 20. September 2001 <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR>Original erstellt von Crush: <STRONG>Ach soooo ist das! Und ich dachte schon, daß der []-Operator als protected deklariert ist und deshalb keine Referenzzugriffe erlaubt! Man soll wohl lieber mit dem Iterator oder at() arbeiten, dann gibt´s auch keinen Ärger.</STRONG> Zitieren
multimac Geschrieben 20. September 2001 Geschrieben 20. September 2001 Eine gute Referenz zum Nachschlagen gibts übrigens von SGI unter http://www.sgi.com/tech/stl/ . Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.