Programm über Kommandozeile aufrufen



  • Hallo,

    ich soll als Übung ein Programm schreiben, das über die Kommandozeile mittels append datei1 datei2 ausgeführt wird.

    Funktionsweise:
    -Programm soll den Inhalt aus datei1 an datei2 anhängen. Dateinamen dürfen nur durch die Kommandozeile übergeben werden.
    -Wird das Programm nur mit einem Dateinamen aufgerufen, dann soll eine datei2 erzeugt werden, deren Inhalt identisch ist zu der von der ersten Datei.
    -Falsche Anzahl an Argumenten -> Fehlermeldung und Erklärung wie man das Programm nutzt.

    Code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    //kopiert Inhalt von einer Datei in eine andere
    void file_copy(char *file_1, char *file_2) {
        FILE *pf, *pf2;
    
        pf = fopen(file_1, "r");
        pf2 = fopen(file_2, "w");
        if (pf == NULL || pf2 == NULL) {
            printf("File not found!\n");
            return;
        }
        char c;
        while(1) {
            if(feof(pf)) {
                 break;
            }
            c = getc(pf);
            putc(c, pf2);
        }
        fclose(pf);
        fclose(pf2);
    }
    
    //hänge Inhalt von einer Datei an eine andere Datei hinten an
    void file_append(char *file_1, char *file_2) {
        FILE *pf, *pf2;
    
        pf = fopen(file_1, "r");
        pf2 = fopen(file_2, "a");
        if (pf == NULL || pf2 == NULL) {
            printf("File not found!\n");
            return;
        }
        char c;
        while(1) {
            if(feof(pf)) {
                 break;
            }
            c = getc(pf);
            putc(c, pf2);
        }
        fclose(pf);
        fclose(pf2);
    }
    
    int main(int argc, char* argv[]){
    	if(argc > 4 || argc < 3 ){
    		printf("Incorrect amount of arguments!\ngcc dateiname.c append datei1 datei2\n");
    	}
    	if(argc == 3 && !(strcmp(argv[2], "append"))){
    		char* datei2 = "/users3/s-user3/Desktop/datei2.txt";
    		file_copy(argv[3], datei2);
    	}
    	if(argc == 4 && !(strcmp(argv[2], "append"))){
    		file_append(argv[3], argv[4]);
    	}
    
    	return 0;
    }
    

    1. Ich weiß, man hätte dies am Ende mit einer switch-case Anweisung machen können. Ist mir in dem Moment nicht eingefallen.

    Problem:
    -Immer wenn ich das im Terminal eingebe, kommt die Meldung append Verzeichnis nicht gefunden. Wie behebe ich das?

    Fragen:
    1. Auf den Folien von unserem Prof. wird das immer mit gcc dateiname.c append datei1 datei2 aufgerufen. Kann man das auch so machen, dass man nur mit append datei1 datei2 dies ausführt?
    2. Muss man das immer im Terminal ausführen oder kann man das auch in Eclipse machen das man die verschiedenen Fälle durchprobiert?

    thx
    mfg werdas34



  • Ein paar Anmerkungen. Du musst das Programm so kompilieren und ausführen:

    gcc -Wall -Wextra -o append dateiname.c
    ./append datei1 datei2
    

    In der gcc-Zeile: ich empfehle dir dringendst, mindestens mit -Wall und -Wextra Warnungen anzuschalten. Kompiliere NIE ohne Warnungen. Der Kompiler kann dir damit oft schon wertvollte Tipps geben. Mit dem -o gibst du den Dateinamen der zu erzeugenden Datei an (unter Windows würdest du -o append.exe schreiben). Gibst du keinen Namen an, so heißt die Datei a.out oder a.exe.

    In der zweiten Zeile führst du das Programm dann aus, wenn alles gut war.

    In Eclipse wird man das sicher auch irgendwo einstellen können.

    Zu deinem Programm:
    1. append und copy sind doch schon einmal sehr ähnlich. Wenn du eine Funktion mit 2 FILE-Pointern hättest, könntest du hier für beide Operationen denselben Code verwenden. Lediglich das Öffnen der Ausgabedatei wäre im append- und copy-Fall unterschiedlich.

    2. Die eof-Behandlung macht man besser anders. Nämlich indem man den Status nach einem Leseversuch abfragt.

    Also z.B. so:

    while (1) {
      int c = fgetc(file_pointer);
      if (c == EOF) break;
      // schreibe c in Zieldatei
    }
    

    Das könnte man natürlich auch etwa so abkürzen:

    int c;
    while ((c = fgetc(fp)) != EOF) {
      ...
    }
    

    Und noch eine dritte Bemerkung: nutze const, wenn möglich.

    Und dann noch was wichtiges:
    Wenn argc = 4, darfst du dann auf argv[4] zugreifen? Denk mal darüber nach! Oder lass dir als erstes mal ausgeben, welche Werte in den verschiedenen argv-Strings enthalten sind. Oder mach ein printf("Hänge Datei %s and Datei %s an", ...) oder so ähnlich. Dann pass dein Programm entsprechend an.



  • werdas34 schrieb:

    1. Auf den Folien von unserem Prof. wird das immer mit gcc dateiname.c append datei1 datei2 aufgerufen.

    Dann ist die Folie falsch, oder du hast sie falsch verstanden.
    Mit gcc wird der Compiler aufgerufen. Die Angaben danach sind die Argumente dafür. Z.b die Dateien, die übersetzt werden sollen oder auch der Name vom fertigen Programm.

    Der gcc versucht also die Datei oder das Verzeichnis append zu finden.

    werdas34 schrieb:

    Kann man das auch so machen, dass man nur mit append datei1 datei2 dies ausführt?

    So soll es sein.
    Das funktioniert aber nur, wenn dein Programm append auch richtig erstellt wurde.
    Deine Argumente (argv[]) sind falsch nummeriert.

    werdas34 schrieb:

    2. Muss man das immer im Terminal ausführen

    Nun, es ist ein Konsolenprogramm.

    werdas34 schrieb:

    oder kann man das auch in Eclipse machen das man die verschiedenen Fälle durchprobiert?

    Meist kann man in einer die Paramter nur fest vorgeben. Ich kenne Eclipse aber nicht.

    Deine Funktionen unterscheiden sich nur in einer Stelle. Und die ist bei den Vorgaben noch nicht einmal entscheidend.
    Lies dir mal den letzten Satz beim Mode "a" durch: http://www.cplusplus.com/reference/cstdio/fopen/

    Zudem verwendest du das feof() falsch. Das kannst du erst nach einer Operation auf der Datei anwenden.
    Ein char ist auch nicht der richtige Typ für den Rückgabewert für getc .

    int c; // int c, nicht char c.
    while ((c = getc(pf)) != EOF) // pf ist ein schlechter Variablenname
    { 
      putc(c, pf2);               // pf2 ist ein schlechter Variablenname
    };
    


  • Danke euch beiden.
    Habe jetzt eure Sachen umgesetzt.

    Jetzt kann ich es nicht testen, da ein Error auftaucht:

    char* datei2 = "/users3/s-user3/Desktop/datei2.txt";
    

    Dort kommt: a label can only be a part of a statement and a declaration is not a statement

    Ich habe nicht viel Erfahrung mit C, deswegen bringt mich das ziemlich aus der Bahn.

    Kann mir vielleicht einer von euch sagen woran es liegt?



  • Das ist nicht die Fehlerzeile - du hast irgendwo einen Doppelpunkt ':' statt einem Semikolon ';' benutzt.



  • Wie sieht denn die Zeile darüber aus? (besser Zeilen)



  • Hier die Funktion:

    int main(int argc, char* argv[]) {
    
    	if (!(strcmp(argv[2], "append"))) {
    		switch (argc) {
    		case 3:
    		    char* datei2 = "/users3/s-user3/Desktop/datei2.txt";
    			file_copy(argv[3], datei2);
    			break;
    		case 4:
    			file_append(argv[3], argv[4]);
    			break;
    		default:
    			printf("Incorrect amount of arguments!\ngcc FILE.c append datei1 datei2\n");
    		}
    	} else {
    		printf("Incorrect amount of arguments!\ngcc FILE.c append datei1 datei2\n");
    		}
    	return 0;
    }
    


  • Schreib

    case 3: ; // leere Anweisung
    

    Du kannst den Dateinamen auich gleich im Funktionsaufruf schreiben)



  • Variablendeklarationen müssen in Standard-C (89) immer als erstes in einem Block stehen, daher fehlen dort geschweifte Klammern:

    case 3:
    {
        char* datei2 = "/users3/s-user3/Desktop/datei2.txt";
        file_copy(argv[3], datei2);
        break;
    }
    

    Du hast aber, wie von DirkB schon geschrieben, die Aufgabenstellung wohl falsch verstanden.
    Dein Programm soll append heißen und nur genau 2 Parameter entgegennehmen:

    append datei1 datei2
    


  • werdas34 schrieb:

    -Wird das Programm nur mit einem Dateinamen aufgerufen, dann soll eine datei2 erzeugt werden, deren Inhalt identisch ist zu der von der ersten Datei.

    Also ein oder zwei Argumente. argc darf demnach nur 2 oder 3 sein. In argv[0] steht dann der Programmname. Durchaus auch mit Pfad. argv[0] kann auch leer sein


Log in to reply