Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
76 views
in Technique[技术] by (71.8m points)

c++ - Delete n precedent line from file

I have a file, that contain student name, id, age and number of this student. I want to read the file and for example if the number of student is 2 delete all 3 precedent lines corresponding to this student.

My txt look like this

Marc
45646564
18
1
Jean
4563213
21
2
Paul
45654
22
4
Alice
45948
20
5

while (getline(student, line))
{
        if (counter % 4 == 2) { // Here I want to delete all prcedent 3 lines}
}
    
question from:https://stackoverflow.com/questions/65885384/delete-n-precedent-line-from-file

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Unfortunately your approach, or your design idea is not that good. It should be improved a little bit.

You need to start thinking in an object-oriented way. The object "student" has properties or data elements, like "name", "id", "age" and "number". All this data belong together and are related to a specific "student". And next, you need to define methods that should operate on this data, like "reading" and "writing" the complete data for some student.

If the "number" property that you have, after reading a complete "student" record, is ok, then you will store it in some kind of array or std::vector

So, lets start with the data part:

struct Student {
    std::string name{};
    unsigned long id{};
    unsigned int age{};
    unsigned int number{};
};

This will describe the properties of one student.

Next, we do want to operate on this data. And the first operation is that we do want to read this data from any kind of stream, for example from the console (std::cin) or from a file (std::ifstream). This basically doesn't matter, stream is stream :-)

The iostream library has the so called "extractor" operator for reading from streams. That is the >> operator. And this we can simply define for our "Student" struct. Like so:

    friend std::istream& operator >> (std::istream& is, Student& s) {
        return std::getline(is >> std::ws, s.name) >> s.id >> s.age >> s.number;
    }

The signature of the function is given. This is a formal requirement. Then, now to what are we doing in that function. I would like to remind everybody that the istream extraction operations always return a reference to the given istream.. So, first we call std::getline. This will read the name of the student, and then return again is. Then the line looks like return is >> s.id >> s.age >> s.number. Next we will read the id. This will also return is. Then the statement would look like return is >> s.age >> s.number. And so on and so on. At the end we will have read everything and simply return is;

In the std::getline you will see >>std::ws. This will ignore all leading white spaces like new lines or whatever.

So, now, if we have an open file stream, let' s say "ifs" and a Student variable called "student", then we can write ifs >> student and it will read a complete student record from the file. So, all 4 lines.

By the way, we can do the same mechanism for the inserter function <<.

If we run this in a loop now and store the read student data into a std::vector we can copy all data from the file.

Or, if a student has a certain property, then we can also decide to not copy the data.

This could then look like:

#include <iostream>
#include <vector>
#include <string>
#include <fstream>

struct Student {
    std::string name{};
    unsigned long id{};
    unsigned int age{};
    unsigned int number{};

    friend std::istream& operator >> (std::istream& is, Student& s) {
        return std::getline(is >> std::ws, s.name) >> s.id >> s.age >> s.number;
    }
    friend std::ostream& operator << (std::ostream& os, const Student& s) {
        return os << s.name << '
' << s.id << '
' << s.age << '
' << s.number << '
';
    }
};

int main() {


    // Here we will store all our studends
    std::vector<Student> students{};

    // Open the file with the data
    std::ifstream ifs("r:\data.txt");

    // Check, if the file could be opened.
    if (ifs) {

        Student tempStudent{};
        
        // Read all students from a file, until we hit eof or some other problem
        while (ifs >> tempStudent) {

            // if the student does fullfill the requirements, then we take it, else not
            if (tempStudent.number != 2)
                students.emplace_back(std::move(tempStudent));

        }

        // OK, for debug purposes we show all data ion the screen
        for (const Student& s : students)   std::cout << s << '
';
    }
    else std::cerr << "

Error: source file could not be opened

";
    return 0;
}


And if you want to see a more advance C++ solution, please look at the below:

#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <iterator>
#include <algorithm>

struct Student {
    std::string name{};
    unsigned long id{};
    unsigned int age{};
    unsigned int number{};

    friend std::istream& operator >> (std::istream& is, Student& s) {
        return std::getline(is >> std::ws, s.name) >> s.id >> s.age >> s.number;
    }
    friend std::ostream& operator << (std::ostream& os, const Student& s) {
        return os << s.name << '
' << s.id << '
' << s.age << '
' << s.number << '
';
    }
};

int main() {

    // Here we will store all our studends
    std::vector<Student> students{};

    // Open the file with the data and check, if it is open
    if (std::ifstream ifs("r:\data.txt");ifs) {

        // Read all data
        std::copy_if(std::istream_iterator<Student>(ifs), {}, std::back_inserter(students), [](const Student& s) {return s.number != 2;});

        // For debug purposes we show all data ion the screen
        std::copy(students.begin(), students.end(), std::ostream_iterator<Student>(std::cout, "
"));
    }
    else std::cerr << "

Error: source file could not be opened

";
    return 0;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...