Bestimmte Spalten einer eingelesenen Datei ausgeben



  • Hallo,

    ich habe folgendes Programm: In einer Datei habe ich eine Tabelle mit Zahlenkolonnen, die in zehn Spalten gelistet sind. Diese Datei möchte ich einlesen und dann in eine andere Datei nur bestimmte, vorher ausgesuchte Spalten ausgeben. Also, z.B. soll der Programmaufruf ./sortspalt Quelle.dat 2 5 7 mir in der Output-Datei die Spalten 2, 5 und 7 der Tabelle Quelle.dat reinschreiben. Soweit die Aufgabe.
    Mein Konzept ist Folgendes:
    [] Datei öffnen
    [
    ] Anzahl der Zeilen lesen
    [] Zahlenkolonnen einlesen und in eine Matrix schreiben
    [
    ] Gewünschte Spalten in die Ausgabedatei schreiben.

    Ich habe nun bisher folgenden Code gebastelt, der die ersten drei Punkte wie gewünscht ausführt:

    #include<stdio.h>
    #include<stdlib.h>
    
    int i, j;
    FILE *input, *output;
    
    int main(int argc, char **argv) 
    
      {
        // Input-Datei öffnen
        input = fopen(argv[1], "r");
    
        // Variablen zur Dateneinlese bereitstellen
        int nRet;
        size_t *t = malloc(0);
        char **ptr = (char **)malloc(sizeof(char*));
        *ptr = NULL;
    
        // Zeilen zählen
        i=0;
        while( nRet=getline(ptr,t,input)>0 )           
          {
           i++;
          }
    
        fseek(input,0,0); // Dateizeiger an den Dateianfang
        float mat[i][10]; // Matrix zur Dateieinlese
    
        // Output-Datei öffnen
        output = fopen("Tabelle_out.dat", "w+");
    
        // Daten einlesen und formatiert in die Output-Datei schreiben
        j=0;
        while( nRet=getline(ptr,t,input)>0 )
          {
           sscanf(*ptr, "%f %f %f %f %f %f %f %f %f %f", &mat[j][0], &mat[j][1], &mat[j][2], &mat[j][3], &mat[j][4], &mat[j][5], &mat[j][6], &mat[j][7], &mat[j][8], &mat[j][9]);
           fprintf(output, "\n%f\t%f", mat[j][3], mat[j][5]);  // Diese Zeile soll variabel gestaltet werden!
           j++;
          }
    
        // Geöffnete Dateien schließen 
        fclose(output);
        fclose(input);
    
        return 0;
      }
    

    Der letzte Aufgabenteil bereitet mir jedoch Schwierigkeiten. Es geht um die fprintf -Zeile: Natürlich könnte ich jetzt für jede erdenkliche Zahlenkombination beim Programmaufruf mit if-Schleifen entsprechende fprintf-Befehle ins Programm reinwurschteln. Mit ein bisschen Kombinatorik wird leicht klar: Das sind 10! (= 3628000) Möglichkeiten, also nicht des Pudels Kern...
    Wie kann ich es also geschickt schaffen, dass die Argumente des fprintf -Befehls so eingefügt werden, wie es der Befehlsaufruf vorgibt?

    Vielen Dank für jede Hilfe oder jeden Hinweis!

    P.S.: Bitte keine Diskussion über die Funktion von malloc(0) - bei mir funktioniert das Programm nur mit dem Code, den ich oben gepostet habe



  • Oli90x schrieb:

    P.S.: Bitte keine Diskussion über die Funktion von malloc(0) - bei mir funktioniert das Programm nur mit dem Code, den ich oben gepostet habe

    und was passiert wenn du 'malloc(0)' weglässt?
    🙂



  • P.S.: Bitte keine Diskussion über die Funktion von malloc(0) - bei mir funktioniert das Programm nur mit dem Code, den ich oben gepostet habe

    Wird sich aber kaum vermeiden lassen. Ich habe das erst vorige Woche erforscht, und festgestellt, dass man bei einigen Compilern scheinbar wirklich ein free() machen muss, wenn malloc(0) nicht NULL zurückgibt. Lass das Ding mal den ganzen Tag über immer und immer wieder laufen, und schau, ob dann noch Speicher frei ist. Wenn ja, liegt's dann wohl daran, dass dein Compiler auf dich auspasst. Aber ANSI (in its wisdom) mag das nicht.

    Ontopic: du willst gar nichts sortieren ( sortspalt klingt danach)? Dann würde es doch einfach reichen, die paar Spalten-Nummern in eine Liste einzutragen. Dann zeilenweise über die Eingabe iterieren, als Token-Liste auffassen, und für jede Zeile die Nummern-Liste durchgehen, wobei du die Nummer als Index in die Token-Liste verwenden könntest.

    Dann bräuchtest du freilich gar nicht die ganze Datei auf einmal einlesen. Vielleicht hab ich da was falsch verstanden.



  • PS: Die Anzahl der malloc()-Aufrufe in deinem Programm ist die Anzahl der Zeilen in der Eingabedatei plus 1. Die Anzahl der free()-Aufrufe ist -- 0. Da kann was nicht stimmen.



  • Die Anzahl der malloc()-Aufrufe in deinem Programm ist die Anzahl der Zeilen in der Eingabedatei plus 1.

    Was nur in meinem Kopf vorgeht? 😕
    Die ist natürlich genau 2. Dann sind's aber immer noch 2 free()'s zu wenig.



  • Probier es mal so.
    In der for-Schleife wird die Anzahl der Kommandozeilen-Parameter (ohne Programmname und Dateiname) abgearbeitet und das Eingegebene Zeichen mittels atoi in ein Integer umgewandelt.
    Damit kann wird dann der entsprechende Wert aus dem Array in die Datei geschrieben.

    Du solltest natürlich noch Überprüfen, ob die Kommandozeilen-Parameter nach dem Dateinamen auch wirklich nur noch Zahlen sind.

    while( nRet=getline(ptr,t,input)>0 )
          {
           sscanf(*ptr, "%f %f %f %f %f %f %f %f %f %f", &mat[j][0], &mat[j][1], &mat[j][2], &mat[j][3], &mat[j][4], &mat[j][5], &mat[j][6], &mat[j][7], &mat[j][8], &mat[j][9]);
    
    		int colums;
    		for (colums = 2; colums < argc; colums++)
    		{
    			int column = atoi(argv[colums]);
    			fprintf(output, "%f\t", mat[j][column-1]);
    		}
    		fprintf(output, "\n");
    
           j++;
          }
    

    Viele Grüße
    Firutin



  • wieso benutzen neuerdings so viele c-anfänger die nicht standard getline funktion, irgendwo ein nest?
    😕



  • while( nRet=getline(ptr,t,input)>0 )
    

    ist auch so 'ne Sache ... Die Zuweisung "nRet=getline(ptr,t,input)" dürfte ja immer klappen 🕶



  • ;fricky schrieb:

    Oli90x schrieb:

    P.S.: Bitte keine Diskussion über die Funktion von malloc(0) - bei mir funktioniert das Programm nur mit dem Code, den ich oben gepostet habe

    und was passiert wenn du 'malloc(0)' weglässt?
    🙂

    Also, ich kompiliere in der Kommandozeile per gcc. Das funktioniert problemlos. Wenn ich das Programm dann aber auf eine Datei loslasse, bekomme ich als Fehlermeldung "Speicherzugriffsfehler" zurück.

    µngbd schrieb:

    Wird sich aber kaum vermeiden lassen. Ich habe das erst vorige Woche erforscht, und festgestellt, dass man bei einigen Compilern scheinbar wirklich ein free() machen muss, wenn malloc(0) nicht NULL zurückgibt. Lass das Ding mal den ganzen Tag über immer und immer wieder laufen, und schau, ob dann noch Speicher frei ist. Wenn ja, liegt's dann wohl daran, dass dein Compiler auf dich auspasst. Aber ANSI (in its wisdom) mag das nicht.

    Wegen des oben beschriebenen Fehlers: Hättest Du denn einen konkreten Vorschlag, wie man den Code ohne malloc(0) schreiben könnte?

    µngbd schrieb:

    Ontopic: du willst gar nichts sortieren ( sortspalt klingt danach)? Dann würde es doch einfach reichen, die paar Spalten-Nummern in eine Liste einzutragen. Dann zeilenweise über die Eingabe iterieren, als Token-Liste auffassen, und für jede Zeile die Nummern-Liste durchgehen, wobei du die Nummer als Index in die Token-Liste verwenden könntest.

    😃 Du hast mich erwischt! ^^ In Wahrheit heißt das Programm "File_edit", da es noch ein bisschen mehr macht, als nur Tabellen zu extrahieren und sortieren. Ich hätte es hier im Forum vielleicht als extract_spalt_sort benennen sollen. War mir dann aber doch etwas zu lang... 🙂

    firutin schrieb:

    Probier es mal so.
    In der for-Schleife wird die Anzahl der Kommandozeilen-Parameter (ohne Programmname und Dateiname) abgearbeitet und das Eingegebene Zeichen mittels atoi in ein Integer umgewandelt.
    Damit kann wird dann der entsprechende Wert aus dem Array in die Datei geschrieben.

    Danke, firutin! Genau das habe ich gesucht... Ich habe gestern auch schon mit argc , argv[] und einer for-Schleife herumexperimentiert. Mein Fehler: Ich wollte Spalte für Spalte in die Datei schreiben - und ich kam nicht auf die Idee, einfach Zeile für Zeile reinzuschreiben. AUTSCH! 🙄



  • Wegen des oben beschriebenen Fehlers: Hättest Du denn einen konkreten Vorschlag, wie man den Code ohne malloc(0) schreiben könnte?

    Lass es weg und schreib in Zeile 44 free(ptr) . Wer weiß, vielleicht hilft das. Später mehr.



  • µngbd schrieb:

    Wegen des oben beschriebenen Fehlers: Hättest Du denn einen konkreten Vorschlag, wie man den Code ohne malloc(0) schreiben könnte?

    Lass es weg und schreib in Zeile 44 free(ptr) . Wer weiß, vielleicht hilft das. Später mehr.

    Ich muss Dich leider enttäuschen - der Speicherzugriffsfehler bleibt trotzdem... 😞


Anmelden zum Antworten