Zum Inhalt springen

CSV Datei in Struct einlesen


Dionysos211

Empfohlene Beiträge

"C - Programmieren"

Moin,

Ich möchte gern eine CSV Datei einlesen.

Diese kann ich selber generieren, also wenn ihr Vorschläge habt wie ich das doch besser machen sollte... immer her damit.

50;5

Mqnmsebw;Wxeucquu;4;3;Besgvijm Str.;19;2;Rigfwkdv;+;1;K1;D1;2;K2;D2;3;K3;D3;4;K4;D4;5;K5;D5

Iaphhnll;Gawwknjm;8;6;Bvuprmie Str.;19;4;Bnctgswy;+;1;K1;D1;2;K2;D2;3;K3;D3;4;K4;D4;5;K5;D5

Psbvcrri;Xrxrszmk;12;9;Fnocvfga Str.;5;6;Mqllxikg;+;1;K1;D1;2;K2;D2;3;K3;D3;4;K4;D4;5;K5;D5

Rtsqqkle;Shgvufpa;16;12;Slxzmzrd Str.;16;8;Dqbwzjmt;+;1;K1;D1;2;K2;D2;3;K3;D3;4;K4;D4;5;K5;D5
So in etwa kann sie aussehen... Die erste Zeile enthält Infos über die Anzahl der Datensätze und die maximale Anzahl der Variablen Attribute. Kurze Erläuterung: Alles bis zum ;+; sind "feste" Werte... deren Anzahl ändert sich nicht... Nachname;Vorname;Gewicht;Geburtsdatum;Straße;Hausnummer;PLZ;Ort ;+; Alles was dann kommt können beliebig viele Attribute sein welche aber zu dem Datensatz gehören. Sie kommen immer in Paaren vor sprich wenn es ein K1 gibt dann gibt es ein D1 (Krankheit1 und Diagnose1) Sprich das erste sind Patienten Daten und das nach dem + sind dann seine beliebig vielen Krankheiten. Der generator ist noch nicht perfekt (Dazu kommt bestimmt später auch noch eine Frage) Hier einmal das Struct:

#define MAX 150

#define MID 100

#define MIN 50


typedef struct sPatientenkrankheit {

    char cName[MID];

    char cDiagnose[MAX];

    struct sPatientenkrankheit *pNext;

}sPatientenkrankheit;


struct sPatient {

    char cNachname[MIN];

    char cVorname[MIN];

    int iGewicht;

    int iGeburtstag; // JJJJMMTT oder als cGeburtstag

    char cStrasse[MAX];

    int iHausnummer;

    int iPLZ;

    char cOrt[MID];

    struct sPatientenkrankheit *pPatientenkrankheit;

};

Ich lege ein Array an was den Werten der Ersten Zeile der Datei entspricht hier jetzt grad [50]... z.B.
  struct sPatient arPatient_A[iAnzahlP];
ich versuche das ganze jetzt mit fscanf() zu lesen... und komm einfach nicht weiter.. ich weiß es gibt da irgendwie so Schablonen, aber keine Ahnung wie man die richtig verwendet. Meine Vorstellungen wie das eingelesen werden soll: 1. geh in die Erste Zeile 2. Lese den Wert bis Semikolon und speicher in iX Lese den Wert nach dem Semikolon bis zum "lf" und speicher in iKL 3. Lege ein arPatient[iX] an. Merke dir iKL als maximale Anzahl an Krankheiten die Patient haben kann... später vielleicht als Zählvariable zu gegrauchen - int i = 0 4. gehe in die zweite Zeile 5. Lese den Wert bis Semikolon und Speicher in arPatient.cNachname 6. Ignoriere das Semikolon 7. Lese den dann folgenden Wert bis Semikolon und speicher in arPatient.cVorname ... ... 8. Lese den dann folgenden Wert bis Semikolon und speicher in arPatient.cOrt 9. Ignoriere das Semikolon 10. Erstelle weil + nun ein Zeiger auf die erste Krankheitsliste des arPatient i'ten Patienten
arPatient_A[i].pPatientenkrankheit->pNext = NULL;

        struct sPatientenkrankheit *pTempPatientenkrankheit;

        pTempPatientenkrankheit = arPatient_A[i].pPatientenkrankheit;

11. Ignoriere das Semikolon

12. Lese den dann folgenden Wert bis Semikolon und speicher in

pTempPatientenkrankheit->pNext->cName

14. Ignoriere das Semikolon

12. Lese den dann folgenden Wert bis Semikolon und speicher in

pTempPatientenkrankheit->pNext->cDiagnose

14. Ignoriere das Semikolon

15. Lege zeiger auf nächsten Listeneintrag und lese weiter aus datei so wie eben bis du ein LF (line feed) findest..

wenn ja geh in die zweite Zeile und und mach das ganze für Patienten i = 2

Mein Probrlem ist halt der Mix aus char und int und der variablen anzahl an Krankheiten...

oben steht lediglich die MAXIMALE Anzahl die ein Patient haben kann... er kann also auch nur 3 haben..

könnt ihr mir helfen... ?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich habe da noch ein Paar Fragen:

1) Soll das ganze unbedingt in C gehalten werden? Wenn nein, empfehle ich C++.

2) Was sind MAX, MID und MIN? Tick, Trick und Track?

2b) Wenn es, wie es der Fall zu sein schein, Konstanten sind, warum definierst Du sie nicht auch als solche? #define ist einfach unsauber.

3) Bitte unterlasse die unsägliche Hungarian Notation. Ich weiss nicht, warum die a) je erfunden worden ist und B) heute immer noch zu finden ist. Benutze lieber sprechende Namen: "Krankheiten", "Alter", "Gewicht", "Anzahl" etc. und nicht "pKrankheiten", "iAlter". Soetwas verwirrt mehr und ist vollkommen redundant: Niemand würde ein "cAlter" erwarten.

4) Für das Datenmodell schlage ich folgendes vor: Gewicht in double, Geburtsdatum als char, Hausnummer als char, PLZ als char: 83.5 Kilo, 27.12.1989, 2a, D-54689 wären somit auch gültig.

5) Des weiteren würde ich mir einen "Parser" schreiben:


Lese_Header();

Werte_Header_aus();

Solange_noch_Zeilen_vorhanden: 

  Lese_Zeile();

  Werte_Zeile_aus();


Werte_Zeile_aus():

  Teile_Zeile_ab_"+"_in_zwei_Teile();

  Erzeuge_aus_Teil1_Patientendaten();

  Erzeuge_aus_Teil2_Krankheitsverlauf();

  Füge_Krankheitsverlauf_den_Patientendaten_hinzu();

  Gib_Patientendatensatz_zurück();


Erzeuge_aus_Teil2_Krankheitsverlauf():

  Solange_Zeichenkette_nicht_zuende:

    Lies_Zahl_bis_Semikolon();

    Lies_Krankheit[i]n[/i]_bis_Semikolon();

    Lies_Diagnose[i]n[/i]_bis_Semikolon();

    Lege_Krankheitsdatensatz_in_Krankheitsverlauf_ab();

  Gib_Krankheitsverlauf_zurück();

6) fgets ist Dein Freund

7) CSV ist in meinen Augen kein gutes Datenformat. Verwende lieber XML: The XML C parser and toolkit of Gnome

Bearbeitet von lilith2k3
Link zu diesem Kommentar
Auf anderen Seiten teilen

Moin,

hatte n bischen viel um die Ohren...

Erstmal vielen dank dafür das du dir die Zeit genommen hast um dich mit meinem Problem zu befassen..

Ich werd mir das erstmal alles anschaun und melde mich später nochmal...

Nur was ich noch sagen wollte, mein C-Lehrbuch sagt irgendwie "fgets niemals gar nicht überhaupt nicht nehmen weil übel"

eine richtige Begründung führen die aber nicht an...

und jub muss i C sein....

iAlter und cName etc. muss ich leider so machen (Wurde angewiesen den Code so "leichter" lesbar zu machen)

Den XML C parser schau ich mir gleich mal an, aber ich glaub das teil ist wie soll ich sagen zu "heavy"...

hab mal so etwas in Verbindung mit fscanf gelesen:

%[^;];%[^;];%[^\n]\n

nur versteh ich den einsatz nicht ganz...

auch nach dem hier nicht ganz B..4 Formatstring fr scanf(), fscanf, etc.

.....

öhm ja MIN MID und MAX sollen Konstanten sein, das wurde uns so beigebracht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Nur was ich noch sagen wollte, mein C-Lehrbuch sagt irgendwie "fgets niemals gar nicht überhaupt nicht nehmen weil übel"

Entweder, Du hast Dich geirrt und meintest gets oder Dein Buch taugt nicht. Es geht in diesem Punkt um Buffer overflows. Gets liest ohne Punkt und Komma in die Variable ein, die Du angegeben hast (ähnlich scanf!). Da fgets allerdings nur eine begrenzte, von Dir festgelegte Anzahl am Bytes liest, liegt es an Dir Boundary Checks zu betreiben. => sscanf.

Vielleicht schaust Du bezüglich fscanf mal hier weiter:

fscanf - C++ Reference

Galileo Computing :: C von A bis Z – 16.9 Formatiertes Einlesen/Ausgeben von Streams mit »fprintf()« und »fscanf()«

Sollte eigentlich recht verständlich sein. Falls Du noch gezielte Fragen hast, können wir Dir gern hier weiterhelfen.

iAlter und cName etc. muss ich leider so machen (Wurde angewiesen den Code so "leichter" lesbar zu machen)

Macht man heute nicht mehr.

Den XML C parser schau ich mir gleich mal an, aber ich glaub das teil ist wie soll ich sagen zu "heavy"...

Kommt darauf an, wieviel Zeit Du bekommst.

Wäre in meinen Augen eine Überlegung wert.

Vorallem ginge aus dem Datenformat hervor, was gemeint ist. Und der "Header" wäre auch nicht so eine kryptische Kombination.

öhm ja MIN MID und MAX sollen Konstanten sein, das wurde uns so beigebracht.

1) Was heißt "MIN", "MID" bzw. "MAX"?

Ich denke, Du bist Dir dessen bewußt.

Aber kannst Du auch garantieren, dass es der Programmierer nach Dir versteht?

Wohl kaum. Warum also die Variablen nicht richtig benennen? Lange Variablenbenennungen sind auch nicht aufwendig; heutige IDEs beherrschen Code Completion, wodurch das ständige Ausschreiben entfällt. Wenn Du keine IDE nutzt, wäre es genau jetzt an der Zeit, darüber nachzudenken.

2) Sind MIN, MID und MAX keine Konstanten. Konstanten werden nach wie vor mit dem Schlüsselwort "const" deklariert.

Auch wenn im "Kernighan/Ritchie" der Gebrauch solcher "symbolischen Konstanten" gutgeheißen wird, ist es schlechter Stil.

Es handelt sich bei den define-Anweisungen um sog. Präprozessor-Direktiven; d.h. mit #define definierte Ausdrücke werden stumpf vom Präprozessor ersetzt (in etwa so wie STRG+H "search/replace"). Das heißt, wenn Du überlegst, evtl. einen Debugger einzusetzen wirst Du die #defines nicht wiederfinden; was die Fehlersuche erschwert.

Eleganter ist es, Konstanten auch als solche zu kennzeichnen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Vor kurzem war schon mal ein Thema zum Einlesen von CSV Datein. Vielleicht findest du dort nützliche Infos.

Was ich an deiner Stelle nicht machen würde ist, daß du für deine char Arrays konstante Längen hast (char cVorname[MIN];). Was machst du, wenn mal jemand einen exotischen Vornamen, oder mehrere Vornamen, mit mehr als [MIN] hat? Das solltest du schon dynamisch festlegen.

Grundsätzlich kann ich dir nur empfehlen, dass du immer eine ganze Zeile einliest. Du sollstest beim einelsen keinen MAX-Buffer verwenden. Dein String (char *) in dem zu die Zeilen einliest sollte dynamischer länge sein. Speicher solltest du immer Blockweise anfordern, und nicht für jeden char ein malloc.

Deinen Zeilenstring kannst du dann entweder von "Hand", oder mit einer Stringfunktion (ich glaube strtok, fällt mir jetzt nicht ein) zerteilen und in diner Datenstruktur speicher.

lg und happy coding :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...