String richtig kopieren und löschen
-
Hallo
ich ha hier eine Struktur
typedef struct{ char *vorname char *nachname }adressdaten adressdaten a_daten[500];
jetzt hab ich mit malloc Speicher für vorname und nachname angefordert und mit Daten beschrieben, wenn ich jetzt ein unteres Element des arrays löschen will und dafür ein höhere Element dahinkopiern möchte und das höhere Element dann löschn möchte, wie mach ich das am geschicktesten, ich muss ja denn noch den speicher von dem gelöschent Element freigeben oder so.
-
Du gibst den Speicher des gelöschten Array-Elements frei und biegst anschließend alle Nachfolger so um, daß sie auf die vorher angelegten Strings verweisen:
int del_pos=17; free(a_daten[del_pos].vorname); free(a_daten[del_pos].nachname); for(int i=del_pos;i<a_size-1;++i) { a_daten[i].vorname=a_daten[i+1].vorname; a_daten[i].nachname=a_daten[i+1].nachname; } a_daten[a_size].vorname=a_daten[a_size].nachname=NULL; --a_size;
-
Ah ja, danke, aber wenn ich ja schon a_size kenne, und meine Daten eh nicht sortiert sind, ist es da nicht sinnvoller gleich, dies auszuführen?
a_daten[del_pos].vorname=a_daten[a_size-1].vorname; a_daten[del_pos].nachname=a_daten[a_size-1].nachname;
weitere frage kann man auch:
a_daten[a_size].vorname=a_daten[a_size].nachname=0;
ausführen, anstelle von NULL?
Wie sieht es eignetlich aus, wenn das strukt noch aus einigen Einträgen mehr besteht, wie z.B.
typedef struct{ char *vorname char *nachname char *strasse char *stadt int plz int telfon usw. }adressdaten
muss ich dann auch alles einzeln kopieren oder geht da soetwas wie:
a_daten[del_pos]=a_daten[a_size-1];
wie macht man es richtig und effizient?
-
free(a_daten[del_pos].vorname); free(a_daten[del_pos].nachname); /*...*/ memmove(a_daten+del_pos, a_daten+del_pos+1, (a_size-del_pos-1)*sizeof(/*struct*/ adressdaten)); a_size--;
Dynamischer Speicher ist immer eine heikle Angelegenheit, deshalb hab ich mir einen Memorymanager geschrieben, der die Adressen der angelegten Speicherblöcke mitprotokolliert (ne Liste halt) und der bei jeder Veränderung kontrolliert, ob die vorherigen und die nachfolgenden 32 Bytes noch die gleichen Werte haben, so kommt man vielen Fehlern frühzeitig auf die Spur und einen Debugger brauche ich auch nicht. Die Funktionen habe ich Locate (für malloc, realloc, free) und MemMove (für memmove) genannt. Zusätzlich gebe ich den Funktionen eine id mit, um genau zurückverfolgen zu können wo das Malheur passiert ist.
-
Wenn du ein unteres Element löschen willst, sagen wir mal an der Position 100 und statt dessen ein höheres Element ( z.B. Position 200 ) an diese Stelle kopieren möchtest, dann würd ich das so machen:
int untere_pos = 100, hoehere_pos = 200; a_daten[untere_pos].vorname = (char*)realloc( a_daten[untere_pos].vorname, strlen( a_daten[hoehere_pos].vorname ) + 1 ); a_daten[untere_pos].nachname = (char*)realloc( a_daten[untere_pos].nachname, strlen( a_daten[hoehere_pos].nachname ) + 1 ); strcpy( a_daten[untere_pos].vorname, a_daten[hoehere_pos].vorname ); strcpy( a_daten[untere_pos].nachname, a_daten[hoehere_pos].nachname ); free(a_daten[hoehere_pos].vorname); free(a_daten[hoehere_pos].nachname);
-
Danke für die Vorschläg ich werde da mal alle durchpobieren und mit einem Timer nachmessen was bei großen Strukturen günstig wäre. Hmm das Ei des Kolumbus scheit es da ja nicht zu geben, wobei ich sagen muss das memmove scheint mir recht schnell zu sein, zumindest ist es nicht viel Schreibareib, hat ja aber nichts zu sagen, nicht wahr.
-
Frage an keksekekse, um bei dem Beispiel zu bleiben, wenn del_pos der id des zu löschenden Datensatzes und a_size die Anzahl der beschriebenen Datensätze ist, schreibt man dann nicht:
free(a_daten[del_pos].vorname); free(a_daten[del_pos].nachname); : : memmove(&a_daten[del_pos], &a_daten[a_size-1], sizeof(adressdaten)); //hab ich das so richtig gemacht??? a_size--;
oder ist der memmove den du beschreibst so gedacht, daß alle Daten die nach a_daten[del_pos] kommen, um eine Feldgröße nach unten gerückt werden?
-
Der memmove()-Befehl soll die freiwerdende Lücke auffüllen (analog zu meiner for()-Schleife, nur etwas kürzer formuliert). Aber wenn es dir auf die Reihenfolge der Einträge nicht ankommt, dürfte proggingmania's Ansatz noch besser geeignet sein - da mußt du nur ein einziges Element umkopieren.
-
Wie sieht es eigentlich aus, wenn in meiner Struktur noch eine weitere Struktur eingebettet ist? Wie muss ich dann kopieren, löschen oder verschieben.
-
Achso ja das hab ich vergessen zu sagen, ich muss das letzte Element in die Lücke des gelöschten Elements einfügne, da (wie nennt man eigentlich einen einzelnen Teil eines Arrays einer Struktur) die Strukturdaten in einer Windowsanwendung in einer Liste zu sehen sind und dem Item wurde als "lParam" der Datensatz iD mitgegeben, damit ich eine Verbindung zwischen Fensteranwendung und Datensatz herstellen kann, d.h. ich muss wenn ich die Struktur nach unten kopiere oder verschieben auch noch den lParam des Items ändern, damit der Zusammenhang wieder passt.
Ums jetzt nochmal zusammen zu fassen, ich muss also erst den Speicher an Element del_pos freimachen, dann den Datensatz (a_size -1) mit memmove nach unten verschieben und alle Zeiger im Datensatzt (a_size -1) dann auf "0" setzen, habe ich das so richtig verstanden?