Übungsbsp. einer Telefonliste zeigt Einträge nicht an



  • Hallo an alle!

    Ich beschäftige mich mit C++ und arbeite gerade das Buch "C++ lernen und professionell anwenden" durch. In Kapitel 16 Übungsaufgabe 5 (Falls jemand das Buch zur Hand haben sollte) wird ein Programm zur Erstellung und Pflege einer Telefonliste erstellt. Dieses Programm leuchtet mir auch ein, nur kann ich keine Einträge anzeigen lassen, obwohl standardmäßig ein Eintrag ("Peter Lustig") vorhanden sein sollte! Der Compiler findet keine Fehler und ich habe schon mehrfach die gegebene Lösung mit meiner auf Fehler hin abgeglichen und nichts gefunden. Ich kann neue Einträge verfassen die anscheinend auch gespeichert werden (In der Ausgabe werden die reservierten Zeilen angelegt, jedoch nicht mit Einträgen gefüllt!) Da ich schon lange an diesem Problem sitze und nicht mehr weiter weiß, wollte ich Euch fragen ob ihr da mal drüber schauen könnt. Das Programm entspricht der Lösung, also dürfte eigentlcih nichts mehr großartig hinzuzufügen sein. Ich schätze es ist irgendein Fehler in der print()-Methode!
    Hier mal der Quellcode der Header-Datei integriert in das Anwenderprogramm:

    //--------------------------------------------
    // telList.h
    // Eine Klasse telList zur Darstellung einer Liste mit Telefonnummern und Namen
    //--------------------------------------------
    
    #ifndef _TelList_
    #define _TelList_
    
    #include<string>
    using namespace std;
    #define PSEUDO -1                             // Preudoposition
    #define MAX 100                               // Maximalanzahl der Elemente
    
    // Typ eines Listen-Elements
    struct Element { string name, telNr; };        // öffentliche Schnittstelle struct des neuen Types "Element", was aus zwei strings
                                                   // besteht: name und telNr
    
    class TelList
    {
          private:
                  Element v[MAX];                  // Vektor mit Maximaler Anzahl an Elementen
                  int count; 
    
          public:
                 TelList() { count = 0; }           // Default-Konstruktor der den Zähler count auf 0 setzt
                 int getCount()const { return count; }
                 Element *retrieve( int i )         // Methode retrieve() liefert zu einem Index einen Zeiger auf das entsprechende Element
                 {
                         return (i >= 0 && i < count)? &v[i] : NULL;  // && -> UND Operator
                         /* obere Zeile entspricht: if( i >=0 && i < count)
                                                    {
                                                        return &v[i]
                                                    }
                                                    else
                                                    {
                                                        return NULL        (Nullzeiger zurückgeben)
                                                    }*/
                 }
                 bool append( const Element& el )
                 {
                      return append (el.name, el.telNr );      // Neuen Eintrag in List hinzufügen
                 }
                 bool append( const string& name,
                              const string& telNr );
                 bool erase( const string& name );
                 int search( const string& name)const;         // Read-Only-Methode, es kann nur lesend darauf zugergriffen werden!
                 void print()const;
                 int print( const string& name) const;
                 int getNewEntries();
    };
    #endif       //_TelList_
    
    // Implementierung der telList-Methoden
    //-----------------------------------------
    #include "telList.h"
    #include<iostream>
    #include<iomanip>
    using namespace std;
    
    bool TelList::append( const string& name,   // Anhängen 
                          const string& telNr) 
    {
       if( count < MAX                  // noch Platz im Vektor
           && name.length() > 1         // und mind. zwei Zeichen langer Name
           && search(name) == PSEUDO)   // und noch nicht vorhanden
           {
              v[count].name == name;
              v[count].telNr == telNr;
              ++count;
              return true;
           }
           return false;
    }
    
    bool TelList::erase( const string& key)    // Löschen
    {
         int i = search(key);
         if( i != PSEUDO )
         {                                     
             v[i] = v[count -1];               // letztes Element in Position i kopieren
             --count;
             return true;
         }
         return false;
    }
    
    int TelList::search( const string& key )const // suchfunktion (Nur read-only-implementiert!)
    {
        for( int i = 0; i < count; i++)
        if( v[i].name == key )
            return i;        // gefunden
        return PSEUDO;       // nicht gefunden
    }
    
    // Hilfsfunktion für die Ausgabe:
    inline void tabHeader()          // Überschrift der Tabelle
    {
           cout << "\n  Name                        Telefon-Nr\n"
                   "--------------------------------------------"
                << endl;
    }
    inline void printline( const Element& el)
    {
           cout << left << setw(30) << el.name << el.telNr << endl;
    }
    
    void TelList::print() const     // Alle Einträge ausgeben
    {
         if( count == 0)
             cout << "\nDie Telefonliste ist leer!" << endl;
         else
         {
             tabHeader();
             for( int i = 0; i < count; ++i)
                  printline( v[i]);
         }
    }
    
    int TelList::print( const string& name) const      // Alle Einträge die mit Name beginnen
    {
        int matches = 0, len = name.length();
    
        for( int i = 0; i < count; ++i)
        {
             if( v[i].name.compare(0, len, name) == 0) // Der Methode werden nur der anfang eines Namens übergeben, alle passenden Einträge
                                                       // werden dann danach angezeigt!
             {
               if( matches == 0) tabHeader();          // Überschrift vor erster Ausgabe         
               ++matches;
               printline( v[i]);
             }
        }
        if( matches == 0)
            cout << "Kein passender Eintrag gefunden!" << endl;
        return matches;
    }
    
    int TelList::getNewEntries()    // Neue Einträge im Dialog einlesen
    {
        int inputCount = 0;
        cout << "\nNeuen Namen und Telefonnummern eingeben:"
                "\nEnde mit leerer Eingabe!"
             << endl;
        Element el;
        while( true)
        {
           cout << "\nNeuer Nachname, Vorname:  ";
           cin.sync();
           getline( cin, el.name);
           if( el.name.empty())
               break;
           cout << "\nTelefonnummer:  ";
           cin.sync();
           getline( cin, el.telNr);
    
           if( !append( el))
           {
               cout << "Name wurde nicht eingef\x81 \bgt!" << endl;
               if( count == MAX)
               {
                   cout << "Die Tabelle ist voll!" << endl;
                   break;
               }
               if( search( el.name) != PSEUDO)
                   cout << "Name schon vorhanden!" << endl;
           }
           else
           {
               ++inputCount;
               cout << "Neues Element wurde eingef\x81 \bgt!" << endl;
           }
        }
        return inputCount;
    }
    
    // -----------------------------------
    // TelList_.cpp
    // Mit der Klasse TelList eine Telefonliste verwalten.
    // -----------------------------------
    #include "TelList.h"
    #include<iostream>
    #include<string>
    #include<cctype>
    using namespace std;
    
    inline void cls()
    {
           cout << "\n";           // Nur New-Lines ausgeben, falls ANSI-Steuerzeichen nicht verfügbar.
    }
    
    inline void weiter()
    {
           cout << "\n\nWeiter mit der Return-Taste!  ";
           cin.sync();
           cin.clear();                   // Nur neue Eingabe
           while( cin.get() !='\n')
                  ;
    }
    
    int menu();    // Ein Kommando einlesen
    
    char header[] =
    "\n\n             *****  Telefonliste  *****\n\n";
    
    TelList myFriends;       // Eine Telefonliste
    
    int main()
    {
        int aktion = 0;      // Kommando
        string name;         // zum Einlesen eines Namens
    
        myFriends.append("Lustig, Peter", "0203-1234567");
    
        while( aktion != 'B')
        {
           aktion = menu();
           cls();
           cout << header << endl;
    
           switch( aktion)
           {
              case 'A':                    // Alles Anzeigen
                        myFriends.print();
                        weiter();
                        break;
              case 'F':                    // Suchen
                        cout << 
                           "\n--- Telefonnummer finden. ---\n "
                           "\nDen Anfang eines Namens eingeben:  ";
                           getline( cin, name);
                           if( !name.empty())
                           {
                               myFriends.print( name);
                               weiter();
                           }
                           break;
              case 'H':                 // Hinzufügen
                        myFriends.getNewEntries();
                        break;
              case 'L':                 // Löschen
                        cout <<
                             "\n--- Telefoneintrag l\x94 \bschen. ---\n "
                             "\nDen vollst\x84 \bndigen Namen eingeben: ";
                             getline( cin, name);
                             if( !name.empty())
                             {
                                 if( !myFriends.erase( name))
                                      cout << name << " nicht gefunden!"
                                           << endl;
                                 else
                                     cout << "Eintrag für " << name
                                          << " gel\x94 \bscht! " << endl;
                                 weiter();
                             }
                             break;
              case 'B':                   // Beenden
                        cls();
                        break;
           }
        }  // Ende while!
        return 0;
    }
    
    int menu()
    {
        static char menuStr[] =
        "\n\n             A = Anzeigen aller Eintr\x84 \bge"
        "\n\n             F = Finden einer Telefonnummer"
        "\n\n             H = Hinzuf\x81 \bgen eines Eintrages"
        "\n\n             L = L\x94 \bschen eines Eintrages"
        "\n\n             B = Beenden des Programms"
        "\n\n Ihre Wahl:  ";
    
        cls();
        cout << header << menuStr;
    
        char wahl;
        cin.sync();
        cin.clear();   // Nur neue Eingabe
        if( !cin.get(wahl))
            wahl = 'B';
        else
            wahl = toupper(wahl);
    
            cin.sync();          // Eingabepuffer löschen
            return wahl;
    }
    

    Ich hoffe ich habe die Forenregeln eingehalten und danke Euch im Voraus schonmal für eure Mühen!

    Gruß
    Fritz



  • Die append Funktion müsste wenn dann so aussehen:

    bool TelList::append( const string& name,   // Anhängen
                          const string& telNr)
    {
       if( count < MAX                  // noch Platz im Vektor
           && name.length() > 1         // und mind. zwei Zeichen langer Name
           && search(name) == PSEUDO)   // und noch nicht vorhanden
           {
              v[count].name = name;
              v[count].telNr = telNr;
              ++count;
              return true;
           }
           return false;
    }
    


  • Tatsächlich! Das war der Fehler! Vielen Dank! Zumal es in der Lösung auch wirklich nur mit einfachem Gleichheitszeichen steht! Das hab ich echt übersehen!
    Damit ist dieser Beitrag geschlossen...

    Danke nochmal!

    Gruß
    Fritz



  • Noch ein paar Anmerkungen:
    1. Benutze niemals using namespace in einer Header.
    2. Benutze für Konstanten const, und nicht define.
    3. Da die Anzahl der Einträge dynamisch ist, benutze std::vector und kein rohes Array.
    4. Benutze eine Initialisierungsliste.
    5. Wieso ist das Array in der main static?
    6. Die Deklaration einer Funktion vor der main und deren Implementierung nach der main, macht man normal auch nicht, denn was bringt dir das? Definiere die Funktion einfach vor der main.
    7. cin.sync() ist eine schlechte Idee, da es nicht auf jedem System funktioniert. Darum benutzt man immer std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n')



  • Danke für die Anmerkungen! Ich arbeite das Buch chronologisch durch! Ich werd mir merken habs erst mal nur so gemacht wie dies da beschrieben haben!
    Danle vielmals nocheinmal!



  • Fritz83 schrieb:

    Danke für die Anmerkungen! Ich arbeite das Buch chronologisch durch! Ich werd mir merken habs erst mal nur so gemacht wie dies da beschrieben haben!
    Danle vielmals nocheinmal!

    Noch etwas: Ich kenne dieses Buch zwar nicht, aber define und einige Rezensionen lassen darauf schließen, dass das Buch nur bedingt gut ist.



  • Naja, dies fängt halt beim Urschleim an!
    Kennst du bessere?



  • 1. bruce eckel thinking in c++
    2. der c++ programmierer von ulrich breymann
    3. Einführung in die Programmierung mit C++ von Bjarne Stroustrup

    Alle auf deutsch ehhältich und ersteres sogar kostenlos.



  • out schrieb:

    1. bruce eckel thinking in c++
    2. der c++ programmierer von ulrich breymann
    3. Einführung in die Programmierung mit C++ von Bjarne Stroustrup

    Alle auf deutsch ehhältich und ersteres sogar kostenlos.

    Ups. ich meinte: 3. Die C++-Programmiersprache von Bjarne Stroustrup...



  • Vielen Dank! Musste gestern erst mal auf Arbeit!
    Ich werd mir die mal zur Gemüte führen!

    Gruß
    Fritz



  • out schrieb:

    6. Die Deklaration einer Funktion vor der main und deren Implementierung nach der main, macht man normal auch nicht, denn was bringt dir das? Definiere die Funktion einfach vor der main.

    Sehe ich nicht so. Ich mach das z.B. gerne, weil es mir lieber ist, wenn die main gleich am Anfang steht und ich gleich sehe, wie das Programm startet. Dazu gab es, glaube ich, vor anderthalb Jahren eine Diskussion, die gezeigt hat, dass das schon nicht wenige so machen.


Anmelden zum Antworten