class



  • pava schrieb:

    So ich glaube es gibt einen Missverständniss was das hier betrifft:
    vorname [30] = '0';
    das hat der professor so verlangt (denke ich zumindest).

    Bestimmt nicht.

    pava schrieb:

    so hier ist die aufgabe damit keine missverständnise mehr vorkommen 😉
    [...]

    Ich sehe da keine Bemerkung zur Art der Initialisierung. Aber nachdem, was er verlangt, kann die Klasse Teilnehmer kein Aggregat-Typ mehr sein. Ein Array davon müsste sich aber immernoch ähnlich initialisieren lassen:

    int main() {
      Teilnehmer liste[16] = {
        Teilnemher("Hinz", "Kunz", 1234),
        Teilnemher("Dings", "Bums", 4321)
      };
    }
    

    pava schrieb:

    Was char vorname[30] und char nachname[30] betrifft, ich glaube mann muss definieren wie groß der String ist oder irre ich mich?

    Ja, is ja auch richtig. Aber das [30] gehört nicht zum Namen des Arrays dazu. Ich weiß nicht, warum Du glaubst, dass das [30] überall sonst noch dazugeschrieben werden muss.

    pava schrieb:

    eine kleine Frage hätte ich noch, warum muss ich einen Zeiger benutzen?

    Wenn Du einen Konstruktor schreiben willst, der Deine Arrays befüllt, müsstest Du dich mit Funktionen wie sie im Header <cstring> zu finden sind, rumärgern. Diese Funktionen arbeiten mit Zeigern. Das sind Funktionen, die zB die Länge von C-Strings berechnen (Nullterminierung suchen), einen C-String kopieren, etc etc etc. Alles Käse eigentlich, wenn Du nicht std::string benutzen darfst. Käse, weil es damit relativ einfach wird, sich in den Fuß zu schießen.

    Ich rate Dir, das, was der Prof erzählt, kritisch zu betrachten und in dem einen oder anderen guten Lehrbuch nachzuschlagen. Es mag nur sein didaktischer Plan sein, dass die Studenten sich mit C-Strings rumärgern sollen, bevor sie std::string kennenlernen und dann die Vorzüge richtig zu schätzen wissen. Es kann aber auch sein, dass der Prof von C++ nicht ganz so viel Ahnung hat, und Euch in Wirklichkeit "C mit Klassen" beibringt, ohne zu erwähnen, dass man sich mit Klassen (und eigenen Kopierkonstruktoren, Destruktoren, Zuweisungsoperatoren, überladenen Operatoren) ganz nette und leicht benutzbare eigene Typen bauen kann (wie zB std::string), auf die man aufbauen kann. Das Stichwort hier ist Abstraktion und Kapselung. Sorry, ich habe keine Lust, mir jedes Mal Gedanken zu machen, ob mein char-Array auch groß genug ist, und wie ich am besten Zeichenketten ohne Pufferüberläufe kopiere. Der eingefleischte C-Programmierer mag das anders sehen, doch auch in Projekten von C++-Hassern findet man Abstraktionsansätze für Zeichenketten, die auf so etwas ähnliches wie std::strig hinauslaufen -- nur dass man immer noch recht viel bei dem aufpassen muss, was man da tut; denn es gibt ja keine Kopierkonstruktoren, Destruktoren und überladene Zuweisungsoperatoren in C.



  • vielen dank an alle die mir geholfen haben 👍 , ich bin jetzt dank eure hilfe einbischen schlauer geworden, und weiss teilweise was für Fehler ich gemacht habe. Den Rest muss ich wie ihr das gesagt habt in meinem Buch noch lesen. Ich habe das Buch go to c++. ist das Buch ok? ich finde manchmal könnten ein paar mehr Beispiele nichts schaden.
    ach ja noch etwas, wäre es denn richtig so ?

    char vorname [0] = '0';
    


  • pava schrieb:

    vielen dank an alle die mir geholfen haben 👍 , ich bin jetzt dank eure hilfe einbischen schlauer geworden, und weiss teilweise was für Fehler ich gemacht habe. Den Rest muss ich wie ihr das gesagt habt in meinem Buch noch lesen. Ich habe das Buch go to c++. ist das Buch ok? ich finde manchmal könnten ein paar mehr Beispiele nichts schaden.
    ach ja noch etwas, wäre es denn richtig so ?

    char vorname [0] = '0';
    

    Wenn du aus dem String einen Leerstring machen willst, muss es so aussehen:

    char vorname [0] = 0;
    

    Das Stringende wird von einer binären Null signalisiert, nicht von dem Zeichen '0' (dann dürfte in deinen Strings ja nie '0' vorkommen, was dich leicht einschränken würde 😉 ).



  • pava schrieb:

    Den Rest muss ich wie ihr das gesagt habt in meinem Buch noch lesen. Ich habe das Buch go to c++. ist das Buch ok?

    Das kenne ich nicht. Es klingt vom Titel her aber nicht so vielversprechend.

    pava schrieb:

    ich finde manchmal könnten ein paar mehr Beispiele nichts schaden.
    ach ja noch etwas, wäre es denn richtig so ?

    char vorname [0] = '0';
    

    Nein. Das sollte gar nicht kompilieren; denn Du definierst hier ein Array mit 0 Elementen. Und mit "definieren" meinte ich das, was vor dem Gleich steht. Das ab dem Gleich ist die Initialisierung, die auch noch falsch gewesen wäre.

    Beispiel, welches Du sehen willst, aber wegen dem char-Array eigentlich etwas frickelig ist:

    #include <iostream>
    #include <cstring>
    
    const int name_feld_laenge = 30;
    
    class person
    {
      char name_[name_feld_laenge];
    public:
      person() { name_[0] = '\0'; }
      explicit person(const char* zeiger);
      const char* name() const { return &name_[0]; }
    };
    
    person::person(const char* zeiger)
    {
      std::strncpy(&name_[0],zeiger,name_feld_laenge);
      // strncpy garantiert aber keine Nullterminierung im Ziel
      // Wir müssen daher Hand anlegen:
      name_[name_feld_laenge-1] = '\0';
    }
    
    int main() {
      person liste[3] = {
        person("Heinz ist nett und dieser String ist zu lang"),
        person("Uwe")
      };
      std::cout << liste[0].name() << '\n';
      std::cout << liste[1].name() << '\n';
    }
    

    wobei es dies hier eigentlich auch getan hätte:

    #include <iostream>
    #include <string>
    
    struct person
    {
      std::string name;
    };
    
    int main() {
      person liste[3] = {
        {"Heinz ist nett und dieser String ist nicht zu lang"},
        {"Uwe"}
      };
      std::cout << liste[0].name << '\n';
      std::cout << liste[1].name << '\n';
    }
    

    Nur das will Dein Prof nicht sehen, weil er entweder denkt, es sei besser C vor C++ zu lernen oder weil er nicht weiß, wie "schönes" C++ aussehen kann.

    Die Sachen aus der Standardbibliothek (std::string, std::strncpy, etc) kann man zB hier nachgucken.



  • so dank eure hilfe habe ich mein code jetzt einbischen verbessert, ich konnte leider nicht alles umsetzen bzw ändern was ihr mir empfohlen habt zb mit [30] muss weg usw.. weil dann bekam ich fehlermeldungen.
    so kann man das Programm fehlerfrei kompilieren, aber ich habe ein Problem mit der Ausgabe.
    PS: Schauen Sie die main funktion bitte an da habe ich das problem.

    #include <iostream>
    #include <cstring>
    using namespace std;
    
    class teilnehmer
    {
    private :
        char vorname [30] ;
        char nachname [30];
        int matrikelnummer;
    public:
        teilnehmer ();
        teilnehmer (char v[30], int m, char n[30]);
        void print ();
    };
    
    teilnehmer :: teilnehmer ()
    {
    vorname [0] = 0;
    nachname [0] = '-';
    int matrikelnummer = 0;
    }
    
    teilnehmer :: teilnehmer(char v [30], int m, char n[30])
    {
    vorname [30] = v [30];
    matrikelnummer = m;
    nachname [30] = n [30];
    
    }
    
    void teilnehmer :: print ()
    {
    
        if (nachname [0]  != '-')
        {
            cout << "Der Nachname ist : " << nachname  << endl;
        }
    }
    
    int main ()
    {
    	teilnehmer tabelle[16] = {
        teilnehmer  ("Kevin", 123456, "Mueller"),
    
        teilnehmer  ("Franz", 112233, "Schuhmacher"),
    
        teilnehmer  ("Lisa", 102356  , "Fritz"),
    
        teilnehmer  ("Manfred", 258963, "Schmitt"),
    	};
    int i;
    for (i=0 ; i<16 ; i++)
    {
    	/*das Programm kann man Fehlerfrei kompilieren wenn 
         man die cout hier unten nicht benutz, aber ich brauche 
    	 die ausgabe, kann mir jemand bitte zeigen wie die ausgabe richtig wäre?*/
    	cout << tabelle [i].vorname << endl;
    	cout << tabelle[i].matrikelnummer << endl;
    }
        return 0;
    }
    

  • Mod

    Du kannst nicht einfach auf die privaten Attribute einer Klasse zugreifen. Private ist ja gerade genau dafür da! Du musst irgendeine Schnittstelle im public-Bereich deiner Teilnehmerklasse definieren über die du die gewünschten Ausgaben machen kannst. Die übliche Vorgehensweise wäre die Überladung des Operators<<. Das ist aber nicht unbedingt etwas für deinen Kenntnisstand. Die billige Alternative wäre so etwas wie deine print-Funktion, aber stattdessen mit den von dir gewünschten Ausgaben. Oder noch billiger so etwas wie get_matrikelnummer(), dass dann einfach die Matrikelnummer zurückgibt.



  • Da sind noch immer viele Macken drin, die ich beim ersten Mal schon kritisiert habe. Du solltest das, was gesagt wurde, ernst nehmen.

    pava schrieb:

    teilnehmer (char v[30], int m, char n[30]);
    

    müsste tatsächlich heißen:

    teilnehmer (const char v[30], int m, const char n[30]);
    

    wobei die 30 eigentlich überflüssig ist. Man könnte auch const char[] dafür schreiben -- kommt auf dasselbe raus. v und n sind nuneinmal Zeiger hier und keine Arrays -- wegen der angesprochenen Typtransformation.

    pava schrieb:

    void print ();
    

    Hier fehlt ein const am Ende. Sollte so aussehen:

    void print () const;
    

    (Die Funktion print muss/will den Zustand des Objekts nicht ändern.)

    pava schrieb:

    teilnehmer :: teilnehmer(char v [30], int m, char n[30])
    {
    vorname [30] = v [30];
    matrikelnummer = m;
    nachname [30] = n [30];
    }
    

    Man hat Dir schon erklärt, dass das hier sinnfrei ist, was Du machst. Ich habe Dir sogar schon gezeigt, wie man die C-Strings hier richtig kopieren würde. Das [30] hier ist immer noch Nonsense. Klar, es lässt Dich Dein Programm kompilieren, aber es ergibt keinen Sinn. Es macht nicht das, was Du willst. Du willst eine Kette von Zeichen kopieren, maximal 30 (einschließlich Nullterminierung). Was Du machst, ist das 31. Zeichen kopieren, welches im Falle von vorname und nachname nicht existiert, weil Du ja nur 30 Zeichen hast und welches im Falle von v und n auch nicht existieren muss. Du popelst also in einem Speicher rum, der Dir nicht gehört und von dem Du nicht weißt, dass es ihn überhaupt gibt. --> undefiniertes Verhalten

    pava schrieb:

    void teilnehmer :: print ()
    

    hier kommt auch noch ein const an's Ende.

    pava schrieb:

    for (i=0 ; i<16 ; i++)
    {
        /* das Programm kann man Fehlerfrei kompilieren wenn 
           man die cout hier unten nicht benutz, aber ich brauche 
           die ausgabe, kann mir jemand bitte zeigen wie die ausgabe
           richtig wäre? */
        cout << tabelle .vorname << endl;
        cout << tabelle[i].matrikelnummer << endl;
    }
    

    Dass man es fehlerfrei kompilieren kann, heißt nicht, dass der Rest in Ordnung ist. Natürlich kannst Du auf [i]private* Elemente nicht ohne weiteres zugreifen. Das ist ja der Witz von private. Wozu hast Du die print-Funktion? Außerdem solltest Du den Konstanten einen Namen geben, so dass Du sie ändern kannst, indem Du Dein Programm nur an einer Stelle ändern musst.

    const int max_teiln = 16; // <-- eine Stelle. Diese 16 taucht sonst
                              // nirgens mehr auf, nur der Name max_teiln
    teilnehmer tabelle[max_teiln] = {
       u.s.w.
    };
    for (int i=0; i<max_teiln; ++i) {
       tabelle[i].print();
    }
    


  • hallo, danke nochmal für alle die mir geantwortet haben.

    @ Krümelkacker:
    sorry ich wollte nicht das es so rüber kommt. Natürlich habe ich eure Ratschläge ernst genommen, aber ich habe mich halt gefreut als ich das programm Fehlerfrei kompilierte, aber jetzt weiss ich dass das nicht viel heisst.

    der code musste also so aussehen, wenn ich dich dieses mal richtig verstanden habe:

    teilnehmer :: teilnehmer(const char v [], int m, const char n[])
    {
    vorname [0]  = v [0]  ;
    matrikelnummer = m;
    nachname [0] = n [0] ;
    

    somit greife ich jetzt auf das erste Element zu. richtig?

    Gruß pava.



  • pava schrieb:

    teilnehmer :: teilnehmer(const char v [], int m, const char n[])
    {
    vorname [0]  = v [0]  ;
    matrikelnummer = m;
    nachname [0] = n [0] ;
    

    somit greife ich jetzt auf das erste Element zu. richtig?

    Genau. Und dahinter steht immer noch Müll drinnen...
    Ein Array besteht nämlich meistens aus mehr als nur einem Element und du willst doch sicherlich alle Elemente kopieren. Und auch dazu hat dir krümelkacker schon die Lösung präsentiert: std::strncpy.



  • hallo,
    nach kurzer Besprechung mit dem Professor ist es endlich soweit, ich habe es geschafft, und mein Programm sieht jetzt so aus :(Endphase) 😉

    #include <iostream> 
    #include <string> 
    using namespace std; 
    
    class teilnehmer 
    { 
    private : 
        string vorname ; 
       string nachname ; 
        int matrikelnummer; 
    public: 
        teilnehmer (); 
        teilnehmer (string v, int m, string n); 
        void print (); 
    }; 
    
    teilnehmer :: teilnehmer () 
    { 
    vorname  = ""; 
    nachname  = "-"; 
    matrikelnummer = 0; 
    } 
    
    teilnehmer :: teilnehmer(string v, int m, string n) 
    { 
    vorname  = v ; 
    matrikelnummer = m; 
    nachname  = n ; 
    
    } 
    
    void teilnehmer :: print () 
    { 
    	if (nachname   != "-") 
        {
    		cout << "Der Vorname : " << vorname << " und die Matrikelnummer ist : "<< matrikelnummer << endl;
    		cout <<	"Der Nachname ist : " << nachname  <<endl;      
        } 
    } 
    
    int main () 
    { 
        teilnehmer tabelle[16] = { 
        teilnehmer  ("Kevin", 123456, "Mueller"), 
    
        teilnehmer  ("Franz", 112233, "Schuhmacher"), 
    
        teilnehmer  ("Lisa", 102356  , "Fritz"), 
    
        teilnehmer  ("Manfred", 258963, "Schmitt"), 
        }; 
    int i; 
    for (i=0 ; i<16 ; i++) 
    { 
        tabelle[i].print();
    }; 
        return 0; 
    }
    

    so ich glaube jetzt gibts nichts mehr zu meckern oder? ausser bei

    const int max_teilnehmer = 16;
    

    danke schön nochmal und bis zum nächsten Programm.

    MfG Pava



  • Da gibts noch zwei Sachen, die mir gerade so aufgefallen sind:

    • Formatierung - Formatier deinen Code anständig! Das ist schreklick zu lesen!
    • Nutze Initialisierungslisten


  • drakon schrieb:

    Da gibts noch zwei Sachen, die mir gerade so aufgefallen sind:

    • Formatierung - Formatier deinen Code anständig! Das ist schreklick zu lesen!
    • Nutze Initialisierungslisten

    Sry ich bin Anfänger, wie meinst du das mit der Formatierung?



  • An gewissen Stellen ist deine Einrückung ziemlich unübersichtlich.

    Wenn ein neuer Block mit { beginnt, rückst du eine Ebene mehr ein, bei } eine weniger. Dadurch sieht der Code schon viel lesbarer aus.



  • pava schrieb:

    Sry ich bin Anfänger, wie meinst du das mit der Formatierung?

    Einrückung, diese auch konsistent durchziehen.
    Die ";" ebenso konsistent setzen.
    Keine unnötigen Leerzeilen und Leerzeichen.
    USW.




Anmelden zum Antworten