Überprüfen ob vektor sortiert ist und dabei ein Template benutzen
-
vivess schrieb:
Ja und weiter? kann ich jetzt nichts mit anfangen.
Hi,
Deine Funktion verlangt eine Referenz auf einen Vektor von ints. Du übergibst aber einen Vektor von Vektoren von ints.
VG Martin
-
vivess schrieb:
main.cpp:65:20: error: no matching function for call to 'isSorted(std::vector<int> [5])'
in deinem Code sehe ich kein "is_sorted".
möglicherweise erledigt sich dieser Fehler, wenn du den die Sache mit [5] korrigierst, allerdings schon.
Abgesehen davon ist es aber immer blöd, Fehlermeldungen zu schreiben, die sich auf Code beziehen, den du nicht zeigst. (Immerhin postest du die Fehlermeldung, das ist schonmal mehr, als andere User schaffen
)
-
mgaeckler schrieb:
vivess schrieb:
Ja und weiter? kann ich jetzt nichts mit anfangen.
Hi,
Deine Funktion verlangt eine Referenz auf einen Vektor von ints. Du übergibst aber einen Vektor von Vektoren von ints.
VG Martin
Wie schreib ich es dann richtig? jetzt versteh ich überhaupt nichts mehr. wir sollen dieses call-by-reference halt mit referenzen machen und nicht mit zeigern. wenn ich da
irgendwas<int>(v[0]);
hinschreibe bekomm ich keine fehlermeldung, aber das ist ja bestimmt keine referenz auf einen vektor von ints.
daddy_felix schrieb:
vivess schrieb:
main.cpp:65:20: error: no matching function for call to 'isSorted(std::vector<int> [5])'
in deinem Code sehe ich kein "is_sorted".
möglicherweise erledigt sich dieser Fehler, wenn du den die Sache mit [5] korrigierst, allerdings schon.
Abgesehen davon ist es aber immer blöd, Fehlermeldungen zu schreiben, die sich auf Code beziehen, den du nicht zeigst. (Immerhin postest du die Fehlermeldung, das ist schonmal mehr, als andere User schaffen
)
Ich wollte es aufs nötigste minimieren, der rest vom quelltext hat ja nichts mit meinem problem zu tun.
-
vivess schrieb:
irgendwas<int>(v[0]);
hinschreibe bekomm ich keine fehlermeldung, aber das ist ja bestimmt keine referenz auf einen vektor von ints.
Warum nicht?
Was ist es denn?
-
Ich habs mittlerweile raus. Ich habe
vector<int> v[5]
anstatt
vector<int> v(5)
geschrieben. bin da durcheinander gekommen mit den arrays. Ich weiß zwar nicht was das erstere bedeutet, aber auf jeden fall nicht das was ich will. Mit zweitere variante kann ich den vector so
name_von_funktion(v)
als referenz übergeben.
programm sieht jetzt so aus:
#include <iostream> #include <vector> #include <string> using namespace std; template<typename T> bool isSorted(vector<T> &v) { cout<<"Gebe nacheinander ints, doubles oder chars ein, danach wird ueberprueft ob diese in aufsteigender Reihenfolge eingegeben wurden!\n"; int x; T eingabe; for(x=0; x<5; ++x) { cin>>eingabe; // Werte in vektor einlesen v[x] = eingabe; } int zaehler=0; int y; for(x=0, y=1 ; y<5 ; ++x , ++y) { if (v[x] <= v[y]) // Überprüfen ob vektor in aufsteigender reihenfolge sortiert ist ++zaehler; else break; } if(zaehler==4) return true; else return false; } int main() { cout<<"Geben an, ob die Reihenfolge des vektors auf int, double oder chars geprüft werden soll! (i, d oder c eingeben)\n"; char pruefung; cin>>pruefung; switch(pruefung) { case 'i': { vector<int> i(5); if(isSorted<int>(i)==true) cout<<"Die angegebenen ints sind in aufsteigender reihenfolge eingegeben worden!\n"; else cout<<"Die angegebenen ints sind NICHT in aufsteigender reihenfolge eingegeben worden!\n"; break; } case 'd': { vector<double> d(5); if(isSorted<double>(d)==true) cout<<"Die angegebenen double sind in aufsteigender reihenfolge eingegeben worden!\n"; else cout<<"Die angegebenen double sind NICHT in aufsteigender reihenfolge eingegeben worden!\n"; break; } case 'c': { vector<char> c(5); if(isSorted<char>(c)==true) cout<<"Die angegebenen chars sind in aufsteigender reihenfolge eingegeben worden!\n"; else cout<<"Die angegebenen char sind NICHT in aufsteigender reihenfolge eingegeben worden!\n"; break; } default: { cout<<"Fehler! i, d oder c eingeben (i=int ; d=double ; c=char)!\n"; } } return 0; }
Läuft jetzt zwar, aber erfahrungsgemäß ist da bestimmt wieder was falsch oder?
-
vivess schrieb:
hi,
wir sollen eine funktion benutzen die als paramter ein vektor als referenz übergeben bekommt und mit der funktion sollen wir überprüfen ob der vektor in z.b. aufsteigender reihenfolge sortiert ist oder nicht.Deine Funktion isSorted liest genau 5 Werte ein und prüft diese. Weder passt der Name zum Verhalten noch scheint das der Aufgabenstellung zu entsprechen.
-
die funktion überprüft ob die werte im vektor in aufsteigender reihenfolge sortiert sind oder nicht, und das ist die aufgabenstellung. wenn ich 1,2,3,4,5 eingebe sagt der mir, das es sortiert ist und falls ich 4,27,1,9,3 eingebe sagt der mir es ist nicht sortiert. das gleiche funktioniert auch mit doubles und chars.
-
Wenn sich dein Lehrer deiner Interpretation anschließest ...
-
aha. was meinst du denn jetzt genau? soviel spielraum bei der aufgabenstellung ist da nicht.
-
Nein.
Deine Funktion liest 5 Zahlen ein, überschreibt den übergebenen Vector damit und testete dann, ob diese Zahlen sortiert sind. Sie macht also mehrere Dinge.
In der Aufgabenstellung soll sie aber (nur) testen, ob ein übergebener vector sortiert ist. Nicht irgendwelche anderen Dinge.
In deiner Ursprungsfrage hattest du auch noch den sinnvollen Paramter
const vector<T> &v
, jetzt nur nochvector<T> &v
. Wozu übergibst du überhaupt einen Parameter? Das ist doch in deinem Code nicht sinnvoll. Sinnvoll wird es dann, wenn die Funktion isSorted den vector nur ansieht, aber nicht ändert.Und zu dem
vector<int> v[5];
mit eckigen Klammern: das wurde dir doch geschrieben, was das ist, z.B. gleich in der ersten Antwort von hustbaer. Nämlich ein Array von Vectoren.
Und zum Aufruf des isSorted: das Template-Argument übergibt man bei solchen Funktionsaufrufen NICHT explizit, das soll der Compiler ja gerade selbst machen. Also NICHT
if(isSorted<int>(i)==true)
, sondern
if(isSorted(i)==true)
. Abgesehen davon, dass du einen bool nicht mit
== true
vergleichen solltest, das ist schlicht überflüssig. Also nur so:if (isSorted(i))
-
ah ok.
Ich habs jetzt so:
#include<iostream> #include<vector> using namespace std; template<typename T> bool isSorted(const vector<T> &v) { int x,y,zaehler; zaehler=0; for(x=0, y=1; y<5; ++x, ++y) { if(v[x] <= v[y]) ++zaehler; else break; } if(zaehler==4) return true; else return false; } int main() { cout<<"Geben an, ob die Reihenfolge des vektors auf int, double oder chars geprüft werden soll! (i, d oder c eingeben)\n"; char pruefung; cin>>pruefung; int x; switch(pruefung) { case 'i': { cout<<"Gebe nun 5 ints ein!\n"; vector<int> i(5); int ganzzahl; for(x=0; x<5; ++x) { cin>>ganzzahl; i[x]=ganzzahl; } if(isSorted(i)) cout<<"Die angegebenen ints sind in aufsteigender reihenfolge sortiert!"; else cout<<"Die angegebenen ints sind NICHT in aufsteigender reihenfolge sortiert!"; break; } case 'd': { cout<<"Gebe nun 5 doubles ein!\n"; vector<double> d(5); double kommazahl; for(x=0; x<5; ++x) { cin>>kommazahl; d[x]=kommazahl; } if(isSorted(d)) cout<<"Die angegebenen doubles sind in aufsteigender reihenfolge sortiert!"; else cout<<"Die angegebenen doubles sind NICHT in aufsteigender reihenfolge sortiert!"; break; } case 'c': { cout<<"Gebe nun 5 chars ein!\n"; vector<int> c(5); char zeichen; for(x=0; x<5; ++x) { cin>>zeichen; c[x]=zeichen; } if(isSorted(c)) cout<<"Die angegebenen chars sind in aufsteigender reihenfolge sortiert!"; else cout<<"Die angegebenen chars sind NICHT in aufsteigender reihenfolge sortiert!"; break; } default: { cout<<"Fehler! i, d oder c eingeben (i=int ; d=double ; c=char)!\n"; } } return 0; }
-
Besser, aber noch nicht gut.
Denn deine Funktion sollte jetzt nicht "isSorted", sondern "isVectorMitLaenge5sorted" heißen.
Damit sie zum isSorted wird, darfst du keine magischen Zalen wie 4 oder 5 in der Funktion verwenden! Die Funktion muss auch mit vectoren der Länge 0, 1, 2 oder 10 klarkommen können.
-
Ah ok. Dann also mit v.push_back() und v.size()
was wäre besser
1.) Solange in den vektor zahlen/zeichen einzulesen bis ein bestimmtes zeichen eingelesen wird oder
2.) im vorfeld zu fragen "wie viele zeichen sollen eingelesen werden" und dann dementsprechend viele zeichen in den vektor einlesen?
-
habe es nun so
#include<iostream> #include<vector> using namespace std; template<typename T> bool isSorted(const vector<T> &v) { int x,y,zaehler; zaehler=0; for(x=0, y=1; y<v.size(); ++x, ++y) { if(v[x] <= v[y]) ++zaehler; else break; } if(zaehler==v.size()-1) return true; else return false; } template<typename X> X getAverage(const vector<X> &v) { int x; X summe, durschnitt; summe=summe-summe; for(x=0; x<v.size(); ++x) { summe+=v[x]; } durschnitt=summe/v.size(); return durschnitt; } int main() { cout<<"Geben an, ob die Reihenfolge des vektors auf int, double oder chars geprüft werden soll! (i, d oder c eingeben)\n"; char pruefung; cin>>pruefung; int x, anzahl_werte; switch(pruefung) { case 'i': { cout<<"Wie viele ints sollen in den vektor geschrieben werden?\n"; cin>>anzahl_werte; cout<<"Gebe nun "<<anzahl_werte<<" ints ein:\n"; vector<int> i; int ganzzahl; for(x=0; x<anzahl_werte; ++x) { cin>>ganzzahl; i.push_back(ganzzahl); } if(isSorted(i)) cout<<"Die angegebenen ints sind in aufsteigender reihenfolge sortiert!\n"; else cout<<"Die angegebenen ints sind NICHT in aufsteigender reihenfolge sortiert!\n"; cout<<"Der durchschnitt der im vektor eingetragenen werte betraegt: "<<getAverage(i)<<'\n'; break; } case 'd': { cout<<"Wie viele doubles sollen in den vektor geschrieben werden?\n"; cin>>anzahl_werte; cout<<"Gebe nun "<<anzahl_werte<<" doubles ein:\n"; vector<double> d; double kommazahl; for(x=0; x<anzahl_werte; ++x) { cin>>kommazahl; d.push_back(kommazahl); } if(isSorted(d)) cout<<"Die angegebenen doubles sind in aufsteigender reihenfolge sortiert!\n"; else cout<<"Die angegebenen doubles sind NICHT in aufsteigender reihenfolge sortiert!\n"; cout<<"Der durchschnitt der im vektor eingetragenen werte betraegt: "<<getAverage(d)<<'\n'; break; } case 'c': { cout<<"Wie viele chars sollen in den vektor geschrieben werden?\n"; cin>>anzahl_werte; cout<<"Gebe nun "<<anzahl_werte<<" chars ein:\n"; vector<int> c; char zeichen; for(x=0; x<anzahl_werte; ++x) { cin>>zeichen; c.push_back(zeichen); } if(isSorted(c)) cout<<"Die angegebenen chars sind in aufsteigender reihenfolge sortiert!\n"; else cout<<"Die angegebenen chars sind NICHT in aufsteigender reihenfolge sortiert!\n"; cout<<"Der durchschnitt der im vektor eingetragenen werte betraegt: "<<getAverage(c)<<'\n'; break; } default: { cout<<"Fehler! i, d oder c eingeben (i=int ; d=double ; c=char)!\n"; } } return 0; }
-
Ok, jetzt können wir nochmal weitermeckern
Folgende Punkte nun noch offen:
1. Naming. Für Laufvariablen in Schleifen verwendet man in der Regel sowas wie i oder j, aber nicht x. Dein Vector heißt allerdings i, den würde ich dann anders nennen.2. Scope. Halte den Gültigkeitsbereich der Variable so klein wie möglich und deklariere sie nur dort, wo du sie auch gleich benutzt. Lass keine Variable uninitialisiert. Also nicht:
int x; for (x = 0; x < v.size(); ++x) { ... }
sondern:
for (size_t i = 0; i < v.size(); ++i) { ... }
Wenn du Warnungen eingeschaltet hast, hättest du außerdem bei deinem Code eine signed/unsigned-comparison-Warnung erhalten müssen, denn size() liefert nicht int, sondern size_t als Typ zurück.
3. Kreative Initialisierung:
X summe, durschnitt; summe=summe-summe;
Ich denke, mann kann davon ausgehen, dass man Zahlen auch den Wert 0 zuweisen kann. Also
X summe = 0;
Bin mir nicht einmal sicher, ob dein Code definiertes Verhalten hat.
Und die Variable durchschnitt brauchst du erst nach der for-Schleife, also sollte sie auch erst danach deklariert werden.4. Überflüssige Fallunterscheidung:
if(zaehler==v.size()-1) return true; else return false;
Du hast doch in der if-Abfrage schon den korrekten Wert ermittelt! Wozu das if? Mach doch einfach
return zaehler == v.size()-1;
. Hast du dir eigentlich mal überlegt, wie großv.size()-1
ist, wennv.size() == 0
ist?5. Pro-Tipp: Suchst du für dein isSorted nicht eigentlich 2 Zahlen nebeneinander unter einer bestimmten Bedingung? Schau doch mal im
<algorithm>
-Header nach, was es da so gibt. Tipp: benachbarte Objekte nennt man "adjazent".
-
template<typename X> X getAverage(const vector<X> &v) { int x; X summe, durschnitt; summe=summe-summe; ...
- Template-Parameter nennt man in solchen Funktionen üblicherweise T, nicht X.
- Das ist ne nette Idee, aber undefiniertes Verhalten wenn X z.B. int, double, ... ist. Also das Lesen von un-initialisierten Variablen. Besser:
template<typename X> X getAverage(const vector<X> &v) { int x; X summe = X(), durschnitt; summe=summe-summe; // ist jetzt eigentlich nicht mehr nötig ...
- Noch besser:
durschnitt
erst dort definieren wo du es gleich mit dem passenden Wert initialisieren kannst. Bzw. u.U. gleich ganz weglassen -return summe/v.size();
würde es auch tun.
-
Klassischer Einzeiler:
template< typename T > T getAverage( std::vector< T > const& v ) { return std::accumulate( v.begin(), v.end(), T{} ) / v.size(); }
-
Noch mal zurück zu
isSorted
:
Du brauchst in der Funktion nur die Zählvariable für die Schleife, die übrigen Informationen stecken alle im Vektor. Du benutzt als Zählvariablex
undy
, wobeiy
immer 1 größer ist alsx
. Es reicht also aus, wenn du nur eine Zählvariable benutzt und zum Vergleichen von zwei Elementen deren Wert um 1 erhöhst oder verringerst.// Variante 1: for( size_t i = 0; i < v.size() -1; ++i ) { // Vergleiche Elemente an Position i und i +1 } // Variante 2: for( size_t i = 1; i < v.size(); ++i ) { // Vergleiche Elemente an Position i-1 und i }
Variante 1 hat Variante 2 gegenüber einen Nachteil, es muss der Sonderfall für Vektoren der Länge 1 oder weniger behandelt werden, da i +1 sonst auf ungültige Elemente zugreift.
Außerdem braucht du die Information, wie viele Elemente sortiert sind, nicht. Sobald von zwei aufeinanderfolgenden Elementen das erste größer als das zweite ist weißt du schon, dass der Vektor nicht sortiert ist und kannst
false
zurückgeben.if( v[i] > v[i +1] ) return false;
Damit kannst du deine Funktion auf maximal 5 Zeilen reduzieren, selbst wenn du großzügig Code auf mehrere Zeilen verteilst.
-
@ Einzeller
Ja, klar.Ich bin allerdings der Meinung dass es für Lernende oft besser ist wenn man Stück für Stück vorgeht. Also erstmal alles was schlecht/verbesserungswürdig ist anspricht und "korrigiert", auch wenn es Dinge sind die in der "optimalen" Lösung überhaupt nicht mehr vorkommen. Und den Code den sie zeigen Schritt für Schritt in die "optimale" Lösung verwaldelt und jeden Schritt erklärt.
Natürlich ist das sehr mühsam, und ich beschränke mich meist darauf ein oder maximal zwei solche Schritte pro Posting aufzuzeigen. Wenn der Lernende dann die Geduld verliert oder ich vergesse den Thread weiter zu verfolgen, dann hat er am Ende natürlich nicht die optimale Lösung. Aber er hat vermutlich (hoffentlich) mehr dabei gelernt als wenn man ihm die fertige optimale Lösung hinschreibt.
-
hi,
ich hab nun so manches abgeändert/verbessert:#include<iostream> #include<vector> using namespace std; template<typename T> bool isSorted(const vector<T> &v) { for(size_t i=1; i<v.size(); ++i) { if(v[i] >= v[i-1]); else return false; } return true; } template<typename T> double getAverage(const vector<T> &v) { double summe = 0; for(size_t i=0; i<v.size(); ++i) { summe+=v[i]; } return summe/v.size(); } int main() { cout<<"Geben an, ob die Reihenfolge des vektors auf int, double oder chars geprüft werden soll! (i, d oder c eingeben)\n"; char pruefung; cin>>pruefung; int i, anzahl_werte; switch(pruefung) { case 'i': { cout<<"Wie viele ints sollen in den vektor geschrieben werden?\n"; cin>>anzahl_werte; cout<<"Gebe nun "<<anzahl_werte<<" ints ein:\n"; vector<int> a; int ganzzahl; for(i=0; i<anzahl_werte; ++i) { cin>>ganzzahl; a.push_back(ganzzahl); } if(isSorted(a)) cout<<"Die angegebenen ints sind in aufsteigender reihenfolge sortiert!\n"; else cout<<"Die angegebenen ints sind NICHT in aufsteigender reihenfolge sortiert!\n"; cout<<"Der durchschnitt der im vektor eingetragenen werte betraegt: "<<getAverage(a)<<'\n'; break; } case 'd': { cout<<"Wie viele doubles sollen in den vektor geschrieben werden?\n"; cin>>anzahl_werte; cout<<"Gebe nun "<<anzahl_werte<<" doubles ein:\n"; vector<double> b; double kommazahl; for(i=0; i<anzahl_werte; ++i) { cin>>kommazahl; b.push_back(kommazahl); } if(isSorted(b)) cout<<"Die angegebenen doubles sind in aufsteigender reihenfolge sortiert!\n"; else cout<<"Die angegebenen doubles sind NICHT in aufsteigender reihenfolge sortiert!\n"; cout<<"Der durchschnitt der im vektor eingetragenen werte betraegt: "<<getAverage(b)<<'\n'; break; } case 'c': { cout<<"Wie viele chars sollen in den vektor geschrieben werden?\n"; cin>>anzahl_werte; cout<<"Gebe nun "<<anzahl_werte<<" chars ein:\n"; vector<int> c; char zeichen; for(i=0; i<anzahl_werte; ++i) { cin>>zeichen; c.push_back(zeichen); } if(isSorted(c)) cout<<"Die angegebenen chars sind in aufsteigender reihenfolge sortiert!\n"; else cout<<"Die angegebenen chars sind NICHT in aufsteigender reihenfolge sortiert!\n"; cout<<"Der durchschnitt der im vektor eingetragenen werte betraegt: "<<getAverage(c)<<'\n'; break; } default: { cout<<"Fehler! i, d oder c eingeben (i=int ; d=double ; c=char)!\n"; } } return 0; }
getaverage hab ich etwas verändert, damit der mir auch bei ints ein genaues ergebnis liefert.
summe=summe-summe hatte ich geschrieben weil ich gedacht hab 0 könnte ich nicht in ein double schreiben (sondern müsste 0.0 schreiben was bei int dann rumspackt). Ist aber wohl nicht so.
Das
X summe = X(), durschnitt;
und das mit dem adjazent haben wir noch nich. Bin mir nicht so sicher ob wir sachen benutzen dürfen die wir noch nicht hatten.
Achja das mit den warnungen ist so ein problem bei mir... Ich benutze netbeans mit cygwin und irgendwie gibt der keine warnungen aus beim kompilieren. Bei dem compile befehl den man unten in der box sieht, schreibt der auch nirgendwo den paramter "-w". Hatte deswegen schonmal gegoogelt, bin aber nicht drauf gekommen wie man das bei netbeans einstellt, falls es überhaupt geht. finde auch in den einstellungen dazu nichts.