Überprüfen ob vektor sortiert ist und dabei ein Template benutzen
-
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. Allerdings sollen wir dabei ein template benutzen, d.h. die eine funktion soll die reihenfolge überprüfen können egal ob ints, doubles oder chars in dem vektor stehen (aber nur ein Datentyp im gesamten vektor).Ich hab das vom prinzip her jetzt so:
template<typename T> void irgendwas(const vector<T> &v) { T eingabe; cin>>eingabe; v[0] = eingabe; .... } int main() { vector<int> v[5]; irgendwas<int>(v); return 0; }
Aber ich bekomm da immer fehlermeldungen
main.cpp:65:20: error: no matching function for call to 'isSorted(std::vector<int> [5])'
main.cpp:9:6: note: candidate: template<class T> bool isSorted(const std::vector<T>&)
bool isSorted(const vector<T> &v)main.cpp:9:6: note: template argument deduction/substitution failed:
main.cpp:65:20: note: cannot convert 'v' (type 'std::vector<int> [5]') to type 'const std::vector<int>&'
isSorted<int>(v);Weiß wer was da falsch ist?
-
Du musst nochmal ein bisschen C++ Syntax lernen.
vivess schrieb:
vector<int> v[5];
Das erzeugt dir ein Array aus 5 Stück
vector<int>
.
Und ein Array aus 5 Stückvector<int>
ist halt was anderes als ein einzelnervector<int>
.
-
Ja und weiter? kann ich jetzt nichts mit anfangen.
-
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(); }