Problem bei der Ausgabe (Dynamische Speicherverwaltung)



  • Ja, allerdings wird die Speicherverwaltung dann schwieriger (weil du vorher wissen mußt, wieviel Platz du brauchst - da müsstest du den belegten Platz in regelmäßigen Abständen reorganisieren). Oder du könntest umsteigen auf STL-Container (vector oder deque).



  • da reichen meine bisherigen kenntnisse nicht aus, dann lass ich es dabei, trotzdem vielen dank



  • GPC schrieb:

    Oder so (du willst ja bestimmt den ganzen Namen):

    getline(cin, (*(Personen+x)).Name);
    //getline(cin, (Personen+x)->Name);
    

    EDIT: Pellaeons Lösung geht auch, da man Pointer wie Arrays behandeln kann, und umgekehrt.
    EDIT2: Klammern einfügt

    habe mich jetzt nochmal an das prog gesetzt, und versuche alles zu verstehen. was bewirkt dieses +x genau? Muss ich das unbedingt benutzen?

    Dann habe ich noch ne Frage:
    In der Berufsschule haben wir ein Aufgabenblatt zur Dyn. Speicherverwaltung bekommen. (Verwaltung von Artikeln) Dort steht:

    Als Datenstruktur soll ein 1-dimensionales Array mit Pointern vom Typ T_Artikel gewählt werden, was somit einer halbdynamischen Datenstruktur eintspricht: das Pointer-Array ist statisch, die eigentlichen Artikeldaten werden dynamisch angelegt.

    Was ist damit gemeint? - Ist das das gleiche, wie ich bei meinem Prog verwendet habe oder wieder etwas anderes?



  • also das "+ x" dort hat mit Zeigeraritkemtik zu tun.

    "Personen" ist dein Feld. Bei Feldern ist der Name ein Zeiger auf das erste Element im Feld, also die 0.te Stelle sozusagen.
    Bei Feldern liegen die Elemente zusammenhängend hintereinander im Speicher, deswegen ja ein Feld 🙂
    Wenn du jetzt auf das zweite Element zugreifen willst, musst du dich im Feld weiter bewegen. Ein int ist z.B. normalerweise momentan 4 Byte groß. Du müsstes dich also um 4 Adressen weiter bewegen von der Startadresse aus.
    C++ ist jedoch clever, jetzt kommt nämlich die Zeigerarithmetik ins Spiel.
    Wenn du einen Zeiger + 1 machst, springt er nicht einfach ein Byte weiter, sonder es wird nachgeschaut, von welchem Typ der Zeiger ist und dann wird eine Variable weiter gesprungen. Also am Beispiel hier der erkennt "aha ich zeige auf ein int, int ist 4 Byte groß, also muss ich bei + 1 4 Byte weiter gehen im Feld.

    Also sorgt die Zeile (Personen + x) das er die Adresse des x.ten Elements berechnet. Und wenn du nun die Adresse des x.ten Elements hast, kannst du damit arbeiten.

    Zu deiner 2. Frage:

    Du sollst ein Array von Pointern machen, also

    T_Artikel* zeigerFeld[100];
    

    In der Aufgabe steht statisch, also ohne new machen udn einfach nen festen wert abgeben.



  • aber wenn ich das ohne das +1, sondern mit

    Personen[x].Name;
    

    mache funzt es ja genauso.

    ich dachte, das funzt nur mit new, da ich sonst keinen speicherplatz habe, jetzt SOLL ich es ohne new machen????
    da steig ich nicht durch.
    Wie soll denn der entsprechende Speicherplatz reserviert werden, wenn ich kein new verwende???
    Wann benutze ich dann new und wann nicht?



  • siehe Aufgabenstellung:
    Wenn du die Anzahl zur Compilezeit kennst(oder wenns halt vom Lehrer/Prof vorgegeben ist^^), dann machst du ein statisches Array.
    Wenn die Anzahl jedoch beim Kompilieren unbekannt ist, und erst während der Laufzeot ermittelt wird(wie auch immer: eingabe oder Berechnung oder was weis ich ...) dann musst du new benutzen.

    "Personen[x].Name" ist äquivalent zu "(Personen + x)->Namen", zumindest in deinem konkreten Fall.
    Bei dem statischen Array von Zeigern sieht der Zugriff schon wieder anders aus, weil die Typen anders sind.



  • dann werd ich das mal so probieren...



  • habe mein Programm erweitert:

    #include <iostream>
    #include <conio.h>
    #include <stdlib.h>
    #include <string>
    using namespace std;
    
    struct Verwaltung
    	{	string Name;
    		int Nummer;
    	};
    	Verwaltung *Personen;
    
    void Arbeiterauflisten(Verwaltung*,int);
    void Arbeiterneu(Verwaltung*,int);
    void Arbeiteraendern();
    void Arbeiterloeschen();
    
    int main()
    {
    	int n=1;
    	char Eingabe;
    
    	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 << "\n\nName, Person " << x << ":\t\t";
    		cout << Pers[x].Name ;
    		cout << "\nNummer, Person " << x << ":\t";
    		cout << Pers[x].Nummer ;
    
    		getch();
    	}
    }
    
    void Arbeiterneu(Verwaltung *Pers,int v)
    {	char Eing;
    	system("cls");
    	cout << "\tNeuer Arbeiter:";
    	cout << "\n\t~~~~~~~~~~~~~~";
    	do
    	{	*Pers=new Verwaltung[v];             // Hier kommt der Fehler
    		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();
    
    }
    

    und bekomme nun den Fehler:

    error C2679: Binärer Operator '=': Es konnte kein Operator gefunden werden, der einen rechtsseitigen Operator vom Typ 'Verwaltung *' akzeptiert (oder keine geeignete Konvertierung möglich)



  • 'Pers' ist ein Pointer auf ein Verwaltung-Objekt, also ist '*pers' ein Verwaltung-Objekt und dem kann kein Pointer zugewiesen werden. Du mußt direkt an 'Pers' zuweisen (und das als Referenz übergeben).

    (bzw wäre es besser, das Array nur einmal anzulegen - so würdest du es bei jedem 'neu'-Befehl wieder überschreiben)



  • CStoll schrieb:

    'Pers' ist ein Pointer auf ein Verwaltung-Objekt, also ist '*pers' ein Verwaltung-Objekt und dem kann kein Pointer zugewiesen werden. Du mußt direkt an 'Pers' zuweisen (und das als Referenz übergeben).)

    vor meiner Änderung ging es doch auch mit dem Stern, aber ok. Jedenfalls funzt es jetzt. danke

    CStoll schrieb:

    (bzw wäre es besser, das Array nur einmal anzulegen - so würdest du es bei jedem 'neu'-Befehl wieder überschreiben)

    da hast du recht, das hab ich übersehen...



  • ist bei dem Programm zwar nicht SO wichtig, aber: mach die globale Variable weg und in die main-Funktion rein. Du hast ja schon richtiger Weise deine Funktionen so gebaut, dass sie das Feld als Parameter verlangen. Globale Variable ist nicht nötig 🙂 Sollte man sich von Anfang an angewöhnen, die nicht groß zu benutzen.



  • welche variable meinst du? es ist doch keine globale da. oder meinst du die struktur? die muss aber global sein, da sonst der datentyp in der funktion unbekannt ist.



  • sarah1986 schrieb:

    oder meinst du die struktur? die muss aber global sein, da sonst der datentyp in der funktion unbekannt ist.

    Die Struktur selber kann schon global sein, muss, wie du sagtest, aber

    Verwaltung *Personen;
    

    ist global und sollte lieber in der main stehen.



  • Die Struktur kannst du im globalen namespace lassen.
    Ich meine das:

    Verwaltung *Personen;
    


  • 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.


Anmelden zum Antworten