Probleme mit fscanf und CSV



  • Hallo Leute,
    zwar schon einiges gefunden zu diesem Thema, und nun schon einige Zeit "herumgepfuscht", aber es hilft trotz allem nichts:

    Kann mir jemand sagen wo das Problem liegt?^^

    while((fscanf(file,"%[^';'];%[^';'];%d;%[^';'];%d;%s\n",
                      p[i].vorname,p[i].nachname,&p[i].plz,p[i].wohnort,p[i].strasse,&p[i].hausnummer,p[i].telefonnr)) != EOF ){
            printf("%s\n",p[i].nachname);
    
            if(strcmp(p[i].vorname, vorname) == 0 && strcmp(p[i].nachname,nachname) == 0){
                printf("%s;%s;%d;%s;%s;%d;%s\n",p[i].vorname,p[i].nachname,p[i].plz,p[i].wohnort,p[i].strasse,p[i].hausnummer,p[i].telefonnr);
            }
            else{
                printf("\nPerson nicht gefunden!");
            }
            i++;
        }
    

    Die CSV - Datei ist wie folgt aufgebaut: Vorname;Nachname;PLZ;WOHNORT;STRASSE;HAUSNUMMER;TELEFONNUMMER

    Als Ausgabe erhalte ich:

    Nachname
    Person nicht gefunden!Wohnort
    Person nicht gefunden!Hausnummer
    ...
    und das obwohl nur der Nachname ausgegeben werden sollte

    lg



  • Was sollen denn die ' im Formatstring.
    Und eine PLZ ist keine Ganzzahl.


  • Mod

    DirkB schrieb:

    Und eine PLZ ist keine Ganzzahl.

    Hausnummern auch nicht.



  • naja mein struct ist aber so aufgebaut:

    #define MAX 50

    struct person{
    char vorname[MAX];
    char nachname[MAX];
    int plz;
    char wohnort[MAX];
    char strasse[MAX];
    int hausnummer;
    char telefonnr[MAX];
    };

    edit: okay strukut wurde jetzt alles auf char geändert, die fscanf auf:
    while((fscanf(file,"%[;];%[;];%[;];%[;];%[^;];%s\n",

    jetzt funktioniert es, doch warum? darf ich in der structur nicht sowohl int als auch char verwenden? beim abspeichern hats ja auch funktioniert,...



  • Owezahra schrieb:

    naja mein struct ist aber so aufgebaut:
    .....

    Falsches Design.



  • DirkB schrieb:

    Owezahra schrieb:

    naja mein struct ist aber so aufgebaut:
    .....

    Falsches Design.

    In wie weit falsches Design? Hab eben in meinen Lehrbuch nachgeschlagen und da werden ja auch verschiedene Typen in einem struct verwendet...



  • Owezahra schrieb:

    In wie weit falsches Design? Hab eben in meinen Lehrbuch nachgeschlagen und da werden ja auch verschiedene Typen in einem struct verwendet...

    Das bezog sich auf die Hausnummern und PLZ als int.

    Und man kann es auch gemischt einlesen wenn der Formatstring passt.

    Du solltest noch eine Längenbegrenzung bei fscanf angeben.



  • Hi

    Owezahra schrieb:

    Kann mir jemand sagen wo das Problem liegt?^^

    Jepp.
    Einfach ne Gegenüberstellung der Formatspecifier mit den Strukturmembern machen.
    (Die Hochkommata sind jetzt kein Thema.)

    char vorname[MAX]; %[^';'] 
    char nachname[MAX]; %[^';']
    int plz; %d						
    char wohnort[MAX]; %[^';']		
    char strasse[MAX]; %d			// passt nicht zum typ
    int hausnummer; %s			// dito
    char telefonnr[MAX];			// fehlt
    


  • Wärst du vllt. selbst drauf gekommen, hättest du mit dem Rückgabewert von fscanf das gemacht, wozu er da ist: benutzen! :p

    while ( i < MAX && ! feof ( fp ))
    {
    	if ( 7 != fscanf( fp, "%49[^;];%49[^;];%d;%49[^;];%49[^;];%d;%49s\n",
    			p[i].vorname, p[i].nachname, &p[i].plz, p[i].wohnort, p[i].strasse, &p[i].hausnummer, p[i].telefonnr ))
    	    puts ( "OHOH! Es konnten nicht alle Strukturmember gelesen werden!" );
    	else
    		i++;
    }
    


  • Ha! Stimmt vielen Dank, für diesen dummen Fehler könnte ich mir in den Hintern beissen -.- 😃

    Letztes Problem, ich gebe per

    printf("%s\n", p[i].vorname);

    Meinen Vornamen aus, sprich die CSV - Überschrift ( Vorname), als auch z.B. Hansi.

    Als ausgabe erhalte ich jedoch: Vorname, Plz, Strasse, Telefonnummer, Hansi...

    bei der scanf funktion: fscanf(file,"%[;];%[;];%d;%[;];%[;];%d;%s\n",

    jedenfalls vorab vielen Dank für deine Hilfe 😛



  • Ohne Code zu sehen, lässt sich das nur raten.
    Da kommst du bestimmt selbst drauf, bevor du den hier postest.
    Oder? Naja, mal sehen.



  • Schau mal in dein Eröffnungspost die Zeile:
    Die CSV - Datei ist wie folgt aufgebaut: ....
    Und vergleich die mit der Zeile aus dem letzten Post:
    Als ausgabe erhalte ich jedoch: ....



  • Ich möchte folgende "Lösung" zur Diskussion stellen. Sie ist nicht direkt zum Abtippen für die aktuelle Frage gedacht, weil sie

    - Keine Datei mit mehreren Datensätzen einliest (ich war zu faul dazu), sondern eine Präprozessor-Konstante benutzt, mit der ich einfach besser testen kann.
    - Ich mich immer ein wenig wundere, warum die neuen, sicheren Funktionen nicht eingesetzt werden.
    - Ich einfach noch mehr verschiedene Datentypen testen wollte. Für Verbund im Verbund (Datum) ist mir nichts besseres eingefallen.

    /*U0358_Einlesen : Definiert den Einstiegspunkt der Konsolenanwendung*/
    /* direktes Einlesen eines Verbundes*/
    
    #include <stdio.h>
    #include <stdlib.h> /*fuer: system*/
    //#include <string.h> /*fuer spaeter*/
    
    #ifdef __cplusplus
      #define KOMPILERMODUS "mit C++"
    #else
      #define KOMPILERMODUS "mit C"
    #endif
    #pragma message(KOMPILERMODUS)
    
    /*Hier einfach experimentieren*/
    #define EINGABETEXT "Hans567890123456789012345;Mustermann;10001;Berlin;m;01.12.2013" /*Pufferueberlauf in den Nachnamen*/
    //#define EINGABETEXT "Hans5678901234567890;Mustermann;10001;Berlin;m;01.12.2013"
    //#define SICHER
    
    struct sDatum {
      char strTag[2+1];
      char strMonat[2+1];
      char strJahr[4+1];
    };
    struct sPerson1 {
        char strVName[20+1];
        char strNName[30+1];
        long nPLZ;
        char strOrt[20+1];
        char cGeschlecht; /*bei char kein 'regulaerer' Ausdruck mit [] moeglich*/
        //char strGeschlecht[1+1]; /*stattdessen String denkbar*/
        struct sDatum oDatum; /*nur mit Hilfsvariable, da Eingabe 10 Zeichen, sDatum aber nur 8 Zeichen hat*/
      };
    
    int main(void) {
      struct sPerson1 P1={0};
      unsigned int nFeld;
      char strDatum[10+1];
      /*Beim Lesen aus Datei kommt noch \n im Format hinzu*/
    #ifdef SICHER
      if (6!=(nFeld=sscanf_s(EINGABETEXT,"%[^;];%[^;];%d;%[^;];%c;%s",P1.strVName,_countof(P1.strVName),P1.strNName,_countof(P1.strNName),&P1.nPLZ,P1.strOrt,_countof(P1.strOrt),&P1.cGeschlecht,sizeof(char),strDatum,_countof(strDatum)))) {
    #else
      if (6!=(nFeld=sscanf(EINGABETEXT,"%30[^;];%20[^;];%d;%20[^;];%c;%s",P1.strVName,P1.strNName,&P1.nPLZ,P1.strOrt,&P1.cGeschlecht,strDatum))) {
    #endif
        fprintf_s(stderr,"Fehler beim Einlesen im Feld %d\n",nFeld+1);
      } else {
        if (3!=sscanf_s(strDatum,"%[^.].%[^.].%s",P1.oDatum.strTag,_countof(P1.oDatum.strTag),P1.oDatum.strMonat,_countof(P1.oDatum.strMonat),P1.oDatum.strJahr,_countof(P1.oDatum.strJahr))) {
          fprintf_s(stderr,"Fehler im Datum");
        } else {
          fprintf_s(stdout,"'%s' '%s' '%d' '%s' '%c' '%s' '%s' '%s' '%s'\n\n",P1.strVName, P1.strNName, P1.nPLZ, P1.strOrt,P1.cGeschlecht,strDatum,P1.oDatum.strTag,P1.oDatum.strMonat,P1.oDatum.strJahr);
        }
      } /*if*/
      system("Pause");
      return 0;
    } /*main*/
    

    Ohne die sicheren Funktionen ergibt sich

    'Hans56789012345678901Mustermann' 'Mustermann' '10001' 'Berlin' 'm' '01.12.2013'
     '01' '12' '2013'
    
    Drücken Sie eine beliebige Taste . . .
    

    Man sieht sehr schön, wie das Abschlusszeichen überfahren wird und der Vorname länger als erlaubt ist.


Anmelden zum Antworten