Problem bei der Ausgabe (Dynamische Speicherverwaltung)



  • achso.



  • variable ist jetzt lokal.
    mein prog lässt sich zwar kompilieren, aber beim ausführen funzt nix, wie es soll.
    wenn ich den menupunkt 1, oder 2 aufrufe, dann bekomm ich mal wieder run-time-check-failure#3 (Personen is being used without being defined)



  • Deine dynamische Speicherverwaltung ist murks. Wenn du verschiedene Personen willst, brauchst du ein Feld. Du tust jedoch jedesmal nur ein Feld der Länge 1 anlegen. Und wenn du noch keinen Arbeiter im Feld hast, knallt es auch, weil du einen nicht initialisierten Zeiger benutzen tust.
    Bei Felder musst du immer die aktuelle Anzahl, also die Länge des Felde, mitführen

    Entweder machst du dir ein statisches Feld von Zeigern, indem du dann die Zeiger auf deine mit new erzeugten Personen merkst(so hats sich wohl der Lehrer gedacht) oder Du musst ein dymaisches Feld machen. Das müsstest du aber jedesmal von der Größe ändern, wenn eine Person hinzukommt oder gelöscht wird(wirst du mit deinem derzeitigen Wissen noch nicht schaffen).
    Alternativ -> stl-Container, falls die erlaubt sind.



  • mit stl-containern hab ich noch nie gearbeitet. die anzahl habe ich nur zu testzwecken auf 1 gesetzt, damit ich erstmal sehe, obs überhaupt funzt. die zahl will ich dann erhöhen.
    ICH HASSE C++, warum muss das alles so kompliziert sein? Warum lernen wir net vb. das ist einfacher...



  • Die Zeiger sind zugegebenermaßen ein wenig schwierig, besonders für Einsteiger. Aber ich verspreche dir: Wenn du ne Weile C++ gemacht hast, wirst du VB hassen. So geht's mir nämlich. 🙂



  • bin jetzt im 2. lj, hab also schon über 1 jahr c++ hinter mir. vor knapp einem jahr haben wir in der schule mit pointern angefangen, aber kapieren tu ichs dadurch auch noch nicht. Naja dyn datenstrukturen haben wir ende letzten schuljahres gemacht, aber ich peil das net. ich habe vor ca. 6 wochen gerade mal angefangen zu kapieren, was pointer überhaupt sind.
    ich weiß net, wie ich das alles kapieren soll. jedesmal wenn ich denke, jetzt hast es kapiert, merk ich, dass ich davon noch garnix kapiert habe, weil wieder irgendne kleinigkeit alles umdreht.



  • Machst du eine Ausbildung zur Fachinformatikerin?
    Anyways, hast du dir schon mal meinen Pointer - Artikel angeschaut, dort steht so ziemlich alles drin, was es grundlegendes über Zeiger zu wissen gibt.



  • ja, und nochmal ja. aber ich versteh das irgendwie net so ganz. ich hab mir schon um die 15-20 verschiedene artikel zu dem thema durchgelsen. ich hab mich für die fr systemintegration entschieden, weil ich wusste, dass mir programmieren net so spaß macht, aber trotzdem gehen wir da so tief rein. hätte ich das zuvor gewusst, weiß ich net, ob ich den beruf trotzdem gewählt hätte, wahrscheinlich wärs dann eher it-systemelektronikerin geworden.



  • Hast niemand in deiner KLasse/deinem Kurs der dir das mal verstänldich erklären könnte? Oder nerv die Lehrer 🙂 dafür sind sie da



  • Ok, also ich hab jetzt mal dein Problem mit std::vector gelöst, vllt. hilft's dir...Hilfe zu Methoden von vector findest du auf http://www.cppreference.com/ .

    #include <iostream>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    struct Arbeiter {
      Arbeiter(const string &n, int i) : name(n), id(i) {}
      Arbeiter(const Arbeiter &rhs): name(rhs.name), id(rhs.id) {}
      ~Arbeiter() {}
    
      string name;  //Name des Arbeiters
      int id;    //Personalnummer
    };
    
    char menu() {
      static char c;
      cout<< "\n\n\tPersonalverwaltung"
          << "\n\t~~~~~~~~~~~~~~~~~~\n\n"
          << "1 --> Vorhandene Arbeiter ansehen"
          << "\n2 --> Arbeiter hinzufuegen"
          << "\n3 --> Arbeiter aendern"
          << "\n4 --> Arbeiter loeschen"
          << "\n\n0 --> Programm beenden"
          << "\n\nIhre Eingabe:\t";
      cin>>c;
      getchar();
      return c;
    };
    
    void ArbeiterAuflisten(const vector<Arbeiter> &vec) {
      for (int i=0;i<vec.size();++i)
        cout<<"\n\nName: "<<vec[i].name
            <<"\nPersonalnummer: "<<vec[i].id<<'\n';
    };
    
    void ArbeiterNeu(vector<Arbeiter> &vec) {
      string name("");
      int id;
      //Informationen einlesen
      cout<<"Name: "; getline(cin, name);
      cout<<"Id: "; cin>>id;
      getchar();
    
      //Arbeiter erstellen und an vector anhängen
      Arbeiter a(name, id);
      vec.push_back(a);
    };
    
    void ArbeiterAendern(vector<Arbeiter> &vec) {
      /* Das hier darfst du jetzt mal selber probieren */
    };
    
    void ArbeiterLoeschen(vector<Arbeiter> &vec) {
      /* dito */
    }
    
    int main(int argc, char **argv) {
      vector<Arbeiter> vec;
    
      char c;
      do {
        c = menu();
    
        switch (c) {
          case '1': ArbeiterAuflisten(vec); break;
          case '2': ArbeiterNeu(vec); break;
          case '3': ArbeiterAendern(vec); break;
          case '4': ArbeiterLoeschen(vec); break;
          case '0': exit(0);
          default: break;
        };
      }while(c!=0);
    
      return 0;
    };
    

    sarah1986 schrieb:

    ja, und nochmal ja. aber ich versteh das irgendwie net so ganz.

    Wenn du uns sagst, was genau du nicht verstehst, dann können wir dir vllt. helfen.



  • zum beispiel, warum ich bei dem einen prog

    *Pers=new Verwaltung[v];
    

    und bei dem anderen

    Pers=new Verwaltung[v];
    

    schreiben musste.
    und warum ich

    Personen[i].Name;
    

    und nicht

    (*Personen[i]).Name;
    

    schreiben muss.

    und warum ich den run-check-failure bekomme. Es ist zwar lieb, dass du mir das prog umgeschrieben hast, aber ich wüsste trotzdem gerne, was an meiner programmierung falsch ist.

    in der klasse die arbeiten alle selber grade. und ich soll das alles in der arbeit lernen, damit ich auf den gleichen stand wie der rest der klasse komme, und daheim hab ich keine zeit mich zusätzlich damit stundenlang zu beschäftigen, und wenn ich 8 std. in der arbeit c++ gemacht habe, hab ich daheim keinen nerv mehr dazu.



  • sarah1986 schrieb:

    schreiben musste.
    und warum ich

    Personen[i].Name;
    

    und nicht

    (*Personen[i]).Name;
    

    schreiben muss.

    der operator [] auf einen Zeiger angewendet, tut automatisch mit derefernzieren.Also der * wird sozusagen schon automatisch mit gesetzt, wenn du [] benutzt. Wenn du den dann extra noch hinschreibst, hättest du faktisch 2 mal dereferenziert.



  • ok, das habe ich verstanden.



  • Gut gut, also entweder du machst das in einem Schritt:

    //Speicher für v Verwaltung anfordern und an Pers zuweisen
    Verwaltung *Pers = new Verwaltung[v];
    

    Oder in zwei Schritten:

    Verwaltung *Pers=0;  //Pointer auf Verwaltung, mit 0 initialisiert
    
    Pers = new Verwaltung[v];  
    //new fordert jetzt Speicher für v Verwaltungsobjekte an, und weist den Speicher Pers zu, d.h. der Wert von Pers ist die Adresse des angeforderten Speichers.
    

    Um dann an die Objekte zu kommen, die in diesem Speicher liegen, dereferenziert man den Pointer mit dem * - Operator:

    cout<<*Pers; //1.Element
    cout<<*(Pers+0); //Auch erstes Element, index 0
    cout<<*(Pers+1); //Zweites Element, index 1
    cout<<Pers[2];  //Dritts Element, index 2, Array-Schreibweise
    //...
    


  • aber warum ist das bei dem 1. was ich hingeschrieben hab mal mit stern, mal ohne. das waren beides arrays. und beides funzt, bei dem einen prog mit, bei dem anderen ohne stern.

    EDIT: das hat sich ja nun erledigt....war wohl zu ungeduldig.



  • k, das hab ich glaub ich auch verstanden.
    bin mal gespannt, was als nächstes kommt.

    wo liegt denn bei meiner prog der fehler, dass ich diesen blöden failure bekomme? ich hab, meiner meinung nach, alles richtig.



  • sarah1986 schrieb:

    aber warum ist das bei dem 1. was ich hingeschrieben hab mal mit stern, mal ohne. das waren beides arrays. und beides funzt, bei dem einen prog mit, bei dem anderen ohne stern.

    Es kommt drauf an, was in dem Array drinne ist.

    Verwaltung *Pers = new Verwaltung[v];
    

    Hier hast du ein Feld von Objekten. Wenn du den Zeiger derefernezierst(ob mit * und . oder mit [] ist egal) befindest du dich jetzt quasi im Objekt.

    Zurück zum statischen:

    Verwaltung *Pers[100];
    

    Das ist ein Feld von Zeigern, oben drüber warns Objekte, jetzt sind es Zeiger ⚠ ⚠
    du kannst jetzt jedem Zeiger ein Objekt zuweisen

    pers[0] = new Verwaltung; //Achtung, EIN Objekt hier, kein Feld
    pers[1] = new Verwaltung; //Achtung, EIN Objekt hier, kein Feld
    usw.
    

    Wenn du jetzt pers derefernzierst, wo bist du dann? GENAU, wieder bei einem Zeiger, wir haben ja au schließlich ein Zeigerfeld.
    Was macht man mit Zeigern? Richtig, bei bedarf dereferenzieren

    (*pers[0]).name;
    

    Jetzt hast du einen Zeiger auf einen Zeiger. Bei 2 Zeigern. muss man auch 2 mal dereferenzieren. Das erste mal wird mit [] dererenziert, siehe POst oben, das zweite mal dann direkt mit dem *

    versuch das mal in Ruhe nachzuvollziehen, auch wenns jetzt beim Ersten lesen verwirrend ist.
    Du musst halt immer schauen, was du hast: Zeiger oder Objekt



  • sarah1986 schrieb:

    aber warum ist das bei dem 1. was ich hingeschrieben hab mal mit stern, mal ohne. das waren beides arrays. und beides funzt, bei dem einen prog mit, bei dem anderen ohne stern.

    Man kann auch Pointer auf Pointer anlegen, deshalb "ging" das:

    //Erstellen:
    int zeilen=5,spalten=10;
    Verwaltung **Pers;  //Ein Pointer auf weitere Pointer
    Pers = new Verwaltung*[zeilen];  //Erstmal die Zeilen holen
    
    for (int i=0;i<zeilen;++i)
      *(Pers+i) = new Verwaltung[spalten]; // Spalten anlegen
    
    //Löschen:
    for (size_t i=0;i<zeilen;++i)
      delete [] *(Pers+i);  //Spalten freigeben
    
    delete [] Pers;  //Zeilen freigeben
    Pers = 0;
    

    EDIT:

    wo liegt denn bei meiner prog der fehler, dass ich diesen blöden failure bekomme? ich hab, meiner meinung nach, alles richtig.

    Poste mal den aktuellen Code.



  • #include <iostream>
    #include <conio.h>
    #include <stdlib.h>
    #include <string>
    using namespace std;
    
    struct Verwaltung
    	{	string Name;
    		int Nummer;
    	};
    
    void Arbeiterauflisten(Verwaltung*,int);
    void Arbeiterneu(Verwaltung*,int);
    void Arbeiteraendern();
    void Arbeiterloeschen();
    
    int main()
    {
    	int n=1;
    	char Eingabe;
    	Verwaltung *Personen;
    
    	do
    	{	system("cls");
    		cout << "\tPersonalverwaltung";
    		cout << "\n\t~~~~~~~~~~~~~~~~~~\n\n";
    		cout << "1 --> Vorhandene Arbeiter ansehen";
    		cout << "\n2 --> Arbeiter hinzufuegen";
    		cout << "\n3 --> Arbeiter aendern";
    		cout << "\n4 --> Arbeiter loeschen";
    		cout << "\n\n0 --> Programm beenden";
    		cout << "\n\nIhre Eingabe:\t";
    
    		cin >> Eingabe;
    
    		switch (Eingabe)
    		{
    		case '1':
    			Arbeiterauflisten(Personen,n);
    			break;
    
    		case '2':
    			Arbeiterneu(Personen,n);
    			break;
    
    		case '3':
    			Arbeiteraendern();
    			break;
    
    		case '4':
    			Arbeiterloeschen();
    			break;
    		}
    	}
    	while (Eingabe != '0');
    
    	return 0;
    }
    
    void Arbeiterauflisten(Verwaltung *Pers,int v)
    {	system("cls");
    	cout << "\tIhre Arbeiter:";
    	cout << "\n\t~~~~~~~~~~~~~";
    	for (int x=0; x<v && Pers[x].Name.length()!=0; x++)
    	{	cout << x << " -->\t";
    		cout << "\tName:\t";
    		cout << Pers[x].Name ;
    		cout << "\n\t\tNummer:\t";
    		cout << Pers[x].Nummer ;
    
    		getch();
    	}
    }
    
    void Arbeiterneu(Verwaltung *Pers,int v)
    {	char Eing=' ';
    	system("cls");
    	cout << "\tNeuer Arbeiter:";
    	cout << "\n\t~~~~~~~~~~~~~~";
    	Pers=new Verwaltung[v];
    	do
    	{	for (int x=0; x<v && Pers[x].Name.length()!=0; x++)
    		{	cout << "\nName, Person " << x << ":\t\t";
    			cin >> Pers[x].Name;
    			cout << "Nummer, Person " << x << ":\t";
    			cin >> Pers[x].Nummer;
    		}
    	cout << "Moechten Sie einen weiteren Arbeiter eingeben? (j/n)\n\n\t";
    
    	}
    	while (Eing=='j');
    
    	getch();
    }
    
    void Arbeiteraendern()
    {	system("cls");
    	cout << "\tIhre Arbeiter:";
    	cout << "\n\t~~~~~~~~~~~~~";
    	getch();
    }
    
    void Arbeiterloeschen()
    {	system("cls");
    	cout << "\tIhre Arbeiter:";
    	cout << "\n\t~~~~~~~~~~~~~";
    	getch();
    }
    


  • WEnn ich raten soll: du arbeitest im Debugmodus und hast irgendwo einen Speicherzugriff auf ein nicht existierendes Objekt

    for (int x=0; x<v && Pers[x].Name.length()!=0; x++)
    

    Das ist aus der Arbeiterneu. Das Pers[x].Name.length(), was soll das dort?


Anmelden zum Antworten