简体   繁体   中英

How can I read .txt files, to inherited objects in c++?

I'm doing an assignment, where I have to create a database in c++ for a sport organization, without using STL (I created my own list and String). The database is keeping the data in a doubly linked list, where besides the nodes, there is the data, which are the teams. Of course there is not just one type of teams, there is currently three. These objects, inherited the teams objects. I have made everything work, except reading the text file, and thus creating objects.

I have already tried, to create a marker, which is the first piece of information the program will read, which will decide which of the three classes needs to be created, then reads the other data, to create the new object, then put it in the end of the doubly linked list. Unfortunately it does'nt work, instead it does nothing, and continue the whole programme, like nothing happened.

void hozzaad(ListaElem *s, team *data) { ///adding to the end
        ListaElem *iter = s;
        while (iter->kov=NULL)
        {
            iter = iter->kov;
        }
        ListaElem *uj = new ListaElem(data);
        uj->elozo = iter;
        iter->kov = uj;
    }

    void listaz(ListaElem *s) { //print out all that is in the list
        if (s == NULL) {
            std::cout << "Ures lista" << std::endl;
            return;
        }
        ListaElem *iter = s;
            while (iter!=NULL)
            {
                iter->adat->kiirt(std::cout);
                iter = iter->kov;
        }
    }

void listament(ListaElem *s, const char *a) { //this one creates the file
        std::ofstream file;
        file.open(a);
        ListaElem *iter = s;
        if (file.is_open()) {
            while (iter != NULL) {
                file << iter->adat->Getclub()<< "\n";
                file << iter->adat->Getname() << "\n" << iter->adat->Getmember()<< "\n";
                if (iter->adat->Getclub() == 1) {
                    file << iter->adat->Getsupport() << "\n";
                }
                if (iter->adat->Getclub() == 2) {
                    file << iter->adat->Getpompom() << "\n";
                }
                if (iter->adat->Getclub() == 3) {
                    file << iter->adat->Getname1() << "\n" << iter->adat->Getname2() << "\n";
                }
                iter = iter->kov;
            }
        }
        else
        {
            std::cout << "Nem tudom kinyitni a file-t";
        }
        file.close();
        return;
    };

void test4() {                  // the basic test 
    Handball c("Kezes HC", 21, 50000);
    team adat("", 0);
    ListaElem *egyik = new ListaElem(&adat);
    hozzaad(egyik,&c);
    ListaElem *uj = new ListaElem(&adat);
    listament(egyik, "test.txt"); 
    std::ifstream file;
    file.open("test.txt");
    if (!(file.is_open())) {
        std::cout << "hiba\n";
        return;
    }
    int micsoda;
    while (file >> micsoda);
    {
        if (micsoda == 1) {
            String beolvas("");
            int m;
            int d;
            getline(file, beolvas);
            file >> m;
            file >> d;
            Handball ujh(beolvas, m, d);
            hozzaad(uj, &ujh);
            beolvas = "";
        }
        if (micsoda == 2) {
            String fbeolvas("");
            int fm;
            String e1("");
            String e2("");
            getline(file, fbeolvas);
            file >> fm;
            getline(file, e1);
            getline(file, e2);
            football ujh(fbeolvas, fm, e1, e2);
            hozzaad(uj, &ujh);
        }
        if (micsoda == 3) {
            String bbeolvas("");
            int bm;
            int bd;
            getline(file, bbeolvas);
            file >> bm;
            file >> bd;
            Basketball ujh(bbeolvas, bm, bd);
            hozzaad(uj, &ujh);
        }
    }
    std::cout << "OK" << std::endl;
    listaz(uj);
    file.close();
    std::cout << "OK" << std::endl;
}


test4() expects to go out like:

OK Kezes HC 21 50000 OK

Shortening the code to the absolutely necessary:

if (micsoda == 1)
{
    Handball ujh;
    hozzaad(uj, &ujh);
} // at this point in code, your object ujh runs out of scope!!!

At the time the object runs out of scope, it is destroyed (you will notice if you add some output statement in the class' destructor...) and any pointers to it get invalid; especially, those in the list get invalid (one speaks of dangling pointers – or references, for which the same can happen). Now using them results in undefined behaviour – which means anything could happen. If you're unlucky (or lucky, depending on point of view), your program even crashes.

Be aware that, due to lacking important parts of your code, I am assuming that you only store pointers to the objects in your ListaElem class, which is pretty likely, though, as the classes to be stored are polymorphic...

What you need, though, are objects living longer than just while the programme is in the if block. Assuming we target some real-life scenario, just moving the objects out of the if clauses is no option as we might need more than one single object of the same type. So you will create the objects dynamically. However, then you'll have to deal with memory management and the ownership question as well. Easiest to handle the memory management part is using smart pointers. Ownership? Well, it appears reasonable to me to assume the list being the sole owner of the objects, so you could have:

class ListElem
{
    std::unique_ptr<Team> m_data;
public:
    ListElem(std::unique_ptr<Team> data) // accepting a unique_ptr already here indicates
                                         // clearly that the item will grab ownership
        : m_data(std::move(data)) // unique_ptr is only movable, not copiable!
    { }
}

Then you can change your code above to:

if (micsoda == 1)
{
    int n, m; // sample data
    hozzaad(uj, std::make_unique<Team>(n, m); // arguments are passed directly to
                                              // the constructor of class Team
}

OK, you are not allowed to use STL; then you'd write your smart pointers on your own, as well as make_unique and move template functions (just as you did for list and string already). On cppreference, you can find a sample implementation, eg for std::make_unique . Don't just copy/paste the code, but understand it first, and best re-write it from scratch on your own, otherwise you won't be learning anything (same applies for my code above). Or maybe you ask your teacher if she/he makes an exception on STL for smart pointers.

Final advice: Operating on contiguous memory in general is much faster than operating on memory potentially distributed all over your system RAM. So you might consider rather re-implementing std::vector instead of std::list .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM