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

就算世界荒芜,总有一个人,他会是你的信徒。          ----《独木舟里的星星》
第一步:创建一个节点
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。关系如下图:


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

#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 ;
}





QQ:1786610699      倔强的木木      2017年8月26日
  • 46
    点赞
  • 274
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值