PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Funktionen und Array von Pointern auf Struct als Parameter



ReSeT
11-01-2003, 13:17
Hallo zusammen!

Folgendes Problem:

Ich habe ein kleines Programm geschrieben, welches eine Adressdatei einliest, die aus einem Warenwirtschaftssystem als Textdatei exportiert worden ist. Die Datensätze umfassen jeweils 38 Felder, bestehend aus Strings. Die einzelnen Felder sind jeweils durch Semikolon getrennt. Der jeweils nächste Datensatz ist in der Datei nicht näher gekennzeichnet, daher muß also jeder Datensatz abgezählt werden.

Hier zunächst der Code zum Öffnen der Datei

adress.h



#define MAXFIELDS 38
#define MAXADDR 2000

typedef struct {
int number;
char field[MAXFIELDS][42];
}t_adress;



adress.c



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "adress.h"

int open_ascii_adress_file(char *filename,t_adress *adresse[])
{

FILE *fd;
int count = 0;
int entry = 0;
int row = 0;
int line = 0;
char c;
char buffer[42];

if ((fd = fopen(filename,"r")) == NULL) fprintf(stderr,"Error opening %s \n",filename);

while ((c = getc(fd)) != EOF) {
if (c == ';') {
if (count == 38) {
count = 0;
entry++;
}
buffer[row++] = '\0';
if ((adresse[entry] = malloc(sizeof(t_adress))) == NULL)
fprintf(stderr,"Memory allocation failed");
exit(1);
}
strncpy(adresse[entry]->field[count],buffer,strlen(buffer));

/*
if (strlen(adresse[entry]->field[count]) >= 1) {
printf("ID %d SLOT %d", entry, count);
printf(" -> %s\n ",adresse[entry]->field[count]);
}
*/

row = 0;
count++;
continue;
}
if ( isprint(c) || isdigit(c) ) buffer[row++] = c;
}

fclose(fd);

return entry;
}


Diese Funktion liefert die Anzahl der Einträge zurück und schreibt die einzelnen Felder in eine Struktur. Zur Struktur referenziere ich über einen Pointer, den ich aus einem Array lese.

Das Programm:




#include <stdio.h>
#include <stdlib.h>
#include "adress.h"

int main()
{
char *filename = "A01.TXT";

t_adress *my_adresses[MAXADDR];

int entries, i;
int entry = 0;
char ch;

entries = open_ascii_adress_file(filename,my_adresses);

do {
for (i = 0;i < MAXFIELDS;i++)
printf("%d: %s\n",entry,my_adresses[entry]->field[i]);
entry++;
ch = getc(stdin);
} while ( (entry < entries) && (ch != 'q') && (ch != 'Q'));

return 0;
}


Da ich ja der Funktion open_ascii_adress_file einen Array von Pointern auf Strukturen übergebe, müsste diese Funktion die Strukturen ja direkt über die Zeiger ändern können. Innerhalb der Funktion sind die Daten ja vorhanden, wie ich durch den auskommentierten Teil nachweisen kann. Möchte ich die Daten in main() ausgeben, erhalte ich eine leere Ausgabe. Ich verstehe an dieser Stelle nicht warum, da ich ja alle Daten über Zeiger anspreche. Habe ich hier grundsätzlich etwas nicht verstanden, oder lediglich eine Kleinigkeit übersehen?

anda_skoa
11-01-2003, 14:04
Ich hab das jetzt nicht ausprobiert, aber wahrscheinlich wird das Array als call-by-value übergeben.
D.h. dass das externe Array nicht geändert wird.
Du müsstest einen Pointer auf das Array übergeben, oder eine Referenz darauf.

Ciao,
_

ReSeT
12-01-2003, 01:59
Jo, stimmt, war nicht ganz untrivial da drauf zu kommen. Ich war zunächst der Auffassung, ich hätte einen Zeiger übergeben.

Also hilft nur ein Zeiger auf den Zeiger :D

Danke einstweilen.

ReSeT
13-01-2003, 20:47
Hallo!

Ich habe mich nochmals etwas mit dem Thema Vektoren von Zeigern befasst und bin zu folgendem Ergebnis gekommen:

Genau wie einen Zeiger kann ich Vektoren von Zeigern an Funktionen übergeben, es wird immer direkt die Speicheradresse auf die der Zeiger zeigt behandelt, sei sie aus einem Vektor oder nicht. Es spielt auch keine Rolle, ob der Zeiger bereits einen sinnvollen Inhalt hat oder nicht, solange ich ungültige Zeiger nicht referenziere.

vgl K&R Programming in C pp.93 ff., pp.104 ff.

Das Problem in obigem Programm ist ein ganz anderes:

Der Speicher für adresse[entry] wird bei jedem Semikolon neu alloziert anstatt bei jedem 38sten.Somit ist der gewünschte Speicher nicht adressierbar. Das kann nicht funktionieren.

Folgender Ansatz ist ANSI konform und laut meinem Verständnis und meinen schlauen Büchern korrekt.



int open_ascii_adress_file(char *filename,t_adress *adresse[])
{
FILE *fd;
int count = 0;
int entry = 0;
int row = 0;
int line = 0;
char c;
char buffer[42];

if ((fd = fopen(filename,"r")) == NULL) {
fprintf(stderr,"Error opening %s \n",filename);
exit(1);
}

if ((adresse[entry] = malloc(sizeof(t_adress))) == NULL) {
fprintf(stderr,"Memory allocation failed");
exit(1);
}

while ((c = getc(fd)) != EOF) {
if (c == ';') {
if (count == 38) {
count = 0;
entry++;
if ((adresse[entry] = malloc(sizeof(t_adress))) == NULL) {
fprintf(stderr,"Memory allocation failed");
exit(1);
}
}
buffer[row++] = '\0';
strncpy(adresse[entry]->field[count],buffer,strlen(buffer)+1);
row = 0;
count++;
continue;
}
if ( isprint(c) || isdigit(c) ) buffer[row++] = c;
}

fclose(fd);

return entry;
}


GreetZ
ReSeT