Kundenverwaltung mit CSV, bitte um Hilfe!!!



  • Hallo an alle,

    ich soll eine Kundeneingabe mittels CSV realisieren.
    Dabei soll ein CSV-File mit Daten (Vorname, Nachname, Adresse, PLZ und Ort) die eingegeben werden sollen befüllt werden.
    Das File soll gespeichert werden und beliebig oft aufgerufen und erweitert werden können.
    Die Eingabe soll über eine Struktur erfolgen die die oben genannten Daten ins CSV schreibt.
    Weiters sollen die Funktionen malloc und realloc verwendet werden.

    Statische Variablen sind mir relativ klar nur leider hab ich noch keine Ahnung von dynamischer Speicherverwaltung, Strukturen und wie man sie befüllt und schreiben in CSVs.
    Ich wäre über jede Hilfe dankbar.

    mfg Phil



  • Statische Variablen sind mir relativ klar nur leider hab ich noch keine Ahnung von dynamischer Speicherverwaltung, Strukturen und wie man sie befüllt

    Na dann würde ich genau unter diesen Schlagworten nachlesen.

    und schreiben in CSVs.

    Naja: man sage, was man zu sagen hat und mache danach einen Beistrich.
    Ist fast wie sprechen, nur daß man statt einem Punkt einen Zeilenumbruch
    macht.

    Ganz allgemein bietet sich ein Format wie CSV aber eher an, um Tabellen
    oder ähnliches zu speichern. Für solche "einzeiligen" Tabellen, wie du
    sie beschreibst, ist das völlig sinnlos.



  • Danke für diesen hilfreichen Kommentar.
    Wäre für konstruktivere Vorschläge sehr dankbar.
    mfg Phil



  • im allgemeinen erwartet man von hilfesuchenden hier, dass sie ein konkretes problem haben und keine vorlesung in programmieren suchen. zum thema csv gibt es derzeit einen thread. für die anderen themen gibt es genug tutorials im internet.http://www.c-plusplus.net/forum/viewtopic-var-p-is-1637821.html

    wie genau kommst du zum programmieren? ist das nur etwas, was nebenher läuft oder willst du da mehr machen? wenn ja, wäre vielleicht der kauf eines buches zu diesem thema eine gute investition. (lesen solltest du es dann natürlich auch.)



  • Jetzt sei doch nicht gleich eingeschnappt!
    Du meinst doch Comma Separated Values, oder?
    Das ist ein Plain-Text-Format, kann man lesen und schreiben wie
    jeden anderen Text. Über die Trennzeichen ist man sich nie so recht
    einig geworden, siehe zum Beispiel die Wikipedia-Seite:
    http://de.wikipedia.org/wiki/CSV_(Dateiformat)

    wie genau kommst du zum programmieren? ist das nur etwas, was nebenher läuft oder willst du da mehr machen?

    Könnte dir wahrscheinlich besser helfen, wenn ich das wüßte.

    Dynamische Speicherverwaltung brauchst du prinzipiell nur, wenn du beim
    Programmieren nicht voraussagen kannst, wieviel Platz du brauchen wirst.
    Nachdem aber die Anzahl der Felder scheinbar feststeht, bräuchtest du
    malloc() und Freunde nur, damit die Strings beliebig lang sein können.



  • @ flamer:
    ich mache an einer technischen Schule eine Ausbildung zum Biomedizintechniker. Im Zuge dieser Ausbildung werde ich auch in C geschult oder besser gesagt geprüft.
    Diese Aufgabe ist Teil eines Projekts. Die Aufgabenstellung ist natürlich völlig Sinnlos, jeder vernünftige Mensch - auch ich zumindest - würde wahrscheinlich eine Datenbanklösung preferieren und mittels SQL-Statements Daten ein- und auslesen.
    Leider helfen mir meine Datenbankkenntnisse nicht bei dieser Aufgabe und da ich leider bisher keine Ausbildung zu diesem Bereich des Programmierens genießen durfte, habe ich auf Hilfe aus dem Board gehofft.

    Meine Probleme im Detail.

    Wie lese ich ein Bestehendes CSV mit nicht definierter Länge (auf leer) in ein Strukt ein das je nach Inhalt des CSVs mehr oder weniger Speicher benötigt - malloc, realloc.

    Wie füge ich dieser Struktur beliebig viele weitere Datensätze hinzu - ich dachte an EOF und realloc oder ähnliches, konnte aber noch nicht schlau werden - und schreibe diese Erweiterungen in das CSV.

    Tut mir leid wenn ich etwas forsch bin, leider bin ich etwas verzweifelt weil ich am kommenden Donnerstag etwas vorlegen soll und als Rüstzeug nur den Vorschlag "schau ins Internet" bekommen habe.

    @besserwisser: kannst du mir ein bestimmtes Buch empfehlen?

    Vielen lieben Dank
    Phil



  • phil666 schrieb:

    Wie lese ich ein Bestehendes CSV mit nicht definierter Länge (auf leer) in ein Strukt ein das je nach Inhalt des CSVs mehr oder weniger Speicher benötigt - malloc, realloc.

    csv's sind zeilenorientiert, d.h. ein kompletter datensatz endet mit einem '\n', also: du liest eine komplette zeilen ein (mit fgets o.ä, in einen festen buffer, der gross genug für die längste zu erwartende zeile ist), zelegst die zeile (mit strtok z.b.) in ihre bestandteile. als nächstes legst du dir mit 'malloc' eine struct-instanz an, in die die daten rein sollen. jetzt kannst du die kleinen strings entweder direkt in deine struct kopieren (falls sie char-arrays enthält), oder in der struct sind pointer, dann legst du mit malloc(strlen(eintrag)+1) speicher an, weist den dem pointer zu und kopierst danach den eintrag rüber. bei numerischen datentypen o.ä. musst du den eintrag natürlich vor dem speichern umwandeln, wenn deine struct entsprechende member enthält.

    phil666 schrieb:

    Wie füge ich dieser Struktur beliebig viele weitere Datensätze hinzu - ich dachte an EOF und realloc oder ähnliches, konnte aber noch nicht schlau werden

    mit 'linked lists' kannst du sowas machen. schau mal hier (6ter beitrag): http://www.c-plusplus.net/forum/viewtopic-var-t-is-160978-and-start-is-0.html

    phil666 schrieb:

    ...und als Rüstzeug nur den Vorschlag "schau ins Internet" bekommen habe.

    das ist doch shcon was. da findest du alles zu deinem thema.
    🙂



  • C hat ja eigentlich keinen String-Typ. Deshalb mußt du dich entscheiden, ob du für die Feldbreite Grenzen festlegen möchtest (das ist ein wenig einfacher zu programmieren -- aber irgendwie schrecklich). Wenn die einzelnen Felder nur vom Speicher begrenzt sein sollen, muß man auch beim Einlesen aus der Eingabe aufpassen. In C ist sowas nicht unbedingt komfortabel.

    fgets() ist so schlau, daß man damit einen Pufferüberlauf verhindern kann, wie schon fricky angemerkt hat.

    das ist doch shcon was. da findest du alles zu deinem thema.

    🙂
    Aber auch so viel Schwachsinn, daß es bis Donnerstag eng werden könnte.

    oder in der struct sind pointer, dann legst du mit malloc(strlen(eintrag)+1) speicher an

    Aber nicht vergessen, daß jeder malloc()-Zeiger auch wieder an free() gehen muß, damit der Speicher wieder freigegeben wird.



  • mit 'linked lists' kannst du sowas machen. schau mal hier (6ter beitrag)

    Bin ich jetzt der letzte, der aus Protest Unreg bleibt?



  • flamer schrieb:

    mit 'linked lists' kannst du sowas machen. schau mal hier (6ter beitrag)

    Bin ich jetzt der letzte, der aus Protest Unreg bleibt?

    gegen was protestierst du denn?
    🙂



  • Hab jetzt folgendes zusammengebracht:

    typedef struct
    {
    char Kundennummer[3];
    char Vorname[40];
    char Nachname[40];
    char Adresse[80];
    char PLZ[5];
    char Ort[20];
    char Land[20];
    } KUNDEN ;

    int main(int argc, char **argv) {

    int i,c,counter=0;
    FILE *datei;
    datei=fopen(argv[1], "r");
    while( (c=fgetc(datei)) != EOF)
    {
    if(c == '\n')
    counter++;
    }
    printf("Counter = %d \n",counter);

    KUNDEN kunde[counter];

    for(i=0;i<=counter;i++) {
    fscanf(datei,"%s,%s,%s,%s,%s,%s,%s\n",
    kunde[i].Kundennummer,kunde[i].Vorname,kunde[i].Nachname,kunde[i].Adresse,kunde[i].PLZ,kunde[i].Ort,kunde[i].Land);
    fprintf(stdout,"Kundennummer von %s %s, Wohnhaft in %s, %s %s %s lautet: %s\n",
    kunde[i].Vorname,kunde[i].Nachname,kunde[i].Adresse,kunde[i].PLZ,kunde[i].Ort,kunde[i].Land,kunde[i].Kundennummer);
    }

    return EXIT_SUCCESS;
    }

    Bekomme nur leider folgende Ausgabe:

    Counter = 5
    Kundennummer von @ @Øöÿ¿, Wohnhaft in ¿, úÿ¿
    7 lautet:
    lautet: mer von , Wohnhaft in , TÖ@@ii
    í@@øÿ¿«, Wohnhaft in @, @hùÿ¿
    ùÿ¿j
    ùÿ¿j c lautet: «
    Kundennummer von , Wohnhaft in @°ùÿ¿@sôï@ðùÿ¿h, ö lautet: ø
    Kundennummer von Ø_I ¿íìÂ@Àê@, Wohnhaft in ¿ç, ¿ôï@úÿ¿ò
    úÿ¿ò
    lautet: Ö[Ø_I
    Kundennummer von , Wohnhaft in @øúÿ¿PÄ@, }Ã@ôÏ@ !

    lautet:

    CSV wäre:

    1,Josef,Meyer,Musteralle 5/1/9,1010,Wien,Oesterreich
    2,Sepp,Mueller,Michlstr. 12/4/5,1020,Rom,Italien
    3,Horst,Cerny,Marxerstr. 45/21/7,1030,Strassburg,Belgien
    4,Heinz,Knapp,Mariahilferstr. 145/6/23,1040,Berlin,Deutschland
    5,Rudolf,Joechl,Rotenturmstr. 1a/r5,1050,St. Poelten,Oesterreich

    Ich wollte die CSV Elemente in ein struct Array schreiben und mit count die größe des arrays bestimmen.
    Leider funktioniert es anscheinend mit dem code den ich geschrieben habe nicht.
    Kann mir jemand sagen was ich falsch gemacht habe?

    wie könnte ich das strukt array dann zur laufzeit erweitern und die änderungen ins csv zurückschreiben.

    danke für euren input
    lg phil



  • ^^lies doch ganze zeilen mit fgets o.ä. ein und zerlege sie mit strtok, strcspn oder sowas. fscanf ist manchmal etwas zickig.
    🙂



  • gegen was protestierst du denn?

    Gegen das Vorurteil, dass Unregs so schlecht im Kopfrechnen sind, dass man ihnen dauernd Übungsaufgaben stellen muss.
    🙂

    fscanf ist manchmal etwas zickig.

    Manchmal? So ein Vorraus.

    Und jetzt kommen die man-Tags:
    man: fgets
    man: strtok



  • char Kundennummer[3];
    

    Du wirst nie mehr als tausend Kunden haben.
    Nimm statt 3 mindestens sizeof(int). 😉

    KUNDEN kunde[counter];
    

    Alte Compiler mögen sowas nicht.
    Da musst du stattdessen sagen:

    KUNDEN *kunde = malloc(sizeof(*kunde) * counter);
    /* und am Ende: */
    free(kunde);
    


  • fgets(string,STRINGSIZE,datei);
    strcpy(kunde[i].Kundennummer, strtok(string,","));
    strcpy(kunde[i].Vorname, strtok(string,","));
    strcpy(kunde[i].Nachname, strtok(string,","));
    strcpy(kunde[i].Adresse, strtok(string,","));
    strcpy(kunde[i].PLZ, strtok(string,","));
    strcpy(kunde[i].Ort, strtok(string,","));
    strcpy(kunde[i].Land, strtok(string,","));

    Irgendwie verwende ich fgets und strtok nicht richtig kann mir jemand auf die Sprünge helfen?

    Danke flamer und fricky für eure wertvollen Tips.

    lg Phil

    Edit:

    bin selbst drauf gekommen das der Counter anscheineind den Inhalt von datei löscht und deshalb nur schwachsinn rauskommt.

    Hab jetzt ein lauffähiges Programm das eine CSV in ein Struct array schreibt.

    Bräuchte nun hilfe beim hinzufügen von neuen Kunden.

    lg Phil

    So sieht es zur Zeit aus:

    #include<string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #define STRINGSIZE 100
    typedef struct
    {
    char Kundennummer[sizeof(int)];
    char Vorname[40];
    char Nachname[40];
    char Adresse[80];
    char PLZ[5];
    char Ort[20];
    char Land[20];
    } KUNDEN ;

    int main(int argc, char **argv) {

    int i,c,counter=0;
    char string[STRINGSIZE];
    FILE *datei;
    FILE *datei2;

    datei=fopen(argv[1], "r");
    datei2=fopen(argv[1], "r");

    while( (c=fgetc(datei)) != EOF)
    {
    if(c == '\n')
    counter++;
    }
    //printf("Counter = %d \n",counter);

    KUNDEN *kunde = malloc(sizeof(*kunde) * counter);
    for(i=0;i<counter;i++) {
    fgets(string,STRINGSIZE,datei2);
    int a=0;
    char *ptr;
    ptr = strtok(string, ",");
    while(ptr != NULL) {
    if(a==0)
    strcpy(&kunde[i].Kundennummer, ptr);
    if(a==1)
    strcpy(&kunde[i].Vorname, ptr);
    if(a==2)
    strcpy(&kunde[i].Nachname, ptr);
    if(a==3)
    strcpy(&kunde[i].Adresse, ptr);
    if(a==4)
    strcpy(&kunde[i].PLZ, ptr);
    if(a==5)
    strcpy(&kunde[i].Ort, ptr);
    if(a==6)
    strcpy(&kunde[i].Land, ptr);
    a++,
    ptr = strtok(NULL, ",");
    }
    fprintf(stdout,"Kundennummer von %s %s,\nWohnhaft in %s, %s %s %s \nlautet: %s\n\n",
    kunde[i].Vorname,kunde[i].Nachname,kunde[i].Adresse,kunde[i].PLZ,kunde[i].Ort,kunde[i].Land,kunde[i].Kundennummer);
    }
    free(kunde);
    return EXIT_SUCCESS;
    }



  • Irgendwie verwende ich fgets und strtok nicht richtig kann mir jemand auf die Sprünge helfen?

    Jetzt noch die Code-Tags - und alles wird gut:

    KUNDEN *kunde = malloc(sizeof(*kunde) * counter);
    for(i=0;i<counter;i++) {
        fgets(string,STRINGSIZE,datei2);
        int a=0;
        char *ptr;
        ptr = strtok(string, ",");
        while(ptr != NULL) {
            if(a==0)
                strcpy(&kunde[i].Kundennummer, ptr);
            if(a==1)
                strcpy(&kunde[i].Vorname, ptr);
            if(a==2)
                strcpy(&kunde[i].Nachname, ptr);
            if(a==3)
                strcpy(&kunde[i].Adresse, ptr);
            if(a==4)
                strcpy(&kunde[i].PLZ, ptr);
            if(a==5)
                strcpy(&kunde[i].Ort, ptr);
            if(a==6)
                strcpy(&kunde[i].Land, ptr);
            a++,  // <---------- besser am Ende ein ;
            ptr = strtok(NULL, ",");
        }
        fprintf(stdout,"Kundennummer von %s %s,\nWohnhaft in %s, %s %s %s \nlautet: %s\n\n",
        kunde[i].Vorname,kunde[i].Nachname,kunde[i].Adresse,kunde[i].PLZ,kunde[i].Ort,kunde[i].Land,kunde[i].Kundennummer);
    }
    free(kunde);
    

    Das sieht auf den ersten Blick sinnvoll aus.
    Wie äußert sich der Fehler bei strtok und fgets?



  • if(a==0)
        strcpy(&kunde.Kundennummer, ptr);
    if(a==1)
        strcpy(&kunde[i].Vorname, ptr);
    if(a==2)
        strcpy(&kunde[i].Nachname, ptr);
    

    Üblicherweise sagt man:

    if(a == 0)
        strcpy(&kunde[i].Kundennummer, ptr);
    else if(a == 1)
        strcpy(&kunde[i].Vorname, ptr);
    else if(a == 2)
        strcpy(&kunde[i].Nachname, ptr);
    

    Oder man nimmt einen [i]switch*.



  • Hallo flamer!

    Den Fehler hab ich beheben können, stimmt sieht sinnvoll aus.
    Könnte ich das auch in eine Funktion schreiben und das Array als Pointerarray in der Main schreiben lassen.

    Dann könnte ich das Ganze, mit leichten Modifikationen, nochmal für ein Artikel CSV verwenden in dem Artikel gespeichert sind bzw. werden sollen.

    Für die neuanlage von Kunden dachte ich mir das Kunden Array um ein Feld zu erweitern und den nächsten Kunden dann unter Counter+1 zu speichern.
    Dafür sollte ich realloc verwenden.
    Dann müsste ich die CSV mit dem Array überschreiben.

    Bin ich da auf einem halbwegs richtigen Weg?

    Die einzelnen Funktionen, also Kundenverwaltung und die Artikelverwaltung und die Rechnungslegung ich jetzt, da ich so gute Erfolge gemacht habe (dank eurer Hilfe) auch noch erledigen muss sollen jeweils als obj-file gespeichert werden und dann irgendwie zum ausführen oder compilieren vereint werden.
    Wenn ihr mir da auch noch behilflich sein könntet wäre ich sehr froh.

    lg Phil

    PS: was hat es mit dem i switch auf sich?



  • Bin ich da auf einem halbwegs richtigen Weg?

    Denke schon.

    jeweils als obj-file gespeichert werden

    Da packt man sie in eigene .c Dateien und macht ein Makefile, oder etc.
    Genaueres für deinen Compiler kannst du im Compiler-Forum nachfragen.
    Vereint werden sie dann beim Linken.



  • PS: was hat es mit dem i switch auf sich?

    Vertippt.
    Meinte http://en.wikipedia.org/wiki/Switch_statement


Log in to reply