Benutzerdefinierter Dateityp: Operatoren definieren
-
Unsere Aufgabe in dieser Woche ist es, Felder eines beliebigen Datentyps ElemT
einzulesen und zu sortieren.
Die Sortieralgorithmen habe ich bereits in der letzten Woche programmiert, und
muss sie somit nur noch anpassen.Insgesamt müssen 3 Felder sortiert werden:
double-Feld doubles.txt
string-Feld strings.txt
Student-Feld student.txtFür den benutzerdef. Datentyp 'Student' steht bereits ein Grundgerüst bereit,
das um einen Ausgabeoperator '<<', sowie Vergleichsoperatoren '<', '==' und '!='
ergänzt werden soll.
Und hier enstehen für mich als absoluten Anfänger direkt Schwierigkeiten:Hier einmal das Grundgerüst:
#include "student.h" // Eingabeoperator ">>" std::istream& operator>> ( std::istream& s, Student& a) { s >> a.Vorname >> a.Nachname >> a.MatNr >> a.Note; return s; } // Ausgabeoperator "<<" std::ostream& operator<< ( std::ostream& s, const Student& a) { // hier den Ausgabeoperator definieren } // Vergleichsoperator "<" bool operator< ( const Student&, const Student&) { // hier fehlt was } // Vergleichsoperatoren "==" bzw. "!=" bool operator== ( const Student&, const Student&) { // hier fehlt was } bool operator!= ( const Student&, const Student&) { // hier fehlt was }Meine Ideen:
- Ausgabeoperator: Ich weiß leider nicht wie ich die 4 Merkmale (Vorn., Nachn., Matr.nr. und Note wie gewünscht ausgeben kann)- Vergleichsoperator <:
Hier vergleiche ich Zeichen für Zeichen:
Ist a[i] < b[i] so ist a<b.
- Vergleichsoperator ==:
Zuerst Länge vergleichen: untersch. Längen => false
Ansonsten Zeichen für Zeichen: if a[i] != b[i], dann false
- Vergleichsoperator !=:
Umkehrfkt. zu ==, also dessen Ergebnis negieren.Im Code würde das bei mir nun so ausschauen:
#include "student.h" // Eingabeoperator ">>" std::istream& operator>> ( std::istream& s, Student& a) { s >> a.Vorname >> a.Nachname >> a.MatNr >> a.Note; return s; } // Ausgabeoperator "<<" std::ostream& operator<< ( std::ostream& s, const Student& a) { // hier den Ausgabeoperator definieren } // Vergleichsoperator "<" bool operator< ( const Student& a, const Student& b) { std::size_t min_length = std::min(a.length(), b.length()); for(std::size_t i = 0; i < min_length; ++i){ if(a[i] < b[i]){ return true; } if(a[i] > b[i]){ return false; } } if(a.length() >= b.length()){ return false; } return true; } // Vergleichsoperatoren "==" bzw. "!=" bool operator== ( const Student& a, const Student& b) { if(a.length() != b.length()){ return false; } for(std::size_t i = 0; i < a.length(); ++i){ if(a[i] != b[i]){ return false; } } return true; } bool operator!= ( const Student& a, const Student& b) { return !(a == b); }Wäre für jeden Tipp, sowie Hilfe (vor allem bei dem Ausgabeoperator) dankbar

VG
-
Du weißt wie die Daten eingelesen werden sollen. Damit weißt du ja auch, wie sie geschrieben werden könnten.
Du brauchst nur ein Trennzeichen zwischen den Werten.
(Wie stehen sie denn in student.txt?
)Wie sollen denn die Studenten sortiert werden?
(Was macht das length oder []-Operator?)Sollten bei Vergleichen nicht alle Eigenschaften verglichen werden?
Btw, du musst nur operator< implementieren... == und != lassen sich damit ausdrücken.
std::string::compare könnte das vereinfachen...
-
Ein Beispiel:
Carl-Friedrich Gauss 111111 1.0student.txt besteht aus 12 solcher Einträge.
Die Einträge sollen aufsteigend nach Nachnamen, bei gleichen Nachn. nach Vornamen, sortiert werden.
Jetzt fällt mir auf, dass ich die Operatoren da wohl noch anpassen muss

(bzgl. der versch. Eigenschaften)Ich versuche das mal für '<':
bool operator< ( const Student& a, const Student& b) { std::size_t min_nachname = std::min(a.Nachname.length(), b.Nachname.length()); std::size_t min_vorname = std::min(a.Vorname.length(), b.Vorname.length()); //gleiche Nachnamen if(a.Nachname == b.Nachname){ for(std::size_t i = 0; i < min_vorname; ++i){ if(a.Vorname[i] < b.Vorname[i]){ return true; } if(a.Vorname[i] > b.Vorname[i]){ return false; } } if(a.Vorname.length() >= b.Vorname.length()){ return false; } return true; } for(std::size_t i = 0; i < min_nachname; ++i){ if(a.Nachname[i] < b.Nachname[i]){ return true; } if(a.Nachname[i] > b.Nachname[i]){ return false; } } if(a.Nachname.length() >= b.Nachname.length()){ return false; } return true; }Hier stellt sich mir noch eine Frage:
In der Abfrageif(a.Nachname == b.Nachname)greife ich ja auf den '=='-Operator zurück.
Nun weiß ich nicht wie ich '==' mit '<' ausdrücken kann
EDIT: Werde mir das mit dem std::string::compare mal ansehen. Das scheint einfacher zu sein
-
Um deine direkte Frage zu beantworten: Wenn etwas weder < noch > ist, dann ist es ==. Und > kannst du als < schreiben, indem du einfach beide Seiten umdrehst.
Aber: Der Vergleich der einzelnen Namensbestandteile ist nicht Aufgabe des Studenten-Vergleichsoperators. Haben die Datentypen für Vor- und Nachname denn keine eigenen Vergleichsoperatoren? Falls sie welche haben: Nutze diese! Falls sie keine haben: Schreib welche und nutze diese!
Somit wird dann der Studenten-Vergleichsoperator sowohl einfacher als auch robuster gegen Änderungen und Fehler.
-
Habe jetzt noch im Netz nachgeschaut (bin wirklich ein absoluter Neuling in Sachen C++):
In C++ kann ich Zeichenketten vom Typ string einfach mit Hilfe von
==, !=, <, >, <=, => miteinander vergleichen oder?Nun nehme ich mal 2 Dateien vom Typ student:
Pierre-Louis Lions 301979 1.3
Jacques-Louis Lions 271954 1.3Angenommen es sei
a= Pierre-Louis Lions 301979 1.3,
b= Jacques-Louis Lions 271954 1.3
Weiß C++, dass a.Nachname vom Typ string ist?Dann würde mein '<' für Student ja wie folgt ausschauen:
// Vergleichsoperator "<" bool operator< ( const Student& a, const Student& b) { if (a.Nachname == b.Nachname){ //gl. Nachname if(a.Vorname < b.Vorname){ return true; } return false; } if (a.Nachname < b.Nachname){ return true; } return false; }EDIT: Oder kann ich durch
string a.Nachname, b.Nachname;die einzelnen Einträge jeweils dem Typ string zuweisen?
-
Student definiert Nachname. Da musst du nichts mehr machen.
-
Die Variable "Nachname" hat doch schon einen Datentyp, schau mal in die Klasse "Student"
-
Stimmt,
Habe es nun in einer anderen Datei gesehen.struct Student { std::string Vorname, Nachname; int MatNr; double Note; };D.h. dass ich Nachnamen also mit '<' usw. vergleichen kann.
Edit: Ich füge mal die anderen Operatoren hinzu (bin gerade dabei)
// Vergleichsoperatoren "==" bzw. "!=" bool operator== ( const Student& a, const Student& b) { if(a < b){ return false; } if(a > b){ //muss noch implementiert werden return false; } return true; } bool operator!= ( const Student& a, const Student& b) { return !(a == b); //auf == zurückgreifen, und das Ergebnis negieren } bool operator> ( const Student& a, const Student& b) //Mein Versuch für '>' { if (a.Nachname == b.Nachname){ //gl. Nachname if(a.Vorname > b.Vorname){ return true; } return false; } if (a.Nachname > b.Nachname){ return true; } return false; }Wie schaut es soweit aus?

-
Wenn nicht a>b und nicht b>a gilt, gilt dann nach deiner Implementierung a==b? Immer?
-
Hab's heute fertig gestellt.
Danke an alle