std::bad_alloc bei oFStream im zweiten Durchlauf.



  • Hallo Leute. Ich habe ein Problemchen. Erstens bin ich mir nicht sicher ob der Sytax der NEW-Befehle richtig ist, dh die Mitarbeiter korrekt erstellt werden. Zweitens gibt es nach dem zweiten Mitarbeiter (Wenn man mehr als 1 eingeben will) nach der Anstellungsart eine Fehlermeldung (Unten im Spoiler 2). Warum? Anscheinend kann die Datei nicht beschrieben werden, trotz iso::app. Könnt ihr mir helfen?

    C++ Code (Vermutlicher Problemcode):

    void ErstelleNeu()
    {
    	int AnzahlNeu;
    	cout << "Anzahl neuer Mitarbeiter eingeben!" <<endl;
    	cin >> AnzahlNeu;
    
    	for(int i = 0; i < AnzahlNeu; i++)
    	{
    		Mitarbeiter *Neu = new Mitarbeiter;
    		cout << "Vornamen des Mitarbeiters eingeben: "<<endl;
    		cin >> Neu[i].Vorname;
    		cout << "Nachnamen des Mitarbeiters eingeben: "<<endl;
    		cin >> Neu[i].Nachname;
    		cout << "Art der Anstellung eingeben (Vollzeit, Halbzeit, Aushilfe)"<<endl;
    		cin >> Neu[i].Anstellung;
    		ofstream NeuMitarbeiter_O ("Mitarbeiter.li", ios::binary | ios::app);
    		if(NeuMitarbeiter_O == NULL)
    		{
    			cout << "Fehler beim schreiben der Datei: \"Mitarbeiter.list\"!"<<endl;
    		}
    		NeuMitarbeiter_O.write ((char*) &Neu[i], sizeof (Neu[i])); 
    		NeuMitarbeiter_O.close();
    		cout<< "Mitarbeiter: "<<Neu[i].Vorname<<" "<<Neu[i].Nachname<<endl;
    	}
    
    }
    

    Fehlercode:

    Unbehandelte Ausnahme bei 0x76b6b727 in Schichtplan_Gen.exe: Microsoft C++-Ausnahme: std::bad_alloc an Speicherposition 0x0042fad0..

    Liebe Grüße,

    (P.S.: Ich bin noch Anfänger.^^)


  • Mod

    Das ganze Pointergefrickel benötigst du da nicht. Mach es ohne und es wird funktionieren und der Code wird viel besser und übersichtlicher.

    Früher Java gemacht?



  • Besser wäre hier sicherlich ein std::vector<Mitarbeiter>, aber der Fehler im Code liegt dadrin, daß nur jeweils für einen Mitarbeiter Speicher reserviert wird, anschließend aber davon ausgegangen wird, daß ein Array vorliegt.

    Lösung:

    Mitarbeiter *Neu = new Mitarbeiter[AnzahlNeu];
    

    vor die Schleife schreiben...

    Aber dein Programmdesign ist sowieso nicht so gut, denn du solltest die Datenhaltung und die Ein- bzw. Ausgabe in deinem Programm voneinander trennen.
    Bisher kann man nicht mehr im Programm auf die Mitarbeiter zugreifen, nachdem die Funktion aufgerufen wurde.

    Btw. Das entsprechende Speicherbereinigen mittels 'delete' fehlt hier auch noch (das bei einem Standard-Container (wie std::vector<>) manuell auch nicht mehr benötigt werden würde 😉

    Aber du bist ja Anfänger, das wird schon noch...



  • Nein, kein Java, Gar nischt. 😃

    Ich lerne nur aus einem Buch und versuche gerade mein Wissen mithilfe eines eigenen Projektes zu festigen. Doch nun sind auch noch ein paar mehr fragen dazu gekommen:

    Wenn ich diese Mitarbeiter nun erstelle (Wie das ohne Zeiger gehen soll muss ich mir noch mal angucken *grübbel*), wie kann ich die dann in einer anderen FUnktion namens ZeigeMitarbeiter abrufen? Ein kleines Beispiel wäre ganz nett. Ich hab es bisher nur so hinbekommen, indem ich den kram als Datei gespeichert habe und ios::app hinzugefügt habe. Mit .eof konnte ich dann über ifstream auslesen, doch da sind überall total viele Gleichheitszeichen zwischen den einzelnen Wörtern. Wie wei Linien übereinander. Wie bekomme ich die den Weg, so dass man nur die Mitarbeiternamen sieht?

    LG

    (Kompletter Code:)

    #include <iostream>
    #include <conio.h>
    #include <string>
    #include <fstream>
    
    using namespace std;
    
    class Mitarbeiter
    {
    public:
    
    	char Vorname[30];
    	char Nachname[30];
    	char Anstellung[20];
    
    };
    static int AnzahlMitarbeiter;
    
    void ZeigeMitarbeiter()
    {
    	string s;
    	cout<< "Mitarbeiterliste: "<<endl;
    	for(int i=0;i<AnzahlMitarbeiter;i++)
    	{
    	ifstream Mitarbeiter_I ("Mitarbeiter.li", ios::binary | ios::in);
    	while (!Mitarbeiter_I.eof())       
        {
            getline(Mitarbeiter_I, s);     
            cout << s << endl;    
    
        }
    		Mitarbeiter_I.close();
    	};
    }
    // ----------ERSTELLT NEUE MITARBEITER-----------------
    void Verwaltung()
    {
    	int AnzahlNeu,
    		i;
    	cout << "Anzahl neuer Mitarbeiter eingeben!" <<endl;
    	cin >> AnzahlNeu;
    
    	for(int i = 0; i < AnzahlNeu; i++)
    	{
    		Mitarbeiter *Neu = new Mitarbeiter[AnzahlNeu];
    		cout << "Vornamen des Mitarbeiters eingeben: "<<endl;
    		cin >> Neu[i].Vorname;
    		cout << "Nachnamen des Mitarbeiters eingeben: "<<endl;
    		cin >> Neu[i].Nachname;
    		cout << "Art der Anstellung eingeben (Vollzeit, Halbzeit, Aushilfe)"<<endl;
    		cin >> Neu[i].Anstellung;
    		ofstream Mitarbeiter_O ("Mitarbeiter.li", ios::binary | ios::app);
    		if(Mitarbeiter_O == NULL)
    		{
    			cout << "Fehler beim schreiben der Datei: \"Mitarbeiter.list\"!"<<endl;
    		}
    		Mitarbeiter_O.write ((char*) &Neu[i], sizeof (Neu[i])); 
    		Mitarbeiter_O.close();
    		ifstream Mitarbeiter_I ("Mitarbeiter.li", ios::binary | ios::ate);
    		if(Mitarbeiter_I == NULL)
    		{
    			cout << "Fehler beim auslesen der Datei \"Mitarbeiter.li\"!" <<endl;
    		}
    		Mitarbeiter_I.read ((char*) &Neu[i], sizeof (Neu[i]));
    		cout<<Neu[i].Vorname<<" "<<Neu[i].Nachname<<"; "<<Neu[i].Anstellung<<endl;
    		Mitarbeiter_I.close();
    		AnzahlMitarbeiter++;
    	}
    
    }
    
    //_--------------------MENÜ------------------
    
    void Menü()
    {
    	cout << "[M]itarbeiter hinzufügen"<<endl;
    	cout << "[S]chicht-Begrenzungen"<<endl;
    	cout << "[E]insehen der Mitarbeiter"<<endl;
    	cout << "[B]erechnung des Schichtplans"<<endl;
    	cout << "[P]rogramm schließen"<<endl;
    
    }
    
    int main()
    {
    	for(int i=0;i < 100;)
    	{
    		Menü();
    		char Auswahl;
    		cin >> Auswahl;
    		switch(Auswahl) 
    		{
    			case ('M'):
    			case ('m'):
    			{
    				Verwaltung();
    			} break;
    			case ('e'):
    			case ('E'):
    			{
    				ZeigeMitarbeiter();
    			}
    			getch();
    		}
    	}
    }
    

  • Mod

    TheSpecula(zfaul zm login schrieb:

    Ich lerne nur aus einem Buch und versuche gerade mein Wissen mithilfe eines eigenen Projektes zu festigen.

    Das Buch ist nicht zufällig "C++ von A bis Z"?

    Doch nun sind auch noch ein paar mehr fragen dazu gekommen:

    Wenn ich diese Mitarbeiter nun erstelle (Wie das ohne Zeiger gehen soll muss ich mir noch mal angucken *grübbel*),

    So wie sonst auch. Gany einfach ohne Pointer und ohne new. Wenn du int i; schreibst hast du ja auch einen int ohne new. Und diese Variable kann man dann zum Beispiel auch einer dynamischen Liste hinzufügen wie einem std::vector.

    wie kann ich die dann in einer anderen FUnktion namens ZeigeMitarbeiter abrufen?

    Du kannst Funktionen Parameter übergeben. Es ist mir ein Rätsel wie du new kennen kannst, und diese Grundlagen nicht.

    Ein kleines Beispiel wäre ganz nett.

    Mal sehen. Mein Beispiel wird aber ganz anders als dein anderer Code, da ich Th69s Hinweise befolge. Ich werde aber trotzdem versuchen, es anfängerfreundlich zu halten:

    #include<iostream>
    #include<string>
    #include<vector>
    
    using namespace std;
    
    class Mitarbeiter
    {
    private:
      string vorname;
      string nachname;
      string anstellung;
    public:
      Mitarbeiter(const string& vorname, const string& nachname, const string& anstellung): vorname(vorname), nachname(nachname), anstellung(anstellung){}
      string ausgabe() const;
    };
    
    ostream &operator<<(ostream&, const Mitarbeiter&);
    
    class Mitarbeiterlistenverwaltung
    {
    private:
      vector<Mitarbeiter> mitarbeiterliste;
    public:
      void einen_mitarbeiter_einlesen();
      void alle_mitarbeiter_ausgeben() const;
    };
    
    int main()
    {
      Mitarbeiterlistenverwaltung mitarbeiterliste;
      {
        int auswahl;
        do
          {
            cout<< "1: Mitarbeiter hinzufügen\n"
                << "2: Alle Mitarbeiter ausgeben\n\n"
                << "0: Programm beenden\n";
            cin>>auswahl;
            switch(auswahl)
              {
              case 1:
                mitarbeiterliste.einen_mitarbeiter_einlesen();
                break;
              case 2:
                mitarbeiterliste.alle_mitarbeiter_ausgeben();
                break;
              }
          }
        while(auswahl!=0);
      }
    }
    
    ostream& operator<<(ostream& out, const Mitarbeiter& mitarbeiter)
    {
      out<<mitarbeiter.ausgabe();
      return out;
    }
    
    string Mitarbeiter::ausgabe() const
    {
      return "Vorname: "+vorname+"\nNachname: "+nachname+"\nAnstellung: "+anstellung;
    }
    
    void Mitarbeiterlistenverwaltung::einen_mitarbeiter_einlesen()
    {
      cout<<"Neuer Mitarbeiter:\nVorname? Nachname? Anstellung?\nJeweils durch Leerzeichen oder Enter getrennt eingeben:\n";
      string vorname, nachname, anstellung;
      cin>>vorname>>nachname>>anstellung;
      mitarbeiterliste.push_back(Mitarbeiter(vorname, nachname, anstellung));
    }
    
    void Mitarbeiterlistenverwaltung::alle_mitarbeiter_ausgeben() const
    {
      cout<<"Es gibt "<< mitarbeiterliste.size()<<" Mitarbeiter:\n";
      for(unsigned int i=0; i<mitarbeiterliste.size(); ++i)
        {
          cout<<i+1<<".:\n"<<mitarbeiterliste[i]<<"\n\n";
        }
    }
    

    Der Code sollte eigentlich recht lesbar sein, deshalb ohne Kommentare - bei Anfängern weiß ich ohnehin nie was ich kommentieren soll, weil die meistens eher nach technischen Dingen fragen anstatt nach Programmlogik. Technik mag ich aber nicht kommentieren und Programmlogik ist in diesem Beispiel praktisch nicht vorhanden.



  • Hey, vielen Dank euch.

    Doch könntest du mir erklären oder mir einen Link geben, was es mit diesem Ostream-Zeug auf sich hat? Davon habe ich noch nichts gehört oder gelesen. Und nein, das Buch heisst "C++ für Spieleprogrammierer" von Heiki Kalista.

    Habe jedoch auch dieses C++ von A bis Z und muss sagen dass es grausam war/ist.



  • Bzgl. Streams, s. FAQ-Beitrag: Ströme und Dateien in C++


  • Mod

    Eine kürzere Antwort ist, dass ostream die Klasse des cout-Objekts ist.



  • Ty...

    Wenn man nun so das Grundgerüst der kOnsolenprogrammierung so einigermaßen draufhat, ist man ja noch lange nicht im Stande optimal zu programmieren. Welche Bücher würdet ihr empfehlen, welche nicht unbedingt neue Themengebite behandeln, sondern die bestehenden einfach ausbessern. Die da wären zb. Iostream, die STL, Klassen und so weiter.

    Aber bitte nicht das von Jürgen Wolf empfehlen, da bin ich schon drauf reingefallen 😞

    Weiß nicht wieso dass Alle gut finden (Amazon)



  • Specula schrieb:

    Wenn man nun so das Grundgerüst der kOnsolenprogrammierung so einigermaßen draufhat, ist man ja noch lange nicht im Stande optimal zu programmieren. Welche Bücher würdet ihr empfehlen, welche nicht unbedingt neue Themengebite behandeln, sondern die bestehenden einfach ausbessern.

    Für Grundlagen ist der C++-Primer keine schlechte Wahl, er erwähnt auch die Standardbibliothek nicht nur am Rande. Für Programmiertechniken und Idiome ist z.B. "Effective C++" eine Möglichkeit (hab ich zwar selbst nicht, aber wird immer empfohlen), und eventuell "Exceptional C++" (geht vor allem in Richtung robuste/exceptionsichere Programme).

    Specula schrieb:

    Aber bitte nicht das von Jürgen Wolf empfehlen, da bin ich schon drauf reingefallen 😞

    Keine Angst, hier gibt es genügend Leute, die entsprechende Vorschläge in der Luft zerfetzen 😉

    Specula schrieb:

    Weiß nicht wieso dass Alle gut finden (Amazon)

    Weil man als Anfänger gar nicht realisiert, dass man Halbwissen lernt. Das Buch ist gut lesbar geschrieben und ermöglicht es, relativ schnell zu Ergebnissen zu kommen (sogar GUI), nur halt zu einem hohen Preis. Doch wenn man nie modernes C++ gesehen hat, wie kann man wissen, dass das Gelernte weit davon entfernt ist? Daher die guten Rezensionen. Dazu kommt, dass negative Rezensionen schlecht bewertet werden und in der Versenkung verschwinden.

    Daher: Frage immer in Foren nach, dort findest du meist Leute, die mehr Ahnung als so manche Autoren haben...



  • Nexus schrieb:

    Daher: Frage immer in Foren nach, dort findest du meist Leute, die mehr Ahnung als so manche Autoren haben...

    wie zum beispiel du oder volkard(der ist quasi so ne art geheiligter Gott, nein nicht so ne Art, der ist DER GOTT HIER!), SeppJ oder drakon...


Log in to reply