Programm Absturz mit string.h



  • Hallo,
    ich habe folgendes Problem.
    Wenn ich mein kleines Programm aufrufe, Daten eingebe und diese wieder ausgeben lasse stürzt mir das Programm ab.

    Meldung: Zugriffsverletzung bei Adresse xxxxxx, ..... Prozess wurde angehalten.

    Kann mir vielleicht jemand sagen woran das Problem liegt?

    Danke schonmal im Vorraus 🙂

    Hier der Code:

    #include <iostream.h>
    #include <string.h>
    
    class Buch {
       private:
          string Autor;
          string Titel;
          string Erscheinungsjahr;
    
       public:
          Buch(string AutorP, string TitelP, string ErscheinungsjahrP) {
             Autor = AutorP;
             Titel = TitelP;
             Erscheinungsjahr = ErscheinungsjahrP;
          };
          ~Buch() {
             //tue nichts
          };
          string druckeDaten() {
             cout<<"Autor: "<<Autor<<endl;
             cout<<"Titel: "<<Titel<<endl;
             cout<<"Erscheinungsjahr: "<<Erscheinungsjahr<<endl;
          };
    };
    
    int main() {
    
       //Deklaration der Eingabe Variablen
       string eingAutor;
       string eingTitel;
       string eingErscheinungsjahr;
    
       //Eingabe des Autors, Titel und Erscheinungsjahr
       cout<<"Geben Sie den Namen des Autors ein: ";
       cin>>eingAutor;
       cout<<"\nGeben Sie den des Buchs ein: ";
       cin>>eingTitel;
       cout<<"\nGeben Sie das Erscheinungsjahr ein: "<<endl;
       cin>>eingErscheinungsjahr;
    
       //erzeuge Objekt auf Heap
       Buch* objektBuch = new Buch(eingAutor, eingTitel, eingErscheinungsjahr);
    
       objektBuch->druckeDaten();
    
       return 0;
    }
    


  • An welcher Stelle stoppt denn der Prozess nach diesem Zugriffsfehler?

    kleiner Tip: Es ist übrigens vorteilhaft, Strings per Referenz weiterzureichen:

    class Buch
    {
    public:
      Buch(const string& nAutor,const string& nTitel,const string& nJahr)
        : Autor(nAutor),Titel(nTitel),Erscheinungsjahr(nJahr) {}
      //...
    };
    

    PS: Und zu einem new gehört auch immer ein delete (auch wenn das vermutlich nicht für den Fehler verantwortlich ist).



  • Der Fehler tritt auf, sobald die Werte ausgegeben werden sollen.

    Wozu benötige ich das const und die zweite Zeile ": Autor(nAutor),Titel(nTitel),Erscheinungsjahr(nJahr)"?

    Nun habe ich das ganze so, jedoch funktionieren tut es nicht. Selber Absturz 😞

    #include <iostream.h>
    #include <string.h>
    
    class Buch {
       private:
          string Autor;
          string Titel;
          string Erscheinungsjahr;
          //static int zaehler;
    
       public:
          Buch(const string& nAutor,const string& nTitel,const string& nJahr)
          : Autor(nAutor),Titel(nTitel),Erscheinungsjahr(nJahr) {
             Autor = nAutor;
             Titel = nTitel;
             Erscheinungsjahr = nJahr;
          }
       /*   Buch(string* AutorP,string* TitelP,string* ErscheinungsjahrP) {
             Autor = *AutorP;
             Titel = *TitelP;
             Erscheinungsjahr = *ErscheinungsjahrP;
          };  */
          ~Buch() {
             //tue nichts
          };
          string druckeDaten() {
             cout<<"Autor: "<<Autor<<endl;
             cout<<"Titel: "<<Titel<<endl;
             cout<<"Erscheinungsjahr: "<<Erscheinungsjahr<<endl;
          };
    };
    
    void main() {
    
       //Deklaration der Eingabe Variablen
       string eingAutor;
       string eingTitel;
       string eingErscheinungsjahr;
    
       //Eingabe des Autors, Titel und Erscheinungsjahr
       cout<<"Geben Sie den Namen des Autors ein: ";
       cin>>eingAutor;
       cout<<"\nGeben Sie den des Buchs ein: ";
       cin>>eingTitel;
       cout<<"\nGeben Sie das Erscheinungsjahr ein: "<<endl;
       cin>>eingErscheinungsjahr;
    
       //erzeuge Objekt auf Heap
       Buch* objektBuch = new Buch(eingAutor, eingTitel, eingErscheinungsjahr);
    
       objektBuch->druckeDaten();
    
       delete objektBuch;
    }
    


  • Lieber so:

    //.h Header sind veraltet, nimm die neuen
    #include <iostream>
    #include <string>
    
    //EDIT: Das hier muss bei den neuen Headern rein, jetzt befindet sich nämlich alles im Namesraum std
    using namespace std;
    
    class Buch {
       private:
          string Autor;
          string Titel;
          string Erscheinungsjahr;
    
       public:
          //Wie CStoll sagte, const Referenz und Elementinitializer
          Buch(const string &AutorP, const string &TitelP, const string &ErscheinungsjahrP) : Autor(AutorP), Titel(TitelP), Erscheinungsjahr(ErscheinungsjahrP) { };
          ~Buch() { };
    
          string holeDaten() const {
             return "\nAutor" + Autor+"\nTitel: " + Titel + "\nErscheinungsjahr: "+Erscheinungsjahr;
          };
    };
    
    int main() {
       //Deklaration der Eingabe Variablen
       string eingAutor;
       string eingTitel;
       string eingErscheinungsjahr;
    
       //Eingabe des Autors, Titel und Erscheinungsjahr
       cout<<"Geben Sie den Namen des Autors ein: ";
       getline(cin, eingAutor);  //Strings liest man mit getline ein
       cout<<"\nGeben Sie den des Buchs ein: ";
       getline(cin, eingTitel);
       cout<<"\nGeben Sie das Erscheinungsjahr ein: "<<endl;
       getline(cin, eingErscheinungsjahr);
    
       //erzeuge Objekt auf Heap
       Buch* objektBuch = new Buch(eingAutor, eingTitel, eingErscheinungsjahr);
    
       cout<<objektBuch->holeDaten();
       delete objektBuch;
    
       return 0;
    }
    


  • erstmal solltest du weg von den Uralt-Headern, richtig sieht der Programmanfang so aus:

    #include<iostream>//iostream.h ist veraltet
    #include<string>//string.h enthält noch nichtmal die string-Klasse, sondern die char*-Verarbeitung von C
    using namespace std;
    

    Zweitens:

    Wozu benötige ich das const und die zweite Zeile ": Autor(nAutor),Titel(nTitel),Erscheinungsjahr(nJahr)"?

    das 'const string&' übernimmt die Parameter per Referenz (deutlich schneller als das kopieren bei Wert-Übergabe) und die zweite Zeile initialisiert die Elemente der Klasse korrekt (damit fällt auch der Rumpf des Konstruktors ("Autor=nAutor;...") weg).

    Drittens: Wenn du 'druckeDaten()' als string-Funktion deklarierst, benötigst du auch eine return-Anweisung - entweder du machst daraus 'void druckeDaten()' oder du nimmst GPC's Version mit holeDaten().



  • Leider bekomme ich nun den Fehler: Versuch, eine Referenz an die Lokale Variable '<temp>' zurückgeben.

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Buch {
       private:
          string Autor;
          string Titel;
          string Erscheinungsjahr;
          //static int zaehler;
    
       public:
          Buch(const string &AutorP, const string &TitelP, const string &ErscheinungsjahrP) : Autor(AutorP), Titel(TitelP), Erscheinungsjahr(ErscheinungsjahrP) { }; 
          ~Buch() { };
    
          const string& druckeDaten() const {
             return "\nAutor" + Autor+"\nTitel: " + Titel + "\nErscheinungsjahr: "+Erscheinungsjahr;
          };
    
       /*
          Buch(const string& nAutor,const string& nTitel,const string& nJahr)
          : Autor(nAutor),Titel(nTitel),Erscheinungsjahr(nJahr) {
             Autor = nAutor;
             Titel = nTitel;
             Erscheinungsjahr = nJahr;
          }
          Buch(string* AutorP,string* TitelP,string* ErscheinungsjahrP) {
             Autor = *AutorP;
             Titel = *TitelP;
             Erscheinungsjahr = *ErscheinungsjahrP;
          };
          ~Buch() {
             //tue nichts
          };
          string druckeDaten() {
             cout<<"Autor: "<<Autor<<endl;
             cout<<"Titel: "<<Titel<<endl;
             cout<<"Erscheinungsjahr: "<<Erscheinungsjahr<<endl;
          };
       */
    };
    
    int main() {
    
       //Deklaration der Eingabe Variablen
       string eingAutor;
       string eingTitel;
       string eingErscheinungsjahr;
    
       //Eingabe des Autors, Titel und Erscheinungsjahr
       cout<<"Geben Sie den Namen des Autors ein: ";
       cin>>eingAutor;
       cout<<"\nGeben Sie den des Buchs ein: ";
       cin>>eingTitel;
       cout<<"\nGeben Sie das Erscheinungsjahr ein: "<<endl;
       cin>>eingErscheinungsjahr;
    
       //erzeuge Objekt auf Heap
       Buch* objektBuch = new Buch(eingAutor, eingTitel, eingErscheinungsjahr);
    
       objektBuch->druckeDaten();
       delete objektBuch;
    
       return 0;
    }
    


  • dE_MaStEr schrieb:

    Leider bekomme ich nun den Fehler: Versuch, eine Referenz an die Lokale Variable '<temp>' zurückgeben.

    Sorry, mein Fehler, das darf natürlich keine Referenz auf ein temporäres Objekt sein.
    Lösung:

    string druckeDaten() const {
             return "\nAutor" + Autor+"\nTitel: " + Titel + "\nErscheinungsjahr: "+Erscheinungsjahr;
          };
    


  • Beim Zurückgeben eines ad-hoc erzeugten Strings (sog. Temporary) musst Du wieder Wertübergabe machen:

    string druckeDaten() const {
        return "\nAutor" + Autor + "\nTitel: " + Titel + "\nErscheinungsjahr: "  + Erscheinungsjahr;
    }
    


  • dE_MaStEr schrieb:

    const string& druckeDaten() const {
             return "\nAutor" + Autor+"\nTitel: " + Titel + "\nErscheinungsjahr: "+Erscheinungsjahr;
    };
    
    int main() {
       objektBuch->druckeDaten();
       delete objektBuch;
    }
    

    *etwas gekürzt* Jetzt hast du wirklich alles durcheinandergebracht. ENTWEDER du druckst im inneren der Funktion, dann wird sie als void deklariert ODER du gibst einen druckreifen String zurück, den du dann im Hauptprogramm druckst. So ein Mischmasch kann nichts werden.

    //a: Drucken in Funktion
    void drucke() const
    {
      cout<<"Buch - Autor:"<<Autor<<endl;
    }
    //->
    Buch* b=new Buch(...);
    b->drucke();
    delete b;
    
    //b: Rückgabe des Druckstrings
    string hole() const//btw, hier gehört imho KEINE Referenz hin
    {
      return "Buch - Autor:"+Autor+"\n";
    }
    //->
    Buch* b=new Buch(...);
    cout<<b->hole();
    delete b;
    


  • Danke für eure HIlfe,
    Das ganze sieht nun so aus und funktioniert 🙂

    Gruss MIchael

    #include <iostream>
    #include <string>
    #include <conio>
    
    using namespace std;
    
    class Buch {
       private:
          string Autor;
          string Titel;
          string Erscheinungsjahr;
          static int zaehler;
    
       public:
          //Konstruktor Buch
          Buch(const string &AutorP, const string &TitelP, const string &ErscheinungsjahrP)
          : Autor(AutorP), Titel(TitelP), Erscheinungsjahr(ErscheinungsjahrP) {
             cout<<"Aufrufe: "<<zaehler++<<endl;
          };
    
          //Destruktor Buch
          ~Buch() { };
    
          //Gebe eingabe aus
          string druckeDaten() const {
             return "\nAutor: " + Autor+"\nTitel: " + Titel + "\nErscheinungsjahr: "+Erscheinungsjahr;
          };
    };
          //Initialisieren der Variable
          int Buch::zaehler = 0;
    
    int main() {
    
       //Deklaration der Eingabe Variablen
       string eingAutor;
       string eingTitel;
       string eingErscheinungsjahr;
    
    while(true) {
       //Eingabe des Autors, Titel und Erscheinungsjahr
       cout<<"\nGeben Sie den Namen des Autors ein: ";
       cin>>eingAutor;
       cout<<"Geben Sie den des Buchs ein: ";
       cin>>eingTitel;
       cout<<"Geben Sie das Erscheinungsjahr ein: ";
       cin>>eingErscheinungsjahr;
    
       //erzeuge Objekt auf Heap
       Buch* objektBuch = new Buch(eingAutor, eingTitel, eingErscheinungsjahr);
       //Gebe Daten aus
       cout<<objektBuch->druckeDaten()<<endl;
       //freigeben des Speichers
       delete objektBuch;
    }
    
       return 0;
    }
    

    Jedoch könnte mir jemand genau erklären wie sich das mit folgendem Teil verhält:

    Buch(const string &AutorP, const string &TitelP, const string &ErscheinungsjahrP)
          : Autor(AutorP), Titel(TitelP), Erscheinungsjahr(ErscheinungsjahrP) {
             cout<<"Aufrufe: "<<zaehler++<<endl;
          };
    

    Ich versteh nicht ganz wozi man das "const" gebraucht.



  • Wir haben hier ja eine Referenz, d.h. wir arbeiten direkt mit dem übergebenen String, damit der Aufrufer (das musst nicht immer du sein) sichergehen kann, dass sein String nicht verändert wird, macht man den Parameter const.


Anmelden zum Antworten