STL-Container - Vector
-
vip@r schrieb:
Wie soll man das dann machen?
Statt
cin >> wert[i];schreibst du einfach:int Temp; cin >> Temp; wert.push_back(Temp);
-
vector<double> werte; ... do ... int einzelwert; cin >> einzelwert; werte.push_back( einzelwert ); ...
-
Nein, du liest den Wert innerhalb der Schleife in eine Variable ein und wirfst diese dann per push_back() in den vector<>
double wert; cin>>wert; werte.push_back(wert);
-
Hm, soweit funktioniert das jetzt. Nun möchte ich noch eine Funktion schreiben, die mir den Mittelwert berechnet. Wie übergebe ich nun am besten den Vector an die Funktion?
-
Am besten als const-Ref.
Aber wieso selber schreiben - die einfachste Lösung wäre std::accumulate()
-
In meinem C++-Buch finde ich leider keine Informationen zu accumulate()...
Kannst du mir noch ein bisschen draufhelfen?
-
-
google und die referenzen sind dein Freund:
-
Den Vector mit Zeigern oder mit einer der Standardmethoden an dei Funktion übergeben ist wohl nicht möglich?
-
vector::begin() und vector::end()

-
vip@r schrieb:
Den Vector mit Zeigern oder mit einer der Standardmethoden an dei Funktion übergeben ist wohl nicht möglich?
Klar ist es möglich, aber ist nicht sinnvoll (Übergabe als Kopie wird recht aufwendig wenn der vector<> größer wird, Übergabe als Pointer ist ein Relikt aus C-Zeiten).
-
Hm, gut. Dann ist hier wohl das an eine Funktion übergeben wohl wirklich nicht so der bringer.
Aber: Ich verstehe irgendwie nicht, dass C++ hier quasi "verweigert", bzw. es anscheinend sehr schwer macht den Vector an eine Funktion zu übergeben und in der dann den Vector mit einer for-Schleife auslesen und dann eben die Werte aufaddieren und durch 2 zu teilen.
So, wie ich das verstanden habe, benötige ich ja für accumulate() auch noch Iteratore von denen ich widerum (noch) nicht weiß wie das gehen soll...
-
vip@r schrieb:
Hm, gut. Dann ist hier wohl das an eine Funktion übergeben wohl wirklich nicht so der bringer.
Aber: Ich verstehe irgendwie nicht, dass C++ hier quasi "verweigert", bzw. es anscheinend sehr schwer macht den Vector an eine Funktion zu übergeben und in der dann den Vector mit einer for-Schleife auslesen und dann eben die Werte aufaddieren und durch 2 zu teilen.
Was heißt hier "verweigert"? Es ist möglich, vector<>en zu kopieren, du mußt nur damit rechnen, daß dort eine ganze Menge Daten zusammenkommt. Deshalb verwendet man da lieber eine (const) Referenz.
So, wie ich das verstanden habe, benötige ich ja für accumulate() auch noch Iteratore von denen ich widerum (noch) nicht weiß wie das gehen soll...
Iteratoren sind eine Abstraktion, damit die Algorithmen nicht für jeden Container neu angepasst werden müssen (außerdem kannst du mit ihnen auch blanke Arrays oder Teilbereiche deines Containers beschreiben). Und die STL-Containerklassen bieten die Methoden begin() und end(), um Iteratoren für alle Elemente zu ermitteln:
double mv = accumulate(werte.begin(),werte.end(),0.0) / werte.size();
-
Ich hab jetzt mal versucht die Mittelwertberechnung ohne Funktion zu realisieren. Dabei ist mir nun folgendes aufgefallen. Wenn der Zähler der for-Schleife auf 0 steht, dann adressiert er mir ja das Element 0 im Vector. Nur steht da eine 0 obwohl ich für das 0-te-Element eine andere Zahl als 0 eingegeben habe...
Hier der Code:
#include<iostream> #include<vector> #include<numeric> using namespace std; //void mittelwert(vector<double>* werte) //{ // int i, anzahl; // // anzahl = werte[i]; // //} int main() { int anzahl = 0, c = 0; int wert = 0, summe = 0, ergebnis = 0; vector<double> werte(1); cout << "Mittelwert-Berechnung" << endl << endl; do { cout << anzahl+1 << ". Wert angeben: "; c = cin.peek(); if(c != 'e') { cin >> wert; werte.push_back(wert); char cend = cin.get(); anzahl++; } } while(c != 'e'); cout << werte[3]; for(int i=0; i<anzahl; i=i+1) { summe = summe + werte[i]; } ergebnis = summe / anzahl; return 0; }
-
Du hast den vector<> mit einem Element angelegt, das mit 0 vorbelegt ist - die von dir eingelesenen Elemente beginnen ab Index 1.
-
Hm. Da wär ich jetzt nie drauf gekommen. Man kann anscheinend vectoren auch mit 0 vorbelegen.
So, jetzt vielleicht nochmal zum Thema vectoren an Funktionen übergeben. Wie mach ich das jetzt am Besten, bzw. ich hab dazu noch einige Frage:
double mv = accumulate(werte.begin(),werte.end(),0.0) / werte.size();Wenn ich jetzt den Code von dir anschau ist mir da jetzt einiges nicht klar. Dass die Methode size() die Anzahl der im vector<> enthaltenen Element zurückgibt hab ich erlesenen können; somit ist das klar.
Returns the result of accumulating all the values in the range [first,last) to init.
accumulate ( InputIterator first, InputIterator last, T init );
Was aber nun accumulate() genau macht ist mir noch nicht ganz klar. Laut cplusplus ist die Standardoperation das Aufsummieren aller Elemente in einem Bereich und zurückgeben des berechneten Wertes. Was mir aber nicht klar ist, ist was mit dem "init" in obigem Zitat gemeint ist. Ich kann mir zwar denken, dass die Methode .begin quasi den Wert liefert der von obiger Definition durch first gefordert ist und die Methode .end den Wert liefert der von obiger Definition durch last gefordert ist. Was aber mach nunt begin und end wirklich?
Gibts eigentlich noch eine andere Seite als cplusplus bei der man evtl. einfach er auf die Methoden-Erklärung der STL kommt?
-
vip@r schrieb:
Wenn ich jetzt den Code von dir anschau ist mir da jetzt einiges nicht klar. Dass die Methode size() die Anzahl der im vector<> enthaltenen Element zurückgibt hab ich erlesenen können; somit ist das klar.
Returns the result of accumulating all the values in the range [first,last) to init.
accumulate ( InputIterator first, InputIterator last, T init );
Was aber nun accumulate() genau macht ist mir noch nicht ganz klar. Laut cplusplus ist die Standardoperation das Aufsummieren aller Elemente in einem Bereich und zurückgeben des berechneten Wertes. Was mir aber nicht klar ist, ist was mit dem "init" in obigem Zitat gemeint ist. Ich kann mir zwar denken, dass die Methode .begin quasi den Wert liefert der von obiger Definition durch first gefordert ist und die Methode .end den Wert liefert der von obiger Definition durch last gefordert ist. Was aber mach nunt begin und end wirklich?
Du kannst dir die Iteratoren als eine Weiterentwicklung von Zeigern vorstellen - du kannst sie dereferenzieren, weiterschieben und vergleichen. begin() liefert einen Iterator auf den Anfang des Containers, end() einen auf das Ende (genauer: hinter das letzte Element), damit hast du einen Bereich, den du als first/last an den Algorithmus übergeben kannst.
Der Wertinitist der Startwert für die Summierung (und entspricht demsumme = 0bei deiner manuellen Schleife. Der ist nötig, weil dort je nach Anwendung andere Ausgangswerte notwendig werden könnten, z.B.://geometrisches Mittel: double geo = pow( accumulate(werte.begin(),werte.end(),1.0,multiplies<double>), 1/werte.size() ); //String-Verkettung: vector<string> zeilen; ... string datei = accumulate(zeilen.begin(),zeilen.end(),string());
-
vip@r schrieb:
Returns the result of accumulating all the values in the range [first,last) to init.
accumulate ( InputIterator first, InputIterator last, T init );
Nochmal ein bisschen anders erklaert: Stell dir einen Iterator wie ein Zeiger vor. Dieser zeigt an eine bestimmte Stelle in deiner Datentruktur, in deinem Falle ein vector. Die Funktion accumulate will von dir zwei solcher Zeiger haben. Einen der auf den Anfang und einen der auf das Ende der Datenstruktur zeigt.
Beispiel:
vector<int> werte; // Fülle den vector 'werte' mit den zahlen von 0-9 for(int i = 0; i < 10; ++i) werte.push_back(i);Das sieht dann grafisch ungefaehr so aus:
================================================= | 0 || 1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9 | =================================================Jetzt stellt dir dein vector diese Iteratoren bereit. In deinem Falle begin() und end(). Die würden dann hierhin zeigen:
================================================= | 0 || 1 || 2 || 3 || 4 || 5 || 6 || 7 || 8 || 9 | ================================================= begin()-^ end() -^begin() zeigt auf das erste Element und end() auf das Element nach dem letzten Element.
Jetzt sagst du accumulate: Hey, summiere mir mal die Wete von begin() bis end(). Dann laeuft accumulate gemütlich von Element zu Element bis es im Nichts (bei end()) landet und hört dann auf. Es macht also 0+1+2+3+4+5+6+7+8+9. Nebenbei hast du halt die Möglichkeit einen eigenen Startwert anzugeben, also: meinStartWert+0+1+2+3+4+5+6+7+8+9. Und genau dieser Startwert ist das init.
Nach diesem Iteratorprinzip laufen alle Container der STL. Diese Iterator geben dir die Möglichkeit unabhaegig von der wirklichen Datenstruktur dahinter mit Algorithmen (wie accumulate) darauf zu arbeiten. Jede Datenstrukur stellt Iteratoren bereit, sodass du an accumulate gerne auch ein std::list oder ein std::deque übergeben könntest.
Siehst du wie schön das ist! Du hast eine Funktion und kannst verschieden Datenstrukturen übergeben ohne für jede Datenstruktur ein eigenes accumulate zu schreiben und von diesem accumulate gibt es noch weitere Zahlreiche in der STL.
vip@r schrieb:
Gibts eigentlich noch eine andere Seite als cplusplus bei der man evtl. einfach er auf die Methoden-Erklärung der STL kommt?
Das Forum und die dir genannte Referenz. Wie oben beschrieben laeuft alles nach einem Prinzip. Hast du es einmal verstanden, verstehst du auch alles
