Unklarer Fehler



  • Liebe Community,

    ich bin Anfänger und schreibe ein kleines Programm in C++, will aber nur C-Funktionen verwenden, weil ich die lernen will. Dort gibt es eine Stelle, in der ein Zeichen (eine Zahl, aber sie wird wie ein String behandelt) in einer Datei gelöscht werden soll. Ich habe das so gelöst, dass ich die eine Datei ohne das zu löschende Zeichen in eine andere Datei schreibe, die ursprüngliche Datei lösche und die neue Datei umbenenne.
    Der Code sieht folgendermaßen aus:

    #include <stdio.h>
    ...
    void DatenLoeschen(){
            FILE *lesedatei;
            FILE *schreibedatei;
            char Eingabe[10];
            int marker = 0;
            
            lesedatei = fopen("daten.txt", "r");
            schreibedatei = fopen("$daten.txt", "w");
    
            printf("Welche Zahl wollen Sie löschen? ");
            scanf("%s", Eingabe);
            
            if(lesedatei == NULL){
                printf("Datei konnte nicht gelesen werden\n");
            }
            else {
                char zeile[10];
            	while(fgets(zeile, 10, lesedatei)){
            		if(strcmp(zeile, Eingabe)!=0){
            			fputs(zeile, schreibedatei);
            		}
            		else {
            			marker = 1;
            		}
            	}
            	if(marker==1){
                    printf("Löschung ausgeführt\n");
                }
                else{
            		printf("Diese Zahl kommt nicht vor\n");
            	}
            }
    		fclose(lesedatei);
    		fclose(schreibedatei);
    		remove("daten.txt");
    		rename("$daten.txt", "daten.txt");
    		Hauptmenue();
    }
    ...
    

    Der Code wird compiliert ohne Fehlermeldung. Wenn diese Funktion ausgeführt werden soll, fragt er auch nach der zu löschenden Zahl. Dann aber kommt immer die Meldung "Diese Zahl kommt nicht vor", und die Löschung wird nicht ausgeführt (bzw. Zieldatei ist genauso wie die Quelldatei).

    Was stimmt hier nicht?



  • Schau' Dir mal gaaaanz genau an was fgets() alles in den String packt: fgets()

    Ansonsten, wenn Du Feedback willst zeig mal kompletten Code. Du machst da ziemlich grausige Sachen.



  • @Bernhard sagte in Unklarer Fehler:

    ich bin Anfänger und schreibe ein kleines Programm in C++, will aber nur C-Funktionen verwenden, weil ich die lernen will.

    Dann schreib ein C-Programm. Es gibt Unterschiede

    Dort gibt es eine Stelle, in der ein Zeichen (eine Zahl, aber sie wird wie ein String behandelt) in einer Datei gelöscht werden soll.

    Wirklich nur ein Zeichen (das wäre eine Ziffer bei einer Zahl)?
    Oder ein Wort (aus mehreren Zeichen)?

    Bei deiner Lösung sollte die Datei aus Zeilen bestehen, die nicht länger als 7 Zeichen (7 Zeichen, \r\n und \0) sind.

    Ein fscanf wäre da besser zum einlesen.

    Und der Aufruf von Hauptmenue hat in der Funktion nichts zu suchen - auch in C++ nicht.



  • @Bernhard sagte in Unklarer Fehler:

            char zeile[10];
        	while(fgets(zeile, 10, lesedatei)){
        		if(strcmp(zeile, Eingabe)!=0){
        			fputs(zeile, schreibedatei);
        		}
    

    NUR wenn du genau 1 Zeichen löschen willst funktioniert fgetc statt fputs.

    int c;
    while( (c=fgetc(lesedatei))!=EOF )
    {
      if( c==*Eingabe ) ...
    ...
    fputc(c,schreibedatei);
    ...
    }
    

    Wenn es auch mehrere Zeichen sein sollen, wird es deutlich komplizierter;
    da dies aber dann die allgemeine Lösung wäre, ist es ziemlich sicher, dass dein Lehrer das gemeint hat.



  • Vielen Dank für die bisherigen Antworten.

    Ich hatte das falsch geschrieben - die Datei soll zeilenweise eingelesen werden (eine Zeile ist aber nie länger als ein paar Zeichen).

    Es war mir nicht bewusst, dass der Aufruf von Hauptmenue in der Funktion nichts zu suchen hat, danke für den Hinweis. Was für andere "grausige Sachen" mache ich denn?



  • @Bernhard sagte in Unklarer Fehler:

    Was für andere "grausige Sachen" mache ich denn?

    Bei scanf mit %s keine Längenbegrenzung.

    Keine Überprüfung, ob die Datei zum schreiben geöffnet werden konnte.

    Was soll jetzt gelöscht werden?
    Ein Zeichen oder ein Wort (mehrere Zeichen)?
    Besteht die ganze Zeile aus dem Wort?



  • @Bernhard sagte in Unklarer Fehler:

    Es war mir nicht bewusst, dass der Aufruf von Hauptmenue in der Funktion nichts zu suchen hat

    Eine Funktion macht die Aufgabe, nach der sie auch benannt wurde.
    Nicht mehr.

    In deinem Fall würde die Funktion aus dem Menü aufgerufen und kehrt dahin zurück, von wo sie aufgerufen wurde.

    Wenn du jetzt innerhalb der Funktion das Menü aufrufst entsteht eine Art Rekursion.



  • @Bernhard sagte in Unklarer Fehler:

    Was für andere "grausige Sachen" mache ich denn?

    Wie gesagt - poste vollständigen kompilierbaren Code dann bekommst Du eine erschlagendeöpfende Liste.

    Warum Dein Code nicht funktioniert? fgets() speichert - wenn Platz dafür ist - auch das die Zeile abschließende newline ('\n'). Wenn Du also nach einer Eingabe Hausnummer "42\0" suchst wirst Du nie fündig werden weil Du ständig mit "einezahl\n\0" (zB. "42\n\0") vergleichst. Entferne das von fgets() gespeicherte '\n' und es wird funktionieren:

    #include <iterator>  // std::size()
    #include <cstring>  // std::strlen(), std::strcmp()
    #include <cstdio>
    
    constexpr std::size_t max_line{ 20 };
    char const * const input_filename{ "daten.txt" };
    char const * const output_filename{ "$daten.txt" };
    
    void delete_line()
    {
        auto input_file{ std::fopen("daten.txt", "r") };
        if (!input_file) {
            std::fprintf(stderr, "Eingabedatei \"%s\" konnte nicht zum Lesen geoeffnet werden :(\n\n", input_filename);
            return;
        }
    
        auto output_file{ std::fopen("$daten.txt", "w") };
        if (!output_file)
        {
            std::fprintf(stderr, "Ausgabedatei \"%s\" konnte nicht zum Schreiben geoeffnet werden :(\n\n", output_filename);
            std::fclose(input_file);
            return;
        }
    
        std::printf("Welche Zahl wollen Sie loeschen? ");
        char line_to_find[max_line + 1];
        if (!fgets(line_to_find, static_cast<int>(std::size(line_to_find)), stdin)) {
            std::fputs("Input error :(\n\n", stderr);
            std::fclose(input_file);
            std::fclose(output_file);
            return;
        }
    
        auto line_to_find_length{ std::strlen(line_to_find) };
        if (line_to_find_length && line_to_find[line_to_find_length - 1] == '\n')
            line_to_find[line_to_find_length - 1] = '\0';
    
        char line[max_line + 1];
        while (fgets(line, static_cast<int>(std::size(line)), input_file)) {
            auto line_length{ std::strlen(line) };
            if (line_length && line[line_length - 1] == '\n')
                line[line_length - 1] = '\0';
            else fprintf(stderr, "Es waeren noch mehr Daten in der Zeile beginnend mit \"%s\" gewesen. Dein Programmdesign ist flawed.\n\n", line);
    
            if (std::strcmp(line, line_to_find))
                fprintf(output_file, "%s\n", line);
            else printf("\"%s\" wird nicht in die Ausgabedatei geschreieben.\n", line);
        }
        
        std::fclose(output_file);
        std::fclose(input_file);
    
        std::remove(input_filename);
        std::rename(output_filename, input_filename);
    }
    
    int main()
    {
        delete_line();
    }
    

    Aber:

    @DirkB sagte in Unklarer Fehler:

    Eine Funktion macht die Aufgabe, nach der sie auch benannt wurde.
    Nicht mehr.

    Siehe auch SRP.


Anmelden zum Antworten