maximum im Array finden



  • Da, bidde:

    #include <iostream> 
    #include <vector>
    #include <algorithm> // std::sort
    #include <string> // std::cin>> overload
    #include <conio.h> // ::getch()
    
    struct Name_Product
    {
    	Name_Product::Name_Product(const std::string &newVname, const std::string &newName,
    							   const unsigned int &newProduct):
    		vname(newVname),
    		nname(newName),
    		product(newProduct) { }
    
    	std::string vname, nname;
    	unsigned int product;
    };
    
    class Schueler
    { 
    	public:
    		Schueler();
    		Schueler(const Schueler &schueler);
    		Schueler(const std::string &newVname, const std::string &newNname, 
    				 const unsigned char &newInfo, const unsigned char &newMathe,
    				 const unsigned char &newPhy);
    
    		const bool operator == (const Schueler &schueler) const;
    		const Schueler operator = (const Schueler &schueler) const;
    
    		const unsigned int GetProduct() const;
    
    	public: // Gaaanz gaaanz böse...
    		std::string vname; 
    		std::string nname; 
    		unsigned char info; 
    		unsigned char mathe; 
    		unsigned char phy; 
    }; 
    
    Schueler::Schueler():
    	info(NULL),
    	mathe(NULL),
    	phy(NULL) { }
    
    Schueler::Schueler(const Schueler &schueler):
    	vname(schueler.vname),
    	nname(schueler.nname),
    	info(schueler.info),
    	mathe(schueler.mathe),
    	phy(schueler.phy) { }
    
    Schueler::Schueler(const std::string &newVname, const std::string &newNname, 
    				   const unsigned char &newInfo, const unsigned char &newMathe,
    				   const unsigned char &newPhy):
    	vname(newVname),
    	nname(newNname),
    	info(newInfo),
    	mathe(newMathe),
    	phy(newPhy) { }
    
    const bool Schueler::operator == (const Schueler &schueler) const
    {
    	if((info == schueler.info)
    	 &&(mathe == schueler.mathe)
    	 &&(phy == schueler.phy))
    		return true;
    
    	else
    		return false;
    }
    
    const Schueler Schueler::operator = (const Schueler &schueler) const
    {
    	return ::Schueler(schueler);
    }
    
    const unsigned int Schueler::GetProduct() const
    {
    	return (info + mathe + phy);
    }
    
    const Schueler findedenbesten(std::vector<Schueler> &student) ;
    
    void main() 
    { 
    	std::vector<Schueler> Student;
    	Schueler neuStudent;
    	char result(NULL);
    
    	while(result != 'J')
    	{
    		std::cout<<"Neuen Student anlegen: "<<std::endl;
    		std::cout<<"Vorname: ";
    		std::cin>> neuStudent.vname;
    		std::cout<<"Nachname: ";
    		std::cin>> neuStudent.nname;
    		std::cout<<"Informatiknote (1-6): ";
    		std::cin>> neuStudent.info;
    		std::cout<<"Mathematiknote (1-6): ";
    		std::cin>> neuStudent.mathe;
    		std::cout<<"Phsyiknote (1-6): ";
    		std::cin>> neuStudent.phy;
    
    		Student.push_back(neuStudent);
    
    		std::cout<<"Auswerten? (J/N) ";
    		std::cin>> result;
    
    		if(result == 'J')
    			std::cout<<"========================="<<std::endl;
    	}
    
    	Schueler auswertung(findedenbesten(Student));
    
    	if(auswertung.vname == "undefined")
    		std::cout<<"Die Datenbank konnte nicht ausgewertet werden... "<<std::endl;
    	else
    	{
    		std::cout<< "Der beste Student in info... "<<std::endl; 
    		std::cout<< "...hat den Vorname: " << auswertung.vname <<std::endl; 
    		std::cout<< "...hat den Nachname: " << auswertung.nname <<std::endl; 
    		std::cout<< "...hat eine " << auswertung.info << " in Info!" <<std::endl; 
    		std::cout<< "...hat eine " << auswertung.mathe << " in Mathe!" <<std::endl; 
    		std::cout<< "...hat eine " << auswertung.phy << " in Physik!" <<std::endl; 
    	}
    
    	getch(); // Bitte in die Konsolen FAQ schauen!
    } 
    
    const Schueler findedenbesten(std::vector<Schueler> &student) 
    {
    	std::vector<Schueler>::iterator it(student.begin()), it2(student.begin());
    	std::vector<Name_Product> newStudent;
    	std::vector<unsigned int> products;
    	std::string vname;
    
    	for(; it != student.end(); ++it)
    	{
    		Name_Product nameprod(it->vname, it->nname, it->GetProduct());
    
    		newStudent.push_back(nameprod);
    		products.push_back(it->GetProduct());
    	}
    
    	std::sort(products.begin(), products.end());
    
    	for(std::vector<Name_Product>::iterator itNewStudent(newStudent.begin()); itNewStudent != newStudent.end(); ++itNewStudent)
    	{
    		if(itNewStudent->product == products[0])
    			vname = itNewStudent->vname;
    	}
    
    	if(!vname.empty())
    	{
    		for(; it2 != student.end(); ++it2)
    		{
    			if(it2->vname == vname)
    				return *it2;
    		}
    	}
    
    	return ::Schueler("undefined", "undefined", 0, 0, 0);
    }
    

    Also falls was ist, ich blicke da selber nicht mehr durch 😃



  • boar... wenn du schon ne komplett-lösung postest, teste es doch wenigsten einmal...

    struct Name_Product
    {
        Name_Product::Name_Product(/*...*/
    

    const unsigned int &newProduct

    Schueler::Schueler():
        info(NULL),
        mathe(NULL),
        phy(NULL) { }
    

    NULL ist für Zeiger...

    Schueler::Schueler(const Schueler &schueler):
        vname(schueler.vname),
        nname(schueler.nname),
        info(schueler.info),
        mathe(schueler.mathe),
        phy(schueler.phy) { }
    

    rate mal, was der compiler generiert...

    const bool Schueler::operator == (const Schueler &schueler) const
    {
        if((info == schueler.info)
         &&(mathe == schueler.mathe)
         &&(phy == schueler.phy))
            return true;
    
        else
            return false;
    }
    

    1. const bool als rückgabetyp Oo
    2. gleiche noten == gleicher schüler?! OO
    3. if(true) return true; else return false;

    const Schueler Schueler::operator = (const Schueler &schueler) const
    {
        return ::Schueler(schueler);
    }
    

    genau das macht op=... nicht!

    const unsigned int Schueler::GetProduct() const
    {
        return (info + mathe + phy);
    }
    

    1. const unsigned int? schon wieder so was sinnloses...
    2. wieso member fkt?

    void main()
    

    aha?!

    char result(NULL);
    schon wieder fail...

    [....]

    return ::Schueler("undefined", "undefined", 0, 0, 0);
    aha? na, wo ist hier(kein Namespace weit und breit; und du hast davor nie :: mitgeschrieben und so weiter) der Unterschied zwischen Schueler und ::Schueler ?

    Man müsste noch viel mehr bemängeln, damit der TO sich nicht irgend ne dumme Idee von dir abguckt und denkt, es wäre so richtig...
    Vll hat irgendwer noch Lust, den Rest noch zu bemängeln oder was besseres zu posten^^

    bb



  • unskilled schrieb:

    rate mal, was der compiler generiert...

    Also bei mir generiert er alles richtig.

    unskilled schrieb:

    1. const bool als rückgabetyp Oo

    Ja? Klär mich bitte auf ⚠

    unskilled schrieb:

    2. gleiche noten == gleicher schüler?! OO

    In diesem Falle ja. Es geht um die Noten.

    unskilled schrieb:

    genau das macht op=... nicht!

    Wie auch vorhin: Klär mich auf.

    unskilled schrieb:

    1. const unsigned int? schon wieder so was sinnloses...
    2. wieso member fkt?

    1. Warum?
    2. Warum nicht?

    void main()
    

    Habe ich von dem TO übernommen und übersehen.


  • Administrator

    Kóyaánasqatsi schrieb:

    unskilled schrieb:

    rate mal, was der compiler generiert...

    Also bei mir generiert er alles richtig.

    Unskilled meinte auch den Default-Kopierkonstruktor. Der macht nämlich genau das, was du da selber getippt hast. Also hast du völlig unnötigen Code geschrieben.

    Kóyaánasqatsi schrieb:

    unskilled schrieb:

    1. const bool als rückgabetyp Oo

    Ja? Klär mich bitte auf ⚠

    Kóyaánasqatsi schrieb:

    unskilled schrieb:

    1. const unsigned int? schon wieder so was sinnloses...

    1. Warum?

    Diese Rückgabewerte sind sowieso L-Values, wodurch du keine Zuweisung machen kannst. Bei Built-In Typen ist das const unnötig, nur bei eigenen Klassen kann es etwas bringen.

    Kóyaánasqatsi schrieb:

    unskilled schrieb:

    2. gleiche noten == gleicher schüler?! OO

    In diesem Falle ja. Es geht um die Noten.

    Das ist aber äusserst schlecht für das Verständnis. Wenn man die Operatoren verwendet, dann sollte man ganz logische Beziehungen wählen. Ansonsten nimm lieber eine Funktion: int compareMarks(Student const& lhs, Student const& rhs) .

    Kóyaánasqatsi schrieb:

    unskilled schrieb:

    genau das macht op=... nicht!

    Wie auch vorhin: Klär mich auf.

    Der Kopierkonstruktor erzeugt ein neues Objekt anhand eines alten. Der operator = erzeugt aber kein neues Objekt. Ich weiss nicht einmal, ob dieser Aufruf standardkonform ist, schliesslich darf man doch nicht einen Konstruktor auf ein bereits konstruiertes Objekt aufrufen, wäre mir zumindest neu. Zudem könntest du es auch einfach dem Kompiler überlassen, der implementiert dir bereits eine solche Funktion.
    (Und so am Rande, dadurch ist dein operator = nicht Exceptionsicher)

    Kóyaánasqatsi schrieb:

    unskilled schrieb:

    2. wieso member fkt?

    2. Warum nicht?

    Lies: Überladung von Operatoren (Teil 1)

    Grüssli



  • Dravere schrieb:

    Kóyaánasqatsi schrieb:

    unskilled schrieb:

    genau das macht op=... nicht!

    Wie auch vorhin: Klär mich auf.

    Der Kopierkonstruktor erzeugt ein neues Objekt anhand eines alten. Der operator = erzeugt aber kein neues Objekt. Ich weiss nicht einmal, ob dieser Aufruf standardkonform ist, schliesslich darf man doch nicht einen Konstruktor auf ein bereits konstruiertes Objekt aufrufen, wäre mir zumindest neu. Zudem könntest du es auch einfach dem Kompiler überlassen, der implementiert dir bereits eine solche Funktion.
    (Und so am Rande, dadurch ist dein operator = nicht Exceptionsicher)

    naja - der aufruf an sich wird schon standard-konform sein - mit dem eigtl objekt passiert ja eigtl gar nichts, es wird einfach nur eine kopie des anderen objekts wiedergegeben...
    das "tolle" ist, dass sein op= also gar nichts mit dem objekt an sicht macht...
    -> Schueler operator= (const Schueler &other) const 😃

    bb



  • @unskilled
    Das verstehe ich nicht. Die Klasseninstanzen werden doch mit dem Objekt initialisiert 😕



  • Kóyaánasqatsi schrieb:

    @unskilled
    Das verstehe ich nicht. Die Klasseninstanzen werden doch mit dem Objekt initialisiert 😕

    in wie fern? wovon redest du?
    vom op=?
    der sieht ja in nem einfachen bsp so aus:

    struct foo
    {
      int a;
    
      foo() : a(0) {}
      foo(int _a) : a(_a) {}
    
      foo(const foo &other) : a(other.a) {}
      foo& operator= (const foo &other) {a = other.a; return *this;}
    };
    

    man sieht schon, dass der copy ctor und assignment op sich extrem ähnlich sind...
    aber das gleiche tun sie eben nicht.
    Wenn du jetzt noch mal an deinen op= denkst:

    foo operator= (const foo &other)
    {
      foo tmp(other);
      return tmp;
    }
    

    macht so ziemlich gar nichts von dem, was ein op= machen sollte - nämlich das objekt verändern (und einen verweis(keine kopie) des veränderten objekts wiedergeben)
    dravere hatte dir den link(artikel zur op-überladung) schon gegeben, der dir vrmtl die erleuchtung bringt 😉

    und so macht man es dann, wenn man es toll machen möchte ;o)

    struct foo
    {
      int a;
    
      explicit foo(int _a = int()) : a(_a) {}
    
      foo(const foo &other) : a(other.a) {}
      void swap(foo &other) {using std::swap; swap(a, other.a);}
      foo& operator= (const foo &other) {foo to_swap(other); swap(other); return *this}
    };
    

    bb



  • unskilled schrieb:

    foo& operator= (const foo &other) {foo to_swap(other); swap(other); return *this;}
    

    Besser

    foo& operator= (foo other) {swap(other); return *this;}
    

    nehmen und auf copy elision hoffen. 🙂



  • Ryuzaki schrieb:

    unskilled schrieb:

    foo& operator= (const foo &other) {foo to_swap(other); swap(other); return *this;}
    

    Besser

    foo& operator= (foo other) {swap(other); return *this;}
    

    nehmen und auf copy elision hoffen. 🙂

    ja - das thema hatten wir glaub ich ab und an schon mal - und es kam jedes ma das selbe raus: unnötiges impl.-detail und das hat nix im header zu suchen - aber bedingt durch die andere signatur ist es eben doch schon dort zu finden...
    ich werds weiter mit const reference machen und nur, wenn ich iwann merk, dass ich wegen des op= performace-probleme hab, werd ich es ändern...

    bb



  • unskilled schrieb:

    unnötiges impl.-detail und das hat nix im header zu suchen - aber bedingt durch die andere signatur ist es eben doch schon dort zu finden...
    ich werds weiter mit const reference machen und nur, wenn ich iwann merk, dass ich wegen des op= performace-probleme hab, werd ich es ändern...

    Das verstehe ich jetzt überhaupt nicht. WARUM bleibst Du bei const& ? Kannst Du mir ein Beispiel programmieren, wo const& einen Vorteil hat?



  • volkard schrieb:

    unskilled schrieb:

    unnötiges impl.-detail und das hat nix im header zu suchen - aber bedingt durch die andere signatur ist es eben doch schon dort zu finden...
    ich werds weiter mit const reference machen und nur, wenn ich iwann merk, dass ich wegen des op= performace-probleme hab, werd ich es ändern...

    Das verstehe ich jetzt überhaupt nicht. WARUM bleibst Du bei const& ? Kannst Du mir ein Beispiel programmieren, wo const& einen Vorteil hat?

    immer dann, wenn ich die exceptionsicherheit noch anders erhalten kann, außer durch copy&swap bzw sich copy&swap einfach nicht lohnt...

    struct X
    {
    private:
      int id;
      int count;
      std::string beschreibung;
    public:
      X(int id, int count): id(id), count(count), beschreibung(db_lookup(id)) {}
      X(const X& x) : id(x.id), count(x.count), beschreibung(x.beschreibung) {}
    
      X& operator= (const X &x)
      {
        beschreibung = x.beschreibung;
        id = x.id;
        count = x.id;
        return *this;
      }
    };
    

    ist noch immer exceptionsafe und hat nur 2 int-zuweisungen - im ggnsatz zu 2 mal nem dreieckstausch (warum hat tausch eigtl keinen plural? >.<)

    wenn ich also erst op= durch das copy&swap idiom erledigt hab und mir dann auffällt, dass dort mein flaschenhals ist, müsste ich nur mein *.cpp file ändern - ihr müsstet zusätzlich noch den header ändern...
    da kann man sicherlich auch bsp konstruieren, wo es sich richtig lohnt...

    steht eigtl iwo, dass der compiler die copy elision so nicht mehr durchführen darf oder sind die compiler (bisher) nur zu dumm dazu?

    bb


Anmelden zum Antworten