C++ 将数据写入链表,将链表写入文件,再将文件中的内容读出

时间:2024-03-17 10:10:36
就算世界荒芜,总有一个人,他会是你的信徒。          ----《独木舟里的星星》
第一步:创建一个节点
template<typename T>
class Node
{
public:
    Node(T data)
    {
        m_data = data;
        m_pNext = NULL;
    }

    const T &getData()
    {
        return m_data;
    }

    Node<T> * &getNext()
    {
        return m_pNext;
    }
private:
    T m_data;
    Node *m_pNext;
};
     这里用到了类模板,因为这里的数据部分类型无法确定。


第二步:创建链表
template<typename T>
class List
{
public:
    List()
    {
        m_iLen = 0;
        m_pFirstNode = NULL;
    }

    Node<T>* getFirstNode()
    {
        return m_pFirstNode;
    }

    int getListLen()
    {
        return m_iLen;
    }

    void insert(T data)
    {
        Node<T> *node = new Node<T>(data);
        node->getNext() = m_pFirstNode;
        m_pFirstNode = node;
        m_iLen++;
    }

    void display()
    {
        Node<T> *tmp = m_pFirstNode;
        for(int i = 0; i < m_iLen; i++)
        {
            cout << tmp->getData() << endl;
            tmp = tmp->getNext();
        }
    }

private:
    int m_iLen;
    Node<T> *m_pFirstNode;
};
       一般习惯将链表头定义的与其他节点不同,链表头可以放很多信息,例如:链表长度、作者、修改人、创建日期等等,当后面节点加入的时候不会每个节点都有这些信息。


。。。可以在主函数中试一下链表。。。
int main(void)
{
    List<int> intList;
    intList.insert(2);
    intList.insert(1);
    intList.insert(5);
    intList.insert(3);
    intList.insert(4);
    cout << "打印链表" << endl;
    intList.display();


第四步:链表写好后,我们将链表写入文件中
        fstream file1;
        file1.open("int.txt");
        file1 << intList;
        将文件以读写的方式打开,记得要提前创建文件int.txt,因为以读写方式打开文件的时候,如果文件不存在,程序不会自动创建。同样,以只读打开也是一样,只有以只写打开的时候才会自动创建。如果仅仅这样写,编译的时候肯定无法通过,因为无法将一个链表类型的数据直接写入文件。我们需要将<<运算符重载。
重载运算符: <<
template<typename T>
fstream &operator << (fstream &file, List<T> &list)
{
    Node<T> *tmp = list.getFirstNode();
    int len = list.getListLen();
    for(int i = 0; i < len; i++)
    {
        file << tmp->getData();
        tmp = tmp->getNext();
    }
    return file;
}
写完后,再执行file1.intList; 就不会报错了。


第五步:从文件中读取数据到链表
    file1.seekg(0, ios_base::beg);
    cout << "--------读取文件里的链表------------" << endl;
    List<int> intList2;
    int data = 0;
    while(1)
    {
        file1 >> data;
        intList2.insert(data);
        if(file1.eof())
        {
            break;
        }
    }
    intList2.display();
    file1.close();
思路很简单,首先将文件的读写位置设置到首部,因为我们在写入文件的时候,读写位置到了最后,这时候直接读是读不到数据的。然后将文件里的内容读到临时变量data中,然后插入的时候调用有参构造函数,输入参数data,生成新链表。读取完退出,最后打印显示。



上面的链表只针对一般的数据类型有效,如果我们的数据部分是自己构造的类呢?
第一步:创建一个类(以student为例)
class Student
{
public:
    Student(int id = 1000, string name = " ", float score = 0.0f)
    {
        m_iId = id;
        m_strName = name;
        m_fScore = score;
    }

    friend ostream &operator << (ostream &out, const Student &stu);

private:
    int m_iId;
    string m_strName;
    float m_fScore;
};


第二步:重载运算符 <<
ostream &operator << (ostream &out, const Student &stu)
{
    out <<" " << stu.m_iId << " " << stu.m_strName << " " << stu.m_fScore ;
}
这里重载是因为1、打印的时候无法直接直接输入一个Student类型,即:cout << stu 是无法直接实现的, 2、写入文件的时候同样无法直接写入一个Student类型。但为什么只重载ostream中的<<就可以同时实现两个呢?因为fstream继承了iostream,而iostream又继承了istream和ostream。关系如下图:
C++ 将数据写入链表,将链表写入文件,再将文件中的内容读出

这之后的操作大同小异,大家可以自行理解。
下面是全代码,以及打印结果:

#include <iostream>
#include <fstream>
using namespace std;

class Student
{
public:
    Student(int id = 1000, string name = " ", float score = 0.0f)
    {
        m_iId = id;
        m_strName = name;
        m_fScore = score;
    }

    friend ostream &operator << (ostream &out, const Student &stu);
    //friend fstream &operator << (fstream &file, const Student &stu);
private:
    int m_iId;
    string m_strName;
    float m_fScore;
};

ostream &operator << (ostream &out, const Student &stu)
{
    out <<" " << stu.m_iId << " " << stu.m_strName << " " << stu.m_fScore ;
}

template<typename T>
class Node
{
public:
    Node(T data)
    {
        m_data = data;
        m_pNext = NULL;
    }

    const T &getData()
    {
        return m_data;
    }

    Node<T> * &getNext()
    {
        return m_pNext;
    }
private:
    T m_data;
    Node *m_pNext;
};


template<typename T>
class List
{
public:
    List()
    {
        m_iLen = 0;
        m_pFirstNode = NULL;
    }

    Node<T>* getFirstNode()
    {
        return m_pFirstNode;
    }

    int getListLen()
    {
        return m_iLen;
    }

    void insert(T data)
    {
        Node<T> *node = new Node<T>(data);
        node->getNext() = m_pFirstNode;
        m_pFirstNode = node;
        m_iLen++;
    }

    void display()
    {
        Node<T> *tmp = m_pFirstNode;
        for(int i = 0; i < m_iLen; i++)
        {
            cout << tmp->getData() << endl;
            tmp = tmp->getNext();
        }
    }
    
private:
    int m_iLen;
    Node<T> *m_pFirstNode;
};

template<typename T>
fstream &operator << (fstream &file, List<T> &list)
{
    Node<T> *tmp = list.getFirstNode();
    int len = list.getListLen();
    for(int i = 0; i < len; i++)
    {
        file << tmp->getData();
        tmp = tmp->getNext();
    }
    return file;
}


int main(void)
{
    List<int> intList;
    intList.insert(2);
    intList.insert(1);
    intList.insert(5);
    intList.insert(3);
    intList.insert(4);
    cout << "打印链表" << endl;
    intList.display();

    fstream file1;
    file1.open("int.txt");
    file1 << intList;
    file1.seekg(0, ios_base::beg);
    cout << "--------读取文件里的链表------------" << endl;
    List<int> intList2;
    int data = 0;
    while(1)
    {
        file1 >> data;
        intList2.insert(data);
        if(file1.eof())
        {
            break;
        }
    }
    intList2.display();
    file1.close();

    cout << endl << endl;
    List<Student> stuList;
    stuList.insert(Student(1001, "aa", 23));
    stuList.insert(Student(1002, "bb", 14));
    stuList.insert(Student(1003, "cc", 53));
    stuList.insert(Student(1004, "dd", 25));
    stuList.insert(Student(1005, "ee", 94));
    cout << "打印链表" << endl;
    stuList.display();

    fstream file2;
    file2.open("student.txt");
    file2 << stuList;
    file2.seekg(0, ios_base::beg);
    cout << "-------读取文件里的链表------------" << endl;
    List<Student> stuList2;
    int id = 0;
    string name = " ";
    float score = 0.0f;
    while(1)
    {
        name.clear();
        file2 >> id >> name >> score;
        stuList2.insert(Student(id, name, score));
        if(file2.eof())
        {
            break;
        }
    }
    stuList2.display();
    file2.close();

    return 0;
}


C++ 将数据写入链表,将链表写入文件,再将文件中的内容读出


QQ:1786610699      倔强的木木      2017年8月26日