简体   繁体   English

如何读取.txt文件,转换为c ++中的继承对象?

[英]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). 我正在做一项作业,我必须在c ++中为体育组织创建一个数据库,而无需使用STL(我创建了自己的列表和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. 这些对象,继承了team对象。 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 还可以Kezes HC 21 50000还可以

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... 请注意,由于缺少代码的重要部分,我假设您仅将指向对象的指针存储在ListaElem类中,但是很可能,因为要存储的类是多态的...

What you need, though, are objects living longer than just while the programme is in the if block. 但是,您需要的是对象的寿命比程序在if块中的寿命更长。 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. 假设我们针对现实生活中的场景,那么仅将对象移出if子句是不可能的,因为我们可能需要多个同类型的单个对象。 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; 好的,您不允许使用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). 那么您将自己编写智能指针以及make_uniquemove模板函数(就像您对list和string所做的那样)。 On cppreference, you can find a sample implementation, eg for std::make_unique . 在cppreference上,您可以找到一个示例实现,例如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. 或者,您可能会问您的老师,她/他是否在智能指针的STL方面例外。

Final advice: Operating on contiguous memory in general is much faster than operating on memory potentially distributed all over your system RAM. 最终建议:在连续内存上进行操作通常比在整个系统RAM上可能分布的内存上进行操作要快得多。 So you might consider rather re-implementing std::vector instead of std::list . 因此,您可以考虑重新实现std::vector而不是std::list

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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