Task

Remove a specific line or a number of lines from a file.

This should be implemented as a routine that takes three parameters (filename, starting line, and the number of lines to be removed).

For the purpose of this task, line numbers and the number of lines start at one, so to remove the first two lines from the file foobar.txt, the parameters should be: foobar.txt, 1, 2

Empty lines are considered and should still be counted, and if the specified line is empty, it should still be removed.

An appropriate message should appear if an attempt is made to remove lines beyond the end of the file.




# removes the specified number of lines from a file, starting at start line (numbered from 1) #
# returns TRUE if successful, FALSE otherwise #
PROC remove lines = ( STRING file name, INT start line, INT number of lines )BOOL:
     IF  number of lines < 0 OR start line < 1
     THEN
        # invalid parameters #
        print( ( "number of lines must be >= 0 and start line must be >= 1", newline ) );
        FALSE
     ELIF  FILE temp file;
           create( temp file, stand back channel ) /= 0
     THEN
        # unable to create a temporary output file #
        print( (  "Unable to create temporary file", newline ) );
        FALSE
     ELIF NOT reset possible( temp file )
     THEN
        # rewinding the temporary file is not possible #
        # we would have to get its name ( with "idf( temp file )", close it and re-open it #
        print( ( "Temp file is not rewindable", newline ) );
        FALSE
     ELIF  FILE input file;
           open( input file, file name, stand in channel ) /= 0
     THEN
        # failed to open the file #
        print( (  "Unable to open """ + file name + """", newline ) );
        FALSE
     ELSE
        # files opened OK #
        BOOL at eof := FALSE;
        # set the EOF handler for the original file #
        on logical file end( input file
                           , ( REF FILE f )BOOL:
                             BEGIN
                                 # note that we reached EOF on the latest read #
                                 at eof := TRUE;
                                 # return TRUE so processing can continue #
                                 TRUE
                             END
                           );
        # copy the input file to the temp file #
        WHILE STRING line;
              get( input file, ( line, newline ) );
              NOT at eof
        DO
            put( temp file,    ( line, newline ) )
        OD;
        # copy the temp file back to the input, removing the specified lines #
        close( input file );
        IF   open( input file, file name, stand out channel ) /= 0
        THEN
            # failed to open the original file for output #
            print( ( "Unable to open ", file name, " for output", newline ) );
            FALSE
        ELSE
            # opened OK - copy the temporary file #
            reset( temp file ); # rewinds the input file #
            at eof := FALSE;
            on logical file end( temp file
                               , ( REF FILE f )BOOL:
                                 BEGIN
                                     # note that we reached EOF on the latest read #
                                     at eof := TRUE;
                                     # return TRUE so processing can continue #
                                     TRUE
                                 END
                               );
            INT end line = ( start line - 1 ) + number of lines;
            INT line number := 0;
            WHILE STRING line;
                  get( temp file, ( line, newline ) );
                  NOT at eof
            DO
                # have another line #
                line number +:= 1;
                IF line number < start line OR line number > end line
                THEN
                    put( input file, ( line, newline ) )
                FI
            OD;
            # close the files #
            close(   input file );
            scratch( temp file  );
            IF   line number < start line
            THEN
                # didn't find the start line #
                print( ( "Specified start line (", whole( start line, 0 ), ") not in ", file name, newline ) );
                FALSE
            ELIF line number < end line
            THEN
                # the ending line was not in the file #
                print( ( "Final omitted line not in the file ", file name, newline ) );
                FALSE
            ELSE
                # successful operation #
                TRUE
            FI
        FI
     FI # remove lines # ;
 
# test the line removal #
BEGIN
    FILE t;
    open( t, "test.txt", stand out channel );
    print( ( "Before...", newline ) );
    FOR i TO 10 DO
        STRING line = whole( i, - ( ( i MOD 5 ) + 3 ) );
        put( t, ( line, newline ) );
        print(  ( line, newline ) )
    OD;
    close( t );
    remove lines( "test.txt", 2, 3 );
    print( ( "After...", newline ) );
    open( t, "test.txt", stand in channel );
    FOR i TO  7 DO
        STRING line;
        get( t, ( line, newline ) );
        print(  ( line, newline ) )
    OD;
    close( t );
    print( ( "----", newline ) )
END