Home > database >  deleting a line in a .txt file without using another file or array in C
deleting a line in a .txt file without using another file or array in C

Time:12-17

the professor gave told us to delete a line in a txt file without the help of another file or an array, i tried to replace the line with backspace but it print the BS character instead

void rem()
{
    fstream f("test.txt");
    f.seekp(3, ios_base::beg);
    f.write("\b",sizeof(char));
    f.close();
}
1
2
3
4
5

i want to remove 2

1
3
4
5

after searching for few hours i found that everyone use another file or a vector or the try to replay the line with BS like me.

CodePudding user response:

Backspace will not do what you hoped for. A backspace character takes up one char just like any other character. When printed on devices capable of moving the cursor backwards, that's what'll happen. It's just a visual thing and it does not work with files.

Since you are not allowed to use another file or arrays, I'm going to assume that std::vectors and std::strings are also forbidden so I suggest shifting everything down in the file, one char at a time, to overwrite the line to be removed.

  • You will need a function like std::getline which is capable of reading a line from a stream into a std::string - but you do not need to store any data so we can call it skip_line. It could look like this:

    std::istream& skip_line(std::istream& is) {
        // read until reading fails or a newline is read:
        for(char ch; is.get(ch) && ch != '\n';);
        return is;
    }
    
  • When you've opened the file, call skip_line until you've reached the line you want to remove. If you want to remove line 2, call skip_line 1 time. If you instead want to remove line 3, call skip_line 2 times.

  • The get (f.tellg()) position in the stream is now where you should start writing when you move everyting in the file back to overwrite the line to be removed. Store this position in a variable called writepos.

  • Call skip_line one time. The get position is now where you should start reading when moving the contents of the file. Store this position in a variable called readpos.

  • Calculate and store the length of the line to be removed: lenght_of_line_to_be_removed = readpos - writepos.

  • Now, you need to read one char at a time from the readpos position and write that char to the writepos position. It could look like this:

    f.seekg(readpos);           // set the _get_ position where we should read from
    for(char ch; f.get(ch);) {  // loop for as long as you can read a char
        f.seekp(writepos);      // set the _put_ position where you should write to
        f.put(ch);              // ...and write the char
        writepos  = 1;          // step both positions forward
        readpos  = 1;           // -"-
        f.seekg(readpos);       // set the new _get_ position
    }
    
  • When the above is done, everything is "shifted down" in the file - but the size of the file will still be the same as it was before. If you use C 17 or newer, you can use the standard functions std::filesystem::file_size and std::filesystem::resize_file to fix this. Remember that you stored lenght_of_line_to_be_removed above. If you use a version of C that does not have std::filesystem, you need to use some platform specific function. Posix systems have the truncate function that can be used for this.

CodePudding user response:

Technically, this fits requirements :)

$ sed -n "1,2p" input.txt && sed -n "4,9p" input.txt

Or like they said correctly in the comments:

#include <stdio.h>
int main(int argc, char **argv)
{
    return system("sed -n \"1,2p\" input.txt && sed -n \"4,9p\" input.txt");
}
  • Related