Problem bei der Ausgabe (Dynamische Speicherverwaltung)



  • Hi,
    nachdem ich mich langsam an die Pointer heranwage und auch Pointer-Arrays schon hinbekomme, wollte ich ein kleines Programm (man gibt Name und Nummer ein, diese werden am Ende wieder ausgegeben) so verändern, dass ich die Anzahl der einzugebenden Namen bzw. Nummern beliebig verändern kann.
    Ich habe das Problem, dass alle Ausgaben mit den zuletzt eingegebenen Daten belegt sind.
    Wenn ich erst den 1. Namen und Nummer eingebe, diese direkt ausgeben lass, dann den nächsten einlese, etc. funktionierts, wie ich es will.
    Warum ist das so, und wie behebe ich diesen Fehler?

    #include <iostream>
    #include <conio.h>
    #include <stdlib.h>
    #include <string>
    using namespace std;
    
    int main()
    {
    	struct Verwaltung
    	{	string Name;
    		int Nummer;
    	};
    	Verwaltung *Personen;
    
    	int n=0;
    
    	cout << "Wie viele Datensaetze wollen Sie eingeben?\t";
    	cin >> n;
    	Personen=new Verwaltung[n];
    	for (int x=0; x<n; x++)
    	{	cout << "\nName, Person " << x << ":\t\t";
    		cin >> Personen->Name;
    		cout << "Nummer, Person " << x << ":\t";
    		cin >> Personen->Nummer;
    	}
    	for (int x=0; x<n; x++)
    	{	cout << "\n\nName, Person " << x << ":\t\t";
    		cout << Personen->Name;
    		cout << "\nNummer, Person " << x << ":\t";
    		cout << Personen->Nummer;
    	}
    
    	getch();
    	return 0;
    }
    

    (Ich weiß, ich sollte danach wieder den Speicherplatz löschen, so weit bin ich aber noch nicht, dass ich das gemacht habe)



  • Personen[i].Name;
    

    Das dürfte helfen 🙂
    Du musst schon angeben, welches Element im Feld zu haben willst. Du schreibst und liest bisher immer nur auf der 1. Stelle



  • brauch ich das dann nicht so?

    (*Personen[i]).Name;
    

    oder so ähnlich?



  • 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



  • hab das mit der 1. lösung ausprobiert. ausgegeben wird alles richtig, nur anschließend bekomm ich ne fehlermeldung:

    Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)



  • der operator [] bei Zeigern bewirkt, dass automatisch die entsprechende Stelle im Feld adressiert wird UND das der Zeiger dereferenziert wird.

    Personen[i].Name entspricht (Personen + i)->Name oder (*(Personen + i)).Name

    Such dir aus was dir am besten gefällt^^



  • Der g++ macht keine Schwierigkeiten:

    #include <iostream>
    #include <cstdlib>
    #include <string>
    
    using namespace std;
    
    struct Verwaltung {
      string Name;
      int Nummer;
    };
    
    int main() {    
        Verwaltung *Personen=0;
    
        int n=0;
    
        cout << "Wie viele Datensaetze wollen Sie eingeben?\t";
        cin >> n;
        while (getchar()!='\n');
    
        Personen=new Verwaltung[n];
        for (int x=0; x<n; x++)
        {    cout << "\nName, Person " << x << ":\t\t";
            getline(cin, (Personen+x)->Name);
            cout << "Nummer, Person " << x << ":\t";
            cin >> (Personen+x)->Nummer;
            while (getchar()!='\n');
        }
    
        for (int x=0; x<n; x++)
        {    cout << "\n\nName, Person " << x << ":\t\t";
            cout << (Personen+x)->Name;
            cout << "\nNummer, Person " << x << ":\t";
            cout << (Personen+x)->Nummer;
        }
    
        delete [] Personen;
    
        getchar();
        return 0;
    }
    


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

    ich seh grad: das geht schief. der "." hat ne höhere Priorität als der * also macht der doch *((Personen+x).Name).



  • Pellaeon schrieb:

    der operator [] bei Zeigern bewirkt, dass automatisch die entsprechende Stelle im Feld adressiert wird UND das der Zeiger dereferenziert wird.

    Personen[i].Name entspricht (Personen + i)->Name oder (*(Personen + i)).Name

    Such dir aus was dir am besten gefällt^^

    Wobei man bei Zeigern aus stilistischen Gründen zu -> raten sollte, v.a. da somit offensichtlicher wird, dass mit einem Zeiger gearbeitet wird.

    Pellaeon schrieb:

    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.

    ich seh grad: das geht schief. der "." hat ne höhere Priorität als der * also macht der doch *((Personen+x).Name).

    Eh jup, einmal Klammern bitte :xmas2:



  • und woran liegt das jetzt mit der fehlermeldung?

    habe auch

    (Personen + i)->Name

    ausprobiert, aber wie erwartet, hat das nix an der fehlermeldung geändert, die nach der ausgabe kommt.



  • Geh mal mit dem Debugger durch und schaue, wo der Fehler genau auftritt bei welcher Stelle



  • hab ich schon. aber genau am ende wird die meldung angezeigt.



  • tu mal das getch zu testzwecken rausu nd schau ob es dann geht. Der Code sieht eigentlich mit der Änderung sauber aus, mal abgesehen vom fehlenden delete[] natürlich



  • es lag daran, dass ich bereits das delete mit dazu genommen hab, da aber wohl n fehler drin habe.

    habe den delete befehl in die letzte for-schleife gepackt, aber was stimmt denn an der programmierung nicht, hab schon alles ausprobiert, ohne index, mit index, etc.

    for (int x=0; x<n; x++)
    	{	cout << "\n\nName, Person " << x << ":\t\t";
    		cout << (Personen + x)->Name ;
    		cout << "\nNummer, Person " << x << ":\t";
    		cout << (Personen + x)->Nummer ;
    		delete Verwaltung[x];
    	}
    


  • sarah1986 schrieb:

    delete Verwaltung[x];
    

    Die anweisung als solche ist schon unsinnig (sag blos, das hat dein Compiler geschluckt) - 'Verwaltung' ist der Typ. Du mußt deine Variable löschen und zwar als ganzes:

    for(int x=0; x<n; x++)
    {
      //Ausgaben
    }
    delete[] Personen;
    


  • DA liegt der fehler groß groß^^ 🤡

    Du hast mit new[] ein Feld dynamisch angelegt, dieses kannst du nun auch nur wieder als ganzes mit delete[]freigeben

    new <-> delete
    new[] <-> delete[]

    Also mache das

    delete[] Personen;
    

    nachdem zu das Feld nicht mehr benötigst, ergo nach der zweiten for-Schleife



  • so ähnlich hatte ich es auch, nur die eckigen klammern hinter dem personen... das ging net. aber so läufts hoffentlich. tausend dank



  • gibt es die möglichkeit mein programm so zu erweitern, dass ich die abfrage zuvor, wieviele datensätze ich anlegen will, weglasse, und durch irgendne bedingung dann aufgehört wird, wie beispielsweise ein ausrufezeichen.



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


Anmelden zum Antworten