Frage zum Auslesen von Textdateien



  • Hallo, ich probiere mich zur Zeit daran Daten aus einer Textdatei zu lesen. Die Daten innerhalb dieser Datei werden mit "," voneinander getrennt.
    Beispiel:

    1,2,32,4,55,68,7,8,9,10

    Wie würdet ihr diese Daten nun mit C auslesen? Mein Versuch sah so aus:

    int readFile(char *outValues[])
    {
        FILE *inFile;
        inFile = fopen("testdaten.txt", "rt");
    
        int count;
    
        for(count = 0; count <= 9; count++)
        {
            // speicher fuer das einzulesende Zeichen reservieren
            outValues[count] = (char*)malloc(10);
    
            fgets(outValues[count], 3, inFile);
            if(fgetc(inFile)==',') continue;
        }
        fclose(inFile);
        getchar();
        return 0;
    }
    

    1. Die Bedingung "count <= 0" finde ich übel und ich sollte sie lieber mit etwas dynamischen tauschen. Aber überseht das einfach (bitte). 😉
    2. Ich gehe davon aus, dass ein gefundener String maximal 10 Zeichen lang sein kann.

    outValues[count] = (char*)malloc(10);
    

    Kann man das eleganter lösen? Weil was ist wenn ein Wert mal mehr Zeichen als 10 enthält?
    Aber nun zu meinem Hauptproblem: Ich lese mit fgets() jeweils 3 Zeichen ein. Das ist doof. Ich weiß ja wieder nicht wie lang ein Wert ist. Ich bräuchte eine elegantere Lösung, die immer bis zum nächsten Trennzeichen liest und alle bisher gefundenen Zeichen(der String) zurück gibt.

    Wie würdet ihr das machen?
    MfG
    wax



  • Erstmal - wie ist eigentlich "outvalues" definiert?

    Zweitens: Textdaten könntest du z.B. über fscanf() einlesen (dabei kannst du sie gleich als Zahl interpretieren lassen).

    Drittens: Wenn du die Größe variabel gestalten willst, kannst du sie doch am Anfang der Datei speichern und vor den Nutzdaten auslesen. Alternativ verwendest du eine Endemarke für deine Nutzdaten und lässt den Speicher mit realloc() mitwachsen.



  • Hi,

    outValues ist folgendermaßen definiert:

    char *outValues[10];
    

    Wie meinst Du das mit dem realloc() ?

    MfG
    wax



  • realloc ist doch laaaaaahm



  • bonus textfile schrieb:

    realloc ist doch laaaaaahm

    Hast du eine schnellere Möglichkeit? (außerdem habe ich nie behauptet, daß du für jedes neu hinzukommende Element realloc() aufrufen solltest - wenn du den Speicher blockweise vergrößerst, macht sich das schon bemerkbar)

    @wax: Wenn du die Daten als Zahl weiterverwerten willst, dann lies sie besser gleich als Zahl ein 😉



  • bonus textfile schrieb:

    realloc ist doch laaaaaahm

    wenn realloc deiner meinung nach lahm ist, so poste wenigstens ein alternative.
    hier zählt code, und nicht irgendeine abgedroschene meinung.



  • Danke erstmal für eure Antworten.

    Ich habe immer noch ein verständnis Problem mit fscanf().
    Stellen wir uns mal vor, in einer Textdatei stehen Werte(s.o.):

    4,3,6,7

    Ich dachte mir nun, dass ich mit

    fscanf(filePointer, "%d", &tempInt)
    

    die erste Zahl(4) auslesen könnte. Dem war leider nicht so, da mein Programm abstürzt. 🙂
    Muss ich fscanf einfach nur besser einsetzen oder wie könnte ich die Formatangabe so ändern, dass es klappt? Vielleicht irgendwas nach dem Motto: Falls das nächste Zeichen ein ',' ist --> nicht lesen. 🙂

    MfG
    wax



  • bist du sicher, das filePointer gültig ist ?



  • filePointer hab ich nur meinen Zeiger auf den Dateipuffer genannt.

    FILE *filePointer;
    

    MfG
    wax



  • ja, ich meine mit gültig ja auch ob fopen erfolgreich war.

    FILE *fp = fopen("test.txt", "r"); 
        if ( NULL == fp ) // zeiger gültig ?
        {
           puts("sorry no bonus!") exit(1); // nein !!
        }
    	while ( ! feof(fp) ) // ja !
    	{
    		c = fgetc(fp);
    		if ( c == ',' || (c>=0 && c<=9) )
    		{
    			if(fscanf(fp, "%d", &i ))
    				printf("%d\n", i );
    		}
    	}
    
    	fclose(fp);
    

    🙂



  • sorry, das war ein bisschen zu schlurig. hier ne verbesserung:

    while ( ! feof(fp) )
    	{
    		c = fgetc(fp);
    		if ( c == ',' || (c>='0' && c<='9') )
    		{
    			if (c>='0' && c<='9') 
    			{
    				ungetc(c,fp); 
    			}
    			if(fscanf(fp, "%d", &i ))	printf("%d\n", i );
    		}
    	}
    


  • Hi bonus snippet correction,

    danke für deine Antwort. So wie sie da steht, funktioniert das aber nur mit einzelnen Ziffern, oder?

    MfG
    wax



  • wax schrieb:

    Hi bonus snippet correction,

    danke für deine Antwort. So wie sie da steht, funktioniert das aber nur mit einzelnen Ziffern, oder?

    MfG
    wax

    nöööööööööö



  • ok, ich habe Probleme mit dem ungetc().
    Wenn das Programm nun weiß, dass es sich um eine Ziffer handelt, wird die Zahl zurück in den uffer gelegt. Aber an welche Stelle?

    MfG
    wax



  • ganz vorne - mit dem Ergebnis, daß die nächste Eingabefunktion als erstes das zurückgeschriebene Zeichen erhält.



  • Sorry falls ich nerve ;-),

    wenn z.B. der erste Wert in der Datei eine "123" ist. Dann wird die gefundene "1" im ersten Durchlauf ja zurück in den Puffer gesteckt.
    Sollte dann der nächste Aufruf von fscanf() nicht NUR die "1" lesen. Weil es funktioniert, dass die "123" gelesen wird, wobei ich mir vorstelle, dass eigentlich nur eine "1" im Puffer steht.

    Ich glaube ich stelle mir den Puffer falsch vor. Habt ihr vielleicht irgendeine Seite im Internet, auf der das Ganze "verbildlicht" dargestellt wird?

    MfG
    wax



  • ungetc packt das gelesene zeichen sozusagen wieder zurück, wo es herkommt.
    denn sonst würde z.b. von scanf anstatt 123 nur 23 eingelesen werden.
    statt 12 würde nur 2 eingelesen und eine einzelne ziffer würde übersprungen.

    stell dir doch den stream wie eine char arrray vor. bei fgetc wird der array-index um eins erhöht, bei ungetc wird der index um eins vermindert.



  • Danke! So werde ich es nun sehen. 🙂



  • wax schrieb:

    Sollte dann der nächste Aufruf von fscanf() nicht NUR die "1" lesen.

    Wieso sollte es? Der rest der Eingabe "23" wurde vom getc() nicht angefasst und steht deshalb immer noch im Eingabepuffer.


Anmelden zum Antworten