Csv mit C in struct einlesen

ah-chimedes

Ensign
Registriert
Mai 2008
Beiträge
146
Hallo, bräuchte mal ein bissel Hilfe ich möchte eine CSV-Datei in ein struct einlesen und dann wieder ausgeben. Habe ich nur eine Zeile klappt alles bestens. Aber mit mehreren stürzt das Porg immer ab. Aber irgenwie klappts net.

Hier mal mein Quelltext:

CSV hat folgendes Format:

Name;Vorname;Anrede;Strasse;Hausnummer;PLZ;Ort;Kunde_seit
Beispielbau GmbH;;Firma;Industriestr.;1;98765;Werkstatt;2005
Maurer;Evelin;Frau;Kleistr.;11;38440;Wolfsburg;2009
Muster;Max;Herr;Musterstr.;9;12345;Musterstadt;1991
Schuster;Sarah;Frau;Am Walde;12;54321;Musterdorf;200


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

struct Daten
{
char name[200];
char vorname[200];
char anrede[200];
char strasse[200];
int hausnummer;
int plz;
char ort[200];
int kundeseit;

};

int main(int argc, char **argv)
{
FILE *filezeiger = NULL;
struct Daten *daten = NULL;
int x = 1;
int i;

filezeiger = fopen ("test.csv", "r");

if (filezeiger == NULL)
{
printf ("Fehler beim Oeffnen von %s\n",
argv[1]);
fflush(stdin);
getchar();
return 1;
}

while(1)
{
daten = realloc(daten, x * sizeof(struct Daten));
if(daten == NULL)
{
printf ("Es konnte kein Speicher angelegt werden.\n");
fflush(stdin);
getchar();
return 1;
}

if(fscanf(filezeiger, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^\n]\n", daten[x - 1].name, daten[x - 1].vorname, daten[x - 1].anrede, daten[x - 1].strasse,
&daten[x - 1].hausnummer, &daten[x - 1].plz, daten[x - 1].ort, &daten[x - 1].kundeseit) == EOF)
break;

x++;
}

for(i = 0; i < x; i++)
{
printf("%s, %s, %s, %s, %d, %d, %s, %d \n", daten.name, daten.vorname, daten.anrede, daten.strasse, daten.hausnummer, daten.plz, daten.ort, daten.kundeseit );
}


fflush(stdin);
getchar();
return 0;
}
 
Deine whileschleife beendet sich ja gar nicht, oder hab ich was übersehen.
EDIT: Ich habs übersehen, das EOF.
Es ist immer besser, wenn man gleich von anfang an weiß, wie groß das Feld wird, realloc kann m.M. nach nur unterschiedlich viel Speicher zusätzlich hinten anhängen.

Warum verwendest du bei scanf mal ein & und mal nicht, ich würde die Variante ohne nehmen.
EDIT: Auch wieder klar, das eine sind char* das andere ints.
 
Zuletzt bearbeitet:
also muss ich die größe des structs definieren?

wie z.b:

struct Daten daten[x];

und dann
*daten = NULL;
 
werds mal eben testen...danke schon mal:)
Ergänzung ()

hmm dann ist das struct doch nicht initialisiert ...:mad:
 
Hallo,
bevor man realloc einsetzt muss man den Speicher vorher mit malloc reserviert haben.
Also,

struct Daten *daten=malloc(sizeof(struct Daten));

mfg, thetroll
 
so hab mal eben malloc eingebaut...code sieht wie folgt aus:
hoffe ich habe alles richtig gemacht....bekomme nur leider immer noch "konnte keinen speicher anlegen. csv datei liegt direkt neben der quelltext datei...:freak:



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

struct Daten
{
char name[200];
char vorname[200];
char anrede[200];
char strasse[200];
int hausnummer;
int plz;
char ort[200];
int kundeseit[200];

};

int main(int argc, char **argv)
{
FILE *filezeiger = NULL;
struct Daten *daten=malloc(sizeof(struct Daten));
// struct Daten *daten = NULL;
int x = 1;
int i;

filezeiger = fopen ("daten.csv", "r");

if (filezeiger == NULL)
{
printf ("Fehler beim Oeffnen von %s\n",
argv[1]);
fflush(stdin);
getchar();
return 1;
}

while(1)
{
daten = realloc(daten, x * sizeof(struct Daten));
if(daten == NULL)
{
printf ("Es konnte kein Speicher angelegt werden.\n");
fflush(stdin);
getchar();
return 1;
}

if(fscanf(filezeiger, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^\n]\n", daten[x - 1].name, daten[x - 1].vorname, daten[x - 1].anrede, daten[x - 1].strasse,
&daten[x - 1].hausnummer, &daten[x - 1].plz, daten[x - 1].ort, &daten[x - 1].kundeseit) == EOF)
break;

x++;
}

for(i = 0; i < x; i++)
{
printf("%s, %s, %s, %s, %d, %d, %s, %d \n", daten.name, daten.vorname, daten.anrede, daten.strasse, daten.hausnummer, daten.plz, daten.ort, daten.kundeseit );
}


fflush(stdin);
getchar();
return 0;
}
 
@Blitzmerker

sorry hatte deine erste antwort falsch aufgefasst
 
thetroll schrieb:
Hallo,
bevor man realloc einsetzt muss man den Speicher vorher mit malloc reserviert haben.
Na da würde ich an Deiner Stelle gleich nochmal die Funktionsdokumentation anschauen!

realloc(NULL,size) ist gleichbedeutend mit malloc(size)
 
hmm also irgendwie weiss ich net mehr weiter...hab keine ahnung was man da noch ändern sollte
 
Das Problem ist, dass Deine Schleife nicht abbricht, und demnach x zu groß wird.

Die Folge ist, dass das Betriebssystem Deine Speicheranfrage nicht bedienen kann.

Ich würde mit fgets die Zeilen einzeln einlesen und dann per sscanf verarbeiten. fgets liefert NULL zurück, wenn das Dateiende gelesen wurde.
 
Zuletzt bearbeitet:
wenn ich das struct vor entferne meckert der compiler : 'Daten' undeclared....

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

struct Daten
{
char name[200];
char vorname[200];
char anrede[200];
char strasse[200];
int hausnummer;
int plz;
char ort[200];
int kundeseit[200];

};

int main(int argc, char **argv)
{
FILE *filezeiger = NULL;
struct Daten *daten=malloc(sizeof(struct Daten));
// struct Daten *daten = NULL;
int x = 1;
int i;

filezeiger = fopen ("daten.csv", "r");

if (filezeiger == NULL)
{
printf ("Fehler beim Oeffnen von %s\n",
argv[1]);
fflush(stdin);
getchar();
return 1;
}

while(1)
{
daten = realloc(daten, x * sizeof(struct Daten));
if(daten == NULL)
{
printf ("Es konnte kein Speicher angelegt werden.\n");
fflush(stdin);
getchar();
return 1;
}

if(fscanf(filezeiger, "%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^;];%[^\n]\n", daten[x - 1].name, daten[x - 1].vorname, daten[x - 1].anrede, daten[x - 1].strasse,
&daten[x - 1].hausnummer, &daten[x - 1].plz, daten[x - 1].ort, &daten[x - 1].kundeseit) == EOF)
break;

x++;
}

for(i = 0; i < x; i++)
{
printf("%s, %s, %s, %s, %d, %d, %s, %d \n", daten.name, daten.vorname, daten.anrede, daten.strasse, daten.hausnummer, daten.plz, daten.ort, daten.kundeseit );
}


fflush(stdin);
getchar();
return 0;
}
 
Wo muss bitte bei 'struct Daten' das struct weg? Das struct Daten ist nicht via typedef definiert, also ist das Keyword 'struct' zwingend notwendig!
 
das erstaunlich ist nur, dass wenn die csv datei eine einzige zeile besitzt alles klappt. hat sie aber mehrere klappt es nicht....dann bekomme ich den fehler, dass der speicher nicht angelegt werden kann.:freak:

es muss nicht zwingend mit fscf gelöst werden falls jemand da noch eine lösung mit anderen funktionen hat wäre ich auch dankbar...
Ergänzung ()

habe den code noch mal ein wenig umgebaut...einlesen klappt anscheinend. aber er schreibt in die falschen felder des structs....

/*
============================================================================
Name : main.c
Author : Jochen Mueller
Version : 0.3
Copyright : Your copyright notice
Description : Mainfile for C-Project
============================================================================
*/
////*****Einbinden der Header-Dateien*****//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "menu.h"
//*****Zählervariable Deklarierem und Initialisieren****//
int i = 1;
//*****Definition Strukturen****//
struct data
{
char name[40];
char vname[40];
char anrede[10];
char strasse[40];
char hausnr[10];
char plz[5];
char ort[40];
char datum[4];
};

int eingabe;
int ende = 0;



int main(){
struct data text[100];
char buf[100];
int x;
char filename[255];

do
{
menu();
scanf("%i", &eingabe);

switch (eingabe)
{
case 1:
printf("Alles ok\n ");
fflush(stdin) ;
break;

case 2:
{
FILE *f1;

printf("Welche Datei wollen sie öffnen : ");
scanf("%s",filename);

struct data *data = NULL;
f1 = fopen(filename, "r");
if (f1 == NULL)
{
printf("Kann Datei nicht oeffnen\n");

}
else
{
printf("Datei vorhanden!\n");

/*Nun lesen Sie formatiert von der Datei ein ...*/
while((fscanf(f1,"%s;%s;%s;%s;%s;%s;%s;%s;\n",
&text.name,&text.vname,&text.anrede,text.strasse,&text.hausnr,
&text.plz,&text.ort,&text.datum)) != EOF )
{
i++;
}




printf("Es wurden eingelesen!\n\n");
fclose(f1);
}
fflush(stdin) ;
}
break;

case 3:
printf("Sortierfunktion ist noch nich verf\x81gbar!\n\n");
fflush(stdin);
break;

case 4:
while(i>0)
{
printf("Name: %s\t\t\n", text.name);
printf("Vorname: %s\t\n", text.vname);
printf("Anrede: %s\n", text.anrede);
printf("Strasse: %s\n", text.strasse);
printf("Hausnr: %s\n", text.hausnr);
printf("Plz: %s\n", text.plz);
printf("Ort: %s\n", text.ort);
printf("Datum: %s\n", text.datum);
printf("Datensatz Nr.:%i \n", i);
i--;
}


fflush(stdin) ;
break;

case 5:
printf("Das Programm wird beendet!\n");
fflush(stdin) ;
ende =1;
break;

default:
printf("Falsche Eingabe\n");
printf("Bitte erneut auswaehlen!\n\n");
fflush(stdin) ;
break;
}

}
while (ende == 0);



return 0;
}
 
Zuletzt bearbeitet:
Also, ich hab dein Code jetzt mal getestet.
Dein struct data *data=NULL brauchste gar nicht.
struct data test[100]={0}; Gab eine kleine Verbesserung (keine tausend Í's mehr) (Ein String hört bei 0 auf, daher einfach ausnullen, um das Ende automatisch zu erhalten).
Dann glaub ich, versagt fscanf ein bisschen. Laut Dokumentation ignoriert es jedes Leerzeichen, wenn du jetzt welche drin hast, so wie bei deiner GmbH, dann wird natürlich alles falsch sortiert.
Lösung: Komplette Zeile einlesen und dann zerlegen.
(In c++ wäre es
Code:
data split(string s)
{
data d;
size_t pos=0,find;
d.Name=s.substr(pos,find=s.find(";",pos+1));
pos=find;
d.Vorname=s.substr(pos,find=s.find(";",pos+1));
...
return d;
}
funktioniert so schön leider nur in C++)
Aber in C kann man das auch schreiben, ist halt etwas länger.
 
Erst mal danke für die ganzen Antworten. Muss es leider nur in c schreiben... :(
naja dann werd dann mal versuchen den ganzen stream einzulesen und dann mit strtok dass ding zu zerlegen...hab aber keine ahnung wie das funktioniert.
 
@Blitzmerker

jo alles klar...habs gelöst bekommen. kann zu hier. danke nochmal an alle die geantwortet haben.
 
Zurück
Oben