bestimmte Zeile in Text Datei löschen



  • Hallo
    Ich möchte eine Zeile aus einer TXT Datei löschen die zb
    eine bestimmtes Wort enthält.

    Dabei sollen die restlichen zeilen nätürlich nachrücken, sodass keine Leerzeile entsteht.

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <conio.h>
    
    FILE *f; 
    char buffer[256];
    char test[50];
    static int count;
    //fpos_t fpos;
    
    int main(void)
    {
    f = fopen("t.txt","r+");
       if(f == NULL) {
          printf("Fehler beim Öffnen");
          return EXIT_FAILURE;
       }
    
    while (fgets(buffer,sizeof(buffer),f) !=0)
    	{
    		count++;
    	}
    
    	fseek(f,0,0);
    
    for (int i=0;i<=count;i++)
    	{
     fgets(buffer,sizeof(buffer),f);
    
    			if (strstr(buffer,"Frosch"))
    		{
    				fgetpos(f,&fpos);
    				printf("Text gefunden in Zeile %d\n",i+1);
    				break;
    			}
    
    		}
    
    	fclose(f);
    	system("pause");
    	return 0;
    	}
    

    So weit bin ich
    habe schon mit fseek und fg(s)etpos probiert->kein Erfolg

    vg Maxx175



  • Ich hab' Dir mal Deinen Code kommentiert:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    /*
    #include <conio.h>  nicht ANSI C...
    */
    
    FILE *f;
    char buffer[256];
    char test[50];
    static int count; // static? Weißt du, was du hier tust?
    // ^^ globale Variablen sind ... meist unnötig.
    
    int main( void )
    {
    	f = fopen("t.txt","r+");	// Variablen benennen!
    
    	if( f == NULL ) {
    
    		printf( "Fehler beim Öffnen" );
    		return EXIT_FAILURE;
    	}
    
    	while( fgets( buffer, sizeof( buffer ), f ) != 0 )
    	{
    		count++;
    	}
    	// du ließt immer wieder in den selben Speicher.
    	// Zuletzt steht die letzte Zeile drin.
    
    	fseek( f, 0, 0 );
    	// Der letzte Parameter muss einer aus SEEK_CUR, SEEK_END, SEEK_SET sein!
    
    	for( int i = 0; i <= count; i++ ) // <= Operator? (Wennschon?)
    	{
            fgets( buffer, sizeof( buffer ), f );
    		// Nochmal lesen??
    
    		if( strstr( buffer, "Frosch" ) )
    		{
    			fgetpos( f, &fpos );
    			printf("Text gefunden in Zeile %d\n", i + 1 );
    			// reiner Zufallstreffer.
    
    			break;
    		}
    	}
    
    	fclose( f );
    	system( "pause" );  // unschön
    	return 0;           // unnötig
    }
    

    Vielleicht teilst du das Gesamtproblem besser in Teile auf:

    • Datei Zeilenweise einlesen
    • Zu löschende Zeile suchen
    • Zeile (im Speicher) löschen
    • Datei zurückschreiben
    • fertig 😉

    so zB:

    #include <stdbool.h>	/* bool */
    #include <stddef.h>		/* size_t */
    #include <stdlib.h>
    #include <stdio.h>
    
    size_t count_lines( FILE *input_file ) {
    
    	long initial_position;
    	size_t num_lines = 1;
    	char ch = 0;
    
    	if( !input_file ) {
    
    		return 0;
    	}
    
    	initial_position = ftell( input_file );
    
    	while( ( ch = fgetc( input_file ) ) != EOF ) {
    
    		if( ch == '\n' ) {
    
    			++num_lines;
    		}
    	}
    
    	fseek( input_file, initial_position, SEEK_SET );
    
    	return num_lines;
    }
    
    char* get_line( FILE *input_file ) {
    
    	long initial_position = 0;
    	size_t length = 0;
    	char ch = 0, *buffer = 0;
    
    	if( !input_file ) {
    
    		return 0;
    	}
    
    	initial_position = ftell( input_file );
    
    	for( ch = fgetc( input_file ); ( ch != '\n' ) && ( ch != EOF ); ++length, ch = fgetc( input_file ) );
    
    	if( !length ) {
    
    		buffer = calloc( 1, 1 );
    		return buffer;
    	}
    
    	fseek( input_file, initial_position, SEEK_SET );
    	buffer = malloc( length + 2 );
    
    	if( !buffer ) {
    
    		return 0;
    	}
    
    	fgets( buffer, length + 1, input_file );
    	buffer[ length ] = 0;
    
    	// assume Windows-Like "LF+CR", so skip two characters:
    	fseek( input_file, 2, SEEK_CUR );
    
    	return buffer;
    }
    
    bool read_lines( char ***lines, size_t *num_lines, const char file_name[ ] ) {
    
    	FILE *input_file = fopen( file_name, "r" );
    	size_t current_line = 0;
    
    	if( !input_file ) {
    
    		return false;
    	}
    
    	*lines = malloc( ( *num_lines = count_lines( input_file ) ) * sizeof( char* ) );
    
    	if( !( *lines ) ) {
    
    		fclose( input_file );
    		return false;
    	}
    
    	for( ; current_line < *num_lines; ++current_line ) {
    
    		( *lines )[ current_line ] = get_line( input_file );
    	}
    
    	fclose( input_file );
    
    	return true;
    }
    
    void delete_line( char ***lines, size_t *num_lines, size_t line_to_delete ) {
    
    	size_t current_line = line_to_delete;
    
    	if( num_lines <= line_to_delete ) {
    
    		return;
    	}
    
    	free( ( *lines )[ line_to_delete ] );
    
    	for( ; current_line < ( *num_lines ) - 1; ++current_line ) {
    
    		( *lines )[ current_line ] = ( *lines )[ current_line + 1 ];
    	}
    
    	( *lines )[ --( *num_lines ) ] = 0;
    }
    
    bool write_lines( char **lines, size_t num_lines, const char file_name[ ] ) {
    
    	FILE *output_file = fopen( file_name, "w+" );
    	size_t i = 0;
    
    	if( !output_file ) {
    
    		return false;
    	}
    
    	for( ; i < num_lines; ++i ) {
    
    		fputs( lines[ i ], output_file );
    		fputc( '\r', output_file ); // windows...
    	}
    
    	fclose( output_file );
    
    	return true;
    }
    
    void free_lines( char **lines, size_t num_lines ) {
    
    	size_t i = 0;
    
    	for( ; i < num_lines; ++i ) {
    
    		free( lines[ i ] );
    	}
    
    	free( lines );
    }
    
    int main( void ) {
    
    	const char str_to_find[ ] = "another";
    	const char file_name[ ] = "test.txt";
    	char **lines = 0;
    	size_t num_lines = 0, i = 0;
    	bool found = false;
    
    	if( !read_lines( &lines, &num_lines, file_name ) ) {
    
    		fprintf( stderr, "File \"%s\" couldn't be opened!\n\n", file_name );
    		return EXIT_FAILURE;
    	}
    
    	for( ; i < num_lines; ++i ) {
    
    		if( strstr( lines[ i ], str_to_find ) ) {
    
    			printf( "\"%s\" found at line %u.\n", str_to_find, i + 1 );
    			found = true;
    			break;
    		}
    	}
    
    	if( found ) {
    
    		delete_line( &lines, &num_lines, i );
    
    		if( !write_lines( lines, num_lines, file_name ) ) {
    
    			fprintf( "\"%s\" couldn't be opened for writing!\n\n", file_name );
    			free_lines( lines, num_lines );
    			return EXIT_FAILURE;
    		}
    
    		printf( "\"%s\" written.\n\n", file_name );
    
    	} else {
    
    		printf( "\"%s\" wasn't found in \"%s\".\nFile unchanged.\n\n", str_to_find, file_name );
    	}
    
    	free_lines( lines, num_lines );
    }
    

    greetz, Swordfish



  • Und wenn deine read_lines den "Frosch" aufteilen?
    Dann steht der Frosch am Ende immer noch drin, ne.

    Guckst du hier:

    #define BUF 82
    char* rem = "Frosch";
    
    void filter( FILE* in, FILE* out )
    {
    	char* pstr = (rem+1);
    	char buf[BUF]= {*rem};
    	int i = 1;
    
    	while( *pstr && !feof(in) )
    	{
    		if ( ! (buf[i++] = fgetc(in)) == *pstr++)
    			break;
    	}
    	if ( *pstr ) fprintf(out, "%s", buf );
    }
    
    int main(int argc, char *argv[])
    {
    	FILE* in, *out;
    	int c;
    	in  = fopen("test.txt", "r");
    	out = fopen("test.tmp.txt", "w");
    
    	if  ( !in || !out ) return 1;
    
    	while( (c=fgetc(in)) != EOF )
    	{
    		if(c == *rem )	filter(in, out);
    		else fputc(c, out);
    	}
    	fclose(in);
    	fclose(out);
    
    	if ( remove("test.txt")) return 1;
    	if ( rename("test.tmp.txt", "test.txt")); return 1;
    
        return 0;
    }
    

    🙂



  • proggingmania schrieb:

    Und wenn deine read_lines den "Frosch" aufteilen?
    Dann steht der Frosch am Ende immer noch drin, ne.

    maxx175 schrieb:

    Ich möchte eine Zeile aus einer TXT Datei löschen die zb
    eine bestimmtes Wort enthält.

    Tja, ein "Fro\nsch" ist eben kein "Frosch" ... :p

    proggingmania schrieb:

    Guckst du hier:

    Guckst Du hier:

    #include <stddef.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    int main( void ) {
    
    	const char file_name[ ] = "test.txt"; const char str_to_find[ ] = "Frosch";
    	const char *find_pos = str_to_find; char *buffer = 0, *tmp, *nl = 0;
    	FILE *file = fopen( file_name, "r+" );
    	size_t buffer_size = 0; int ch;
    
    	if( !file ) return EXIT_FAILURE;
    
    	for( ch = fgetc( file ); ch != EOF; ch = fgetc( file ) ) {
    
    		nl = ch == '\r' ? buffer + buffer_size : nl;
    
    		if( ch == *find_pos && !find_pos[ 1 ] ) {
    
    			if( nl ) {
    
    				if( !( tmp = realloc( buffer, buffer_size = nl - buffer + 1 ) ) ) goto error_exit;
    				buffer = tmp;
    
    			} else {
    
    				free( buffer );
    				buffer = buffer_size = 0;
    			}
    
    			find_pos = str_to_find;
    
    			while( ( ch = fgetc( file ) ) != EOF && ch != '\r' );
    			continue;
    
    		} else if( ch == *find_pos ) ++find_pos;
    		else find_pos = str_to_find;
    
    		if( !( tmp = realloc( buffer, ++buffer_size ) ) ) goto error_exit;
    		( buffer = tmp )[ buffer_size - 1 ] = ch;
    	}
    
    	if( ( file = freopen( file_name, "w", file ) ) ) fwrite( buffer, buffer_size, 1, file );
    
    error_exit:
    	free( buffer );
    	fclose( file );
    }
    

    Wird das jetzt ein "Ich schreib' den kürzeren, unlesbareren"-Contest? 😃

    greetz, Swordfish



  • Danke erstmals für die Posts
    Aber keiner der Codes hat das gemacht was ich will:

    Geht das nicht ohne dass ich alle chars einzeln einlese.

    Also:

    TXT sieht so aus:

    blablablabla
    juppijuppujuppi
    bla:Frosch
    sowiso sowiso
    

    suche nach "Frosch"-> fgets; AAHHH -> gefunden in Zeile 2 (3)

    Und jetzt lösche komplette Zeile "bla:Frosch" ->

    neue TXT

    blablablabla
    juppijuppujuppi
    sowiso sowiso
    

    Zum meinem Code:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    /*
    #include <conio.h>  nicht ANSI C... 
    */
    //OK ist nur für Test (system("pause");
    
    FILE *f;
    char buffer[256];
    char test[50];
    static int count; // static? Weißt du, was du hier tust?
    // ^^ globale Variablen sind ... meist unnötig.
        //OK muss noch viel lernen
    int main( void )
    {
        f = fopen("t.txt","r+");    // Variablen benennen! 
    //???const char file_name[ ] = "t.txt"; 
    
        if( f == NULL ) {
    
            printf( "Fehler beim Öffnen" );
            return EXIT_FAILURE;
        }
    
        while( fgets( buffer, sizeof( buffer ), f ) != 0 )
        {
            count++; 
        }
        // du ließt immer wieder in den selben Speicher.
        //Zuletzt steht die letzte Zeile drin.
        //macht ja nichts ;zähle ja nur die Zeilen!!
    
        fseek( f, 0, 0 );
        // Der letzte Parameter muss einer aus SEEK_CUR, SEEK_END, SEEK_SET sein!
        // SEEK_SET	(0)	Beginning of file.
        // SEEK_CUR	(1)	Current position of the file pointer.
        // SEEK_END	(2)	End of file.
    
        for( int i = 0; i <= count; i++ ) // <= Operator? (Wennschon?)
              //?? nur = 
        {
            fgets( buffer, sizeof( buffer ), f );
            // Nochmal lesen??
            //um den "Frosch zu suchen
            if( strstr( buffer, "Frosch" ) )
            {
                fgetpos( f, &fpos );//TEST
                printf("Text gefunden in Zeile %d\n", i + 1 );
                // reiner Zufallstreffer.
                //hat bei 10 verschiedenen TXTs-varianten 10 mal geklappt
                //wenn dass Zufall ist sollte ich einmal Lotto spielen :-)
                break;
            }
        }
    
        fclose( f );
        system( "pause" );  // unschön //wie gesagt nur für TEST
        return 0;           // unnötig //sonst mekert mein compi
    }
    

    Also bei meinem Programm bleibt jetzt der Cursor in der nächsten Zeile( nach dem gefunden Wort) stehen.
    Gibt es keine Anweisung um jetzt zu sagen, springe eine Zeile nach oben und lösche sie komplett? Dachte da an fsetpos,strncat und "\b"

    lg Maxx175



  • bist du sicher, das deine zeilen immer maximal 256 zeichen lang sind ?


Anmelden zum Antworten