Auspannen eines Feldes
-
Hi,
ich glaube das Prinzip zu verstehen.
int i, xdim = 20, ydim = 10; int **array = malloc(sizeof(*array) * ydim); for (i = 0; i < ydim; ++i) array[i] = malloc(sizeof(**array) * xdim); /* zu benutzen mit array[y][x] */ for (i = 0; i < ydim; ++i) free(array[i]); free(array);
Du legst also erst einen Vektor mit ydim Elementen an. Aber warum benutzt Du da gleich **array? Würde *array nicht auch funktionieren?
Anschließend erzeugst Du dann von dem Zeilenvektor xdim Spalten. Das gefällt mir!
Könntest Du vielleicht noch kurz erklären, was ein CAST ist? Ansonsten vielen Dank. War gut verständlich!
-
int **array
ein array von int*-pointern.
jeder int*-pointer zeigt auf eine zeile.ein int* wuerde nicht funktionieren, weil ich dann ja nur ein array von ints haette.
ein cast ist, wenn man einen typen in einen anderen typen umwandelt und der compiler versucht, was sinnvolles aus den daten zu machen, die man castet.
so z.b. kann man einen double nach int casten und man bekommt, was man erwartet. der compiler weiss eben, wie man zwischen zahlentypen ordentlich umwandelt.
wenn man aber z.b. einen pointertyp in den anderen castet, passiert eigentlich nichts, weil immernoch an die selbe stelle gezeigt wird.
man kann aber auch einen string zum int casten, was in den meisten faellen absolut schwachsinnig ist, weil nur muell rauskommt. man wuerde ja praktisch die ersten 4 zeichen des strings als die 4 bytes des ints verwenden. beispiel:char string[5] = "ABCD"; long int zahl = *(long int *)string;
ich caste den string (zeiger auf char) zum zeiger auf int und dereferenziere dann.
man kann auch sowas machen:
char string[] = "Hallo Welt"; printf("adresse: %d\n", (int)string);
ohne den cast nach int wuerde der compiler vielleicht meckern. so sagt man dem compiler, dass man wirklich aus dem pointer ne zahl machen will. die zahl ist hier dann eben die adresse des (ersten zeichens des) strings.
-
double **dataBag = (dataBag*) malloc(sizeof(*dataBag) * ydim); for (i = 0; i < ydim; ++i) { dataBag[i] = (double*) malloc(sizeof(*dataBag) * xdim); }
Ich habe gerade versucht mein Feld dataBag aufzuziehen - es klappt aber irgendwie nicht. Wäre für Tips dankbar.
FEHLERMELDUNG:
-----------------------------------------------------------------------------------------------------------
Kompilierung läuft...
main.cpp
c:\AFG_05_1\main.cpp(98) : error C2059: Syntaxfehler : ')'
Fehler beim Ausführen von cl.exe.AFG_05_1.exe - 1 Fehler, 0 Warnung(en)
-----------------------------------------------------------------------------------------------------------
P.S.: Für Visual C++ 6.0 ist der CAST anscheinend doch notwendig - wenn ich diesen weglasse, erhöhen sich meine Fehlermeldungen gleich deutlich....
-
da fehlt ein sternderl
double **dataBag = (dataBag**) malloc(sizeof(*dataBag) * ydim); for (i = 0; i < ydim; ++i) { dataBag[i] = (double*) malloc(sizeof(*dataBag) * xdim); }
Wennst als c++ compilierest ( .cpp ) dann musst du casten.
Kurt
-
Das funktioniert leider immer noch nicht. Die Fehlermeldung ist unverändert.
Kurt kannst Du mir einmal erklären - was da passiert. Wie kann ein sizeOf verwendet werden, wenn der Pointer dataBag noch gar nicht zuvor definiert wurde?
-
W2K2005 schrieb:
Das funktioniert leider immer noch nicht. Die Fehlermeldung ist unverändert.
Kurt kannst Du mir einmal erklären - was da passiert. Wie kann ein sizeOf verwendet werden, wenn der Pointer dataBag noch gar nicht zuvor definiert wurde?
Sorry mein Fehler
muss natürlichdouble **dataBag = (double**) malloc(sizeof(double *) * ydim);
sein
Kurt
-
Hallo Kurt:
Super! Jetzt gehts.
Hättest Du vielleicht noch einen Moment Zeit, um mir zu erklären, was hier passiert. Die Erklärung von c.crackwitz leuchtet mir noch nicht ganz ein.1 double **dataBag = (double**) malloc(sizeof(double *) * ydim); 2 for (i = 0; i < ydim; ++i) 3 databag[i] = malloc(sizeof(**databag) * xdim); 4 }
Zunächst wird ein Feld von double-Pointern (Dimension: ydim) allokiert.
- Warum müssen diese von C++ gecastet werden? Crackwitz hat mir geschrieben, dass dies ein schlechter Stil ist.
- Warum werden in Zeile 1 Pointer allokiert und nicht konventionelle Variablen?
- **dataBag ist dann ein Pointer auf einen Pointer. Richtig?
-
W2K2005 schrieb:
- Warum werden in Zeile 1 Pointer allokiert und nicht konventionelle Variablen?
Weil hinter jedem Element von dataBag ein eigenes SubArray angelegt werden soll - d.h. die Elemente sind Pointer (und werden in Zeile 3 mit Werten gefüllt).
- **dataBag ist dann ein Pointer auf einen Pointer. Richtig?
Korrekt.
-
CStoll schrieb:
- **dataBag ist dann ein Pointer auf einen Pointer. Richtig?
Korrekt.
Kommt jetz drauf an welches in
sizeof(**databag)
ists ein double
Kurt
-
CStoll schrieb:
@showme: in C gibt es (noch) kein new
besser ist das. die heapverwaltung ist eine library und hat in der sprache nix verloren.
-
Hi,
kannn mir bitte noch einmal jemand helfen. Ich bekomme diese 2D-Feld aus double-Zahlen nicht aufgespannt.
double **dataBag = (double**) malloc(sizeof(double*) * ydim); for (i = 0; i < ydim; ++i) { dataBag[i] = (double*) malloc(sizeof(double) * xdim); }
Vielen Dank,
W2K2005
-
W2K2005 schrieb:
Ich bekomme diese 2D-Feld aus double-Zahlen nicht aufgespannt.
Eine ausführliche Fehlerbeschreibung ist immer hilfreich. Deine hat den Informationsgehalt von "geht nicht".
Der Code sieht doch gut aus. Ich würde allerdings xdim und ydim vertauschen.
-
Wenn ich versuche dem Feld Werte zuzuweisen, dann funktioniert das nur, solange ich die erste Spalte verwende.
Also:
double value = 3.14152; int i =0, j; for (i=0; i<dim; i++) { for (j=0; j<xdim; j++) { dataBag[i][j] = value; } }
Soabld i > 0 ist, stehen zwar Werte in der Matrix dataBag aber irgendwie ganz komisch angeordnet....
-
W2K2005 schrieb:
irgendwie ganz komisch
Ach so, na dann ist ja alles klar
Bitte zeig uns ein kompilierbares Minimalbeispiel, mit "irgendwie ganz komisch".
-
#include <stdio.h> #include <stdlib.h> void main(void) { double value = 3.14152; int i = 0, j; int xdim, ydim; scanf("%d", &xdim); scanf("%d", &ydim); double **dataBag = (double**) malloc(sizeof(double*) * ydim); for (i = 0; i < ydim; ++i) { dataBag[i] = (double*) malloc(sizeof(double) * xdim); } for (i=0; i<ydim; i++) { for (j=0; j<xdim; j++) { dataBag[i][j] = value; } } for (i=0; i<ydim; i++) { for (j=0; j<xdim; j++) { printf("%d ", dataBag[i][j]); } printf("\n"); } }
-
double und %d passt nicht zusammen.
-
Stimmt!
In dem Einfachen Beispiel funktioniert die Speicherallokierung - aber in dem Programm, wo ich das Datenfeld eigentlich brauche, klappt es nicht.
Hier ist ein Auszug davon. *pList ist eine Liste mit Dateinamen. Diese enthalten Zahlenwerte, die mit der Funktion parse gelesen werden. Wenn parse die Zeile interpretieren konnte, gibt die Funktion den Wert 1 zurück. Solange ich mich in der ersten Zeile (1. Datei) bewege, funktioniert das Programm. Anschließend entsteht der Fehler???double **dataBag = (double**) malloc(sizeof(double*) * ydim); for (i = 0; i < ydim; ++i) { dataBag[i] = (double*) malloc(sizeof(double) * xdim); } i=0; do { printf("> Scanne %d. Datei: %s\n", i+1, pLIST[i].filename); fPtr = fopen(pLIST[i].filename, "r"); if (fPtr != NULL) { // Spaltenindex zurücksetzen j=0; while (!feof(fPtr)) { // Textzeile auslesen fgets(string, max, fPtr); RetVal = parse(string, name, &value, unit); if (RetVal == 1) { // Daten ins Feld speichern dataBag[i][j] = value; // Hier entsteht der Fehler mit i=1 und j=0 j = j + 1; } else { dataBag[i][j] = 0; // Hier entsteht der Fehler mit i=1 und j=0 } } fclose(fPtr); } else { printf("> Die Datei: %s konnte nicht ge%cffnet werden. Weiter...\n", pLIST[i].filename, 148); } i=i+1; } while (i < nums);
Das Programm liefert einen Ausnahmefehler, wenn die zweite Quelldatei geöffnet wird und ich versuche auf das Element [1][0] zuzugreifen.
-
Ich vermute, du überschreibst den dataBag-Zeiger, weil du bei einem anderen Array über die Grenzen hinaus schreibst. Möglicherweise ist string nicht groß genug, vielleicht schlägt auch die parse-Funktion über die Stränge.
Prüf mal den Wert des Zeigers vor fgets, zwischen fgets und parse, und nach parse.
-
Ich schicke mal das ganze Programm.
In meiner Eingabedatei steht beispielsweise folgender Text:1 INTEGRAL DATA
2 -----------------------------------
3 PLANE 1M
4 -----------------------------------
5 STATIC PRESSURE : 12345.7679543 [Pa] (gfdgdgd)
6 STATIC PRESSURE : 54321.0 [Pa] (reduced quantity)
8 ABSOLUTE TOTAL PRESSURE : 8000000.00000 [Pa] (not reduced quantity)
9 ABSOLUTE TOTAL TEMPERATURE : 400.0000 [K]Ich glaube eigentlich nicht, dass ich das Feld sprenge, denn ich lese zuvor die Anzahl der Zeilen aus meiner Datenbasis mit getMaxFileLength ein.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> typedef struct tagsLIST{ char filename[200]; char path[300]; } cLIST; int parse(char *string, char *name, double *value, char *unit) { if (3 == sscanf(string, "%[^:]:%lf [%[^]]", name, value, unit)) { while (strlen(name) && (name[strlen(name)-1] == ' ' )) name[strlen(name)-1]='\0'; return 1; } else { printf("> Error parsing.\n"); return 0; } } int getmaxFileLength(cLIST *pLIST, int nums) { int i, j; int max = 0; char tmp[512]; FILE *fPtr; for (i=0; i<=nums; i++) { fPtr = fopen(pLIST[i].filename, "r"); if (fPtr != NULL) { // Index auf Null zurücksetzen j = 0; // Datei existiert - ermittle Anzahl der Zeilen while(!feof(fPtr)) { fgets(tmp, 512, fPtr); j = j + 1; } if (j > max) { if (max > 0) printf("> ACHTUNG: Die Datei %s besitzt eine andere Zeilenl%cnge.\n Dies kann zu Problemen f%chren.\n", pLIST[i].filename, 132, 129); max = j; } fclose(fPtr); } } return max; } void main(void) { const int max = 300; int nums, RetVal; int xdim = 0, ydim = 0; int i = 0, j = 0; double tmp, value; char string[max], output[max]; char name[max], unit[50]; FILE *fPtr; printf("--------------------------------------------------------------------------------"); printf("| |"); printf("| Datenbasis-Generator |"); printf("| |"); printf("--------------------------------------------------------------------------------\n\n"); do { printf("> Geben Sie die Anzahl der Dateien ein: "); scanf("%d", &nums); if (nums < 0) { printf("> Bitte geben Sie einen ganzzahligen positiven Wert ein.\n\n"); } } while (nums < 0); if (nums >= 1) { // Ausgabedateiname einlesen printf("> Geben Sie den Ausgabedateiname ein: "); scanf("%s", &output); printf("> ------------------------------------------------------------------------------"); // Speicher allokieren mit dem Pointer pLIST cLIST *pLIST = (cLIST*) malloc(sizeof(cLIST)*nums); // Einzeldateinamen einlesen i=0; do { printf("> Dateiname [Nr.%d]: ", i+1); scanf("%s", pLIST[i].filename); i = i + 1; } while (i < nums); // Speicher allokieren printf("> ------------------------------------------------------------------------------"); printf("> Allokiere den Speicher...\n"); ydim = getmaxFileLength(pLIST, nums); double **dataBag = (double**) malloc(sizeof(double*) * ydim); for (i = 0; i < ydim; ++i) { dataBag[i] = (double*) malloc(sizeof(double) * xdim); } i=0; do { printf("> Scanne %d. Datei: %s\n", i+1, pLIST[i].filename); fPtr = fopen(pLIST[i].filename, "r"); if (fPtr != NULL) { // Spaltenindex zurücksetzen j=0; while (!feof(fPtr)) { // Textzeile auslesen fgets(string, max, fPtr); RetVal = parse(string, name, &value, unit); if (RetVal == 1) { // Daten ins Feld speichern dataBag[i][j] = value; j = j + 1; } else { dataBag[i][j] = 0; } } fclose(fPtr); } else { printf("> Die Datei: %s konnte nicht ge%cffnet werden. Weiter...\n", pLIST[i].filename, 148); } i=i+1; } while (i < nums); printf("> ------------------------------------------------------------------------------"); printf("> Schreibe Werte in die Datei...\n"); fPtr = fopen(output, "w"); if (fPtr != NULL) { for (i=0; i<nums; i=i+1) { for (j=0; j<ydim-1; j=j+1) { fprintf(fPtr, "%lf\t", dataBag[i][j]); } // Erzeuge Zeilenumbruch fprintf(fPtr, "\n"); } fclose(fPtr); printf("> Schreibvorgang erfolgreich beendet.\n"); } else { printf("> Die Ausgabedatei konnte nicht zum Schreiben ge%cffnet werden.\n", 148); } printf("> ------------------------------------------------------------------------------"); printf("\n> Programm beendet."); } else { printf("> Das Programm wurde beendet.\n"); } }
-
W2K2005 schrieb:
Ich schicke mal das ganze Programm.
In meiner Eingabedatei steht beispielsweise folgender Text:Tja, mit diesen Beispieldaten läufts bei mir.
Ich glaube eigentlich nicht, dass ich das Feld sprenge
Leider sind wir aber nicht in der Kirche.
Ich sags auch gern nochmal:
MFK schrieb:
Prüf mal den Wert des Zeigers vor fgets, zwischen fgets und parse, und nach parse.