Dynamisches 2D Array in Subfunction
-
Hallo Profis.
In meinem Programm benutze ich ein 2D Array, um Verbindungen zwischen Punkten zu speichern. Diese werden in einer Unterfunktion gesucht und sollen in ein 2D Array gespeichert werden. Der erste Index des Arrays soll die Punktnummer speichern, der zweite die Punktnummer mit denen eine Verbindung besteht. Das ganze sieht also in etwa so aus:
Array[1][1] = Punktnummer des ersten Punktes, der mit Punkt 1 verbunden ist.
Array[1][2] = Punktnummer des zweiten Punktes, der mit Punkt 1 verbunen ist.
Array[3][4] = Punktnummer des vierten Punktes, der mit Punkt 3 verbunden ist.Das Problem ist, ich erfahre erst in der Unterfunktion, wieviele Punkte maximal mit einem Punkt verbunden sind. Das heißt, ich kann das Array nicht wirklich vor dem Ausführen der Subfunction definieren. Also in etwa so:
void GetConnections(..., unsigned long **fPointConnections,...); int main(){ unsigned long **PointConnections = (unsigned long **)calloc(NNodex, sizeof(unsigned long *),i=0,NConnections; /*Das Problem: Den Wert von NConnections erfahre ich erst in der Subfunction. Andernfalls müsste ich mehrfach eine Schleife durch bis zu 20 Mio. Einträge durchgehen - das wollte ich vermeiden. Aus diesem Grund werde ich jetzt NConnections, so lange es unbekannt ist immer in "" setzen*/ for (i=0;i<"NConnections";i++){ PointConnections[i] = (unsigned long *)calloc("NConnections", sizeof(unsigned long)); } GetConnections(..., PointConnections, ...); } void GetConnections(..., unsigned long **fPointConnections, ...){ unsigned long j=0,k=0; .... /*Erst an dieser Stelle wird bekannt, wie groß NConnections eigentlich ist. Jetzt kann ich das Array also auch erst fertig deklarieren*/ .... for (i=0;i<nNodes;i++){ for (j=0;j<NConnections;j++){ fPointConnections[i][j] = ...; } } }
Ich hoffe, ich habe mein Problem hinreichend dargelegt. Wenn ich die Schleife zur deklaration des zweiten Arrayindexes nämlich erst in der Subfunction ausführe, bekomme ich "Segmentation Violation". Das funktioniert also nicht.
Dazu noch eine zweite, dem Thema verwandte Frage: Ist es möglich, dass ich ein Array überhaupt erst in einer Subfunction deklariere, befülle und dann den Pointer darauf an die main-function zurückgebe, ohne dass die Daten verloren gehen?
Vielen Dank schonmal für die Hilfe.
CJens.
-
Hallo
CJens schrieb:
Hallo Profis.
...Dazu noch eine zweite, dem Thema verwandte Frage: Ist es möglich, dass ich ein Array überhaupt erst in einer Subfunction deklariere, befülle und dann den Pointer darauf an die main-function zurückgebe, ohne dass die Daten verloren gehen?
...Btw. sehe ich deine erste Frage nicht und ich bin kein Profi ... aaber:
Mit malloc/calloc kannst du innerhalb einer Funktion zur Laufzeit Speicher reservieren und "befüllen", also Daten darin speichern und an main zurückgeben.Man kann 2D Arrays auch auf 1D Arrays abbilden bzw. mit 1D Arrays realisieren.
-
CJens schrieb:
unsigned long **PointConnections = (unsigned long **)calloc(NNodex, sizeof(unsigned long *),i=0,NConnections;
Das ist falsch, weil eine Klammer fehlt.
Es gibt mehrere Möglichkeiten,
- du kannst im aufrufenden Kontext eine maximale Größe jeder Dimension festlegen, dann calloc und dann die 'wirklichen' Dimensionsgrößen aus der Funktion rückgeben lassen
- die Funktion könnte unsigned long** rückgeben oder ein Parameter mit unsigned long***; auch hier musst du die Dimensionsgrößen irgendwie rückliefernÜblicherweise kapselt man die Funktionalitäten 'Speicherreservierung' und 'Nutzdatenbearbeitung' in zwei unterschiedliche Funktionen, zumindest aber Kontexte
-
Vielen Dank euch beiden.
Habt mir sehr weitergeholfen. Erstmal, dass man mit calloc einen Speicher reservieren kann und der nach Beenden der function noch erhalten bleibt (hab das mal probiert und hat nicht funktioniert, aber dann lag der Fehler da wohl wo anders) und das mit dem unsigned long *** hab ich ach noch nie gemacht... aber jetzt läuft es.
Für alle, die mal das gleiche Problem haben, anbei die Lösung:
#include <stdlib.h> void FillArray(unsigned long ***fpArray, unsigned long * fpN1, unsigned long * fpN2); int main(){ unsigned long **pArray, N1, N2,i=0,j=0; FillArray(&pArray,&N1,&N2); //Control output of index and value printf("First array dimension: %i\n", N1); printf("Second array dimension: %i\n", N2); for(i=0;i<N1;i++){ for(j=0;j<N2;j++){ printf("Array[%i][%i] contains: %i\n",i,j,pArray[i][j]); } } } void FillArray(unsigned long ***fpArray, unsigned long * fpN1, unsigned long * fpN2){ unsigned long **Array, Dimension1 = 3, Dimension2 = 2, fi=0, fj=0, Counter=0; *fpN1 = Dimension1; *fpN2 = Dimension2; Array = (unsigned long **)calloc(Dimension1, sizeof(unsigned long *)); for (fi=0;fi<Dimension1;fi++){Array[fi] = (unsigned long *)calloc(Dimension2, sizeof(unsigned long));} for (fi=0;fi<Dimension1;fi++){ for (fj=0;fj<Dimension2;fj++){ Array[fi][fj]=++Counter; } } *fpArray=Array; }
Pointer auf Pointer auf Pointer - langsam wirds unübersichtlich
Eine Frage noch an Wutz: Wieso packt man die Speicherallocierung in eine Extrafunction? Ich meine, das ist doch eigentlich ein Einzeiler und calloc ist ein Prototype, also quasi schon eine Subfunction - lasse mich da aber gerne eines besseren belehren, denn ich bin auch noch nicht besonders erfahren...
Grüße,
CJens
-
...noch der Hinweis, dass in der Lösung oben die Anweisung:
#include <stdio.h>
fehlt. Ansonsten funktionieren die printf-Befehle nicht.