C - csv-Datei auslesen

Schnelle objektorientierte, kompilierende Programmiersprache.
Benutzeravatar
stampuhh
Beiträge: 211
Registriert: Sa Nov 07, 2009 4:39 pm
Wohnort: Paderborn

Re: C - csv-Datei auslesen

Beitrag von stampuhh » Do Jan 21, 2010 4:24 pm

@dani93:
das werde ich mir dann auch mal vornehmen.

Aber zuerst hab ich gerade die andere Idee von Dirty Oerti durchgespielt und würde euch gerne fragen ob das so Sinn macht? Laufen tut es in meinem Testfall zwar aber man weiß ja nie ;)

Code: Alles auswählen

    int counter=0;
    char zeichen[1];
    char *string = NULL;

        string = (char *)malloc(strlen(zeichen)+1);
        while (fread(zeichen, sizeof(char), 1, file) == 1)
        {
            if(counter == 0)
            {
                strcpy(string, zeichen);
                counter = 1;
            }
            else
            {
                string = (char *)realloc(string, strlen(zeichen) + strlen(string) + 1);
                strcat( string, zeichen );
            }
        }
oder wäre es besser wenn ich am Anfang einmal einen String von fester Größe allociere und dann mit dem counter (oder kann man auch anders gucken) ob ich schon am Ende bin und neuen Speicher brauche?

edit: Ok. Debug funktioniert, Release funktioniert nicht...warum auch immer glibc detected oO

gruß stampuhh
NachDenkSeiten.de

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: C - csv-Datei auslesen

Beitrag von Dirty Oerti » Do Jan 21, 2010 4:42 pm

Je weniger oft du neuen Speicher anfordern musst, desto besser.
In diesem Sinn ist dani93s Lösung die Beste :)

Natürlich gegeben der Tatsache, dass die Datei nicht all zu groß ist ( mehrere GB oder so)
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
stampuhh
Beiträge: 211
Registriert: Sa Nov 07, 2009 4:39 pm
Wohnort: Paderborn

Re: C - csv-Datei auslesen

Beitrag von stampuhh » Do Jan 21, 2010 4:47 pm

Ne die Dateien sind nicht sehr groß :D
Mir geht es gerade auch eher nur ums Prinzip wie man so etwas machen könnte ;)

Jetzt hab ich mich der gerade geposteten Idee auch irgendwie eine Fehlermeldung

Code: Alles auswählen

glibc detected, realloc(): invalid next size 
und keine Ahnung warum, und warum das ganze nur beim Release auftritt und im Debug läuft alles supi.

Danis Lösung werd ich zusammenbasteln sobald die hier läuft :D

edit:
Und behoben

Code: Alles auswählen

string = (char *)realloc(string, strlen(zeichen) + strlen(string));
Die +1 aus der Zeile entfernt. Muss ich die hier nicht mehr anfügen weil ich zu Beginn schon eine +1 beim malloc hatte?

gruß stampuhh
NachDenkSeiten.de

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: C - csv-Datei auslesen

Beitrag von nufan » Do Jan 21, 2010 4:53 pm

stampuhh hat geschrieben:Jetzt hab ich mich der gerade geposteten Idee auch irgendwie eine Fehlermeldung

Code: Alles auswählen

glibc detected, realloc(): invalid next size 
und keine Ahnung warum, und warum das ganze nur beim Release auftritt und im Debug läuft alles supi.
Soweit ich das sehe beendest du deine Strings nicht korrekt. Die Standard-Funktionen (strlen, strcat etc.) erwarten ein \0 am Ende des Strings, was aber bei dir in beiden Fällen nicht zutrifft. Dadurch werden auch die Werte von strlen verfälscht, wodurch falsche Werte im realloc stehen.

Benutzeravatar
stampuhh
Beiträge: 211
Registriert: Sa Nov 07, 2009 4:39 pm
Wohnort: Paderborn

Re: C - csv-Datei auslesen

Beitrag von stampuhh » Do Jan 21, 2010 5:04 pm

Das könnte auch die Rätsels Lösung sein :D

Aber wie bekomme ich das dahin? Ich weiß ja nicht wie lang der String ist und wo ich das Nullbyte setzen muss :?:
string[x] = '\0', nur was ist x :P

gruß stampuhh
NachDenkSeiten.de

nufan
Wiki-Moderator
Beiträge: 2558
Registriert: Sa Jul 05, 2008 3:21 pm

Re: C - csv-Datei auslesen

Beitrag von nufan » Do Jan 21, 2010 5:13 pm

stampuhh hat geschrieben:Aber wie bekomme ich das dahin? Ich weiß ja nicht wie lang der String ist und wo ich das Nullbyte setzen muss :?:
string[x] = '\0', nur was ist x :P
Am besten zählst du die Anzahl der Zeichen, dann weißt du wo du schreiben musst:

Code: Alles auswählen

char zeichen;
char *string = NULL;
int numchars = 0;

while (fread (&zeichen, sizeof(char), 1, file) == 1)
{
  numchars++;            // neues Zeichen wurde aus der Datei gelesen -> Zähler erhöhen
  string = (char *) realloc (string, numchars + 1);   // neuen Speicher für String + \0 reservieren
  string[numchars - 1] = zeichen;    // altes \0 wird überschrieben
  string[numchars] = '\0';     // neues \0 wird gesetzt
}
Achtung: ungetestet ^^
Ich würde dir trotzdem empfehlen die Daten in einem Stück aus der Datei zu lesen.

Benutzeravatar
stampuhh
Beiträge: 211
Registriert: Sa Nov 07, 2009 4:39 pm
Wohnort: Paderborn

Re: C - csv-Datei auslesen

Beitrag von stampuhh » Do Jan 21, 2010 5:26 pm

Achtung: ungetestet ^^
Klappt trotzdem ;)

Das wäre dann die Variante mit dem Counter gewesen...eingebaut hatte ich ihn ja schon nur noch nicht wirklich in Verwendung. Aber anders kommt man wohl nicht an das letzte Byte.
Ich würde dir trotzdem empfehlen die Daten in einem Stück aus der Datei zu lesen.
Das klang kompliziert und wäre für heute der 4. Ansatz aber ich werde das trotzdem angehen :D

Danke!

edit: Kurze Frage noch zu der Methode: Also wäre es besser wenn ich das so mache und erst nen großes Stück allokiere?

Code: Alles auswählen

        string = (char *)malloc(BUF+1);

        if(string != NULL)
        while (fread(zeichen, sizeof(char), 1, file) == 1)
        {

            counter++;
            if(counter > BUF)
                string = (char *) realloc (string, counter + 1);
            if(string != NULL)
            {
                string[counter-1] = zeichen[0];
                string[counter] = '\0';
            }
            else
                break;
        }
gruß stampuhh
NachDenkSeiten.de

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: C - csv-Datei auslesen

Beitrag von Dirty Oerti » Do Jan 21, 2010 6:06 pm

Zu deiner Frage:
Ja, das wäre wohl sicher besser, denn dadurch sparst du dir ein paar mal das realloc.
Was du aber bedenken musst ist, dass evtl nicht dein ganzer Buffer voll mit ausgelesenen Buchstaben ist (weil z.B. die Datei zu Ende war).
Du hast also "im Hinteren" Teil Müll, und musst den erst "abschneiden", bevor du das letzte Stück an deinen "Ergebnisstring" anhängst.

Wenn du den Buffer wiederum immer weiter vergrößerst, näherst du dich ja automatisch Dani93s Methode an.
Ist dein Buffer kleiner als die Datei, dann musst du "unnötig" oft neuen Speicher anfordern.
Ist dein Buffer größer als die Datei, dann musst du am Ende Zeichen abschneiden und nicht benutzten Speicher freigeben.

-> Das Beste ist, wenn du genau so viel Speicher anforderst, wie du auch brauchst.
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
stampuhh
Beiträge: 211
Registriert: Sa Nov 07, 2009 4:39 pm
Wohnort: Paderborn

Re: C - csv-Datei auslesen

Beitrag von stampuhh » Do Jan 21, 2010 7:21 pm

Ja Dani93s Methode folgt noch ;)

Wollte nur die erst mal zum Laufen bringen, weil ich die gerade angefangen hatte bevor Dani93 gepostet hatte.

Also muss ich gegen Ende mir den Counter ansehen und wenn counter < buf noch mal ein realloc mit der "richtigen" Größe aufrufen um ihn zu verkleinern? Wenn ich das richtig im Tutorial grade gesehen habe müsste das so gehen.

gruß stampuhh
NachDenkSeiten.de

Benutzeravatar
stampuhh
Beiträge: 211
Registriert: Sa Nov 07, 2009 4:39 pm
Wohnort: Paderborn

Re: C - csv-Datei auslesen

Beitrag von stampuhh » Fr Jan 22, 2010 12:08 pm

So hier dann Dani93s Vorschlag ;)

Code: Alles auswählen

long int pos = fseek(file, 0, SEEK_END);
        if(pos != 0)
        {
            //Abbruch
        }

        pos = ftell(file);
        string = malloc ( pos + 1);

        if(string != NULL)
        {
            int start = fseek(file, 0, SEEK_SET);

            if(start != 0)
            {
                //Abbruch
            }

            start = fread(string, pos, 1, file);

            chomp(string); //Setzt das Nullbyte ans Ende und entfernt Zeilenumbruch

       }
        fclose(file);
Läuft mal wieder sowohl im Debug als auch im Release. Gefällt mir sehr gut so ;)
Hab ich das richtig umgesetzt oder gibt es noch Verbesserungen?

gruß stampuhh
NachDenkSeiten.de

Antworten