c++ 文件操作(2)

接上一篇:点击打开链接

准备工作:

fstream p;
p.open("C:\\Users\\用户名\\Desktop\\hh.txt");
if(!p.is_open()){
	cout<<"打开失败我靠什么情况"<<endl;
	exit(1);
}

开篇一个混吃等死管理系统:

struct student
{
    string name;
    int id;
    char gender;
    student(string ts, int ti, char tc):name(ts),id(ti),gender(tc){}  //ts就是临时string,以此类推
    student()=default;
};

使用stl中的list来储存student:

list<student> guys;

定义一个input函数来输入:

void inputs(list<student> &guys)
{
    student temps;         //有没有不定义临时的变量的方法?
    while(cin>>temps.name){   //输入 control + z 结束
        cin>>temps.id>>temps.gender;
        guys.push_back(temps);
    }
}

暴力输出全部文件内容:

char cs[100];
p.getline(cs,100,'\0');
cout<<cs;

上面都没什么好玩的

目标:

掌握文件指针

在文件中排序

替换任意学生的信息

等等

实现:

文件操作其中一个重要的公用就是,以能简易的修改文件的形式,来修改程序所需要的输入,于是就不需要每次都在黑框里打出大量的数据了,也不必直接修改源代码,省去了不必要的编译;

显然楼上的暴力方法没什么用,必须把文件内容转化为 内存内的 复杂的 数据

例如将文件内容写入student类中:

list<student> guys;
student temp;            //临时的学生变量
while(!p.eof()){       //读到文件尾部返回true
     p>>temp.name>>temp.id>>temp.gender;  //利用>>只会读到空白符的特点
     guys.push_back(temp);
}
for(auto &guy:guys){    //11新标准
    cout<<guy.name<<ends<<guy.id<<ends<<guy.gender<<endl;     //全部输出list内的数据;
}

文件内容:

黑框:


这下可好,两个Liza;something happened;


根据网上查找的资料,eof函数指向的是文件尾部最后一个字符之后的时候返回true,也就是在此之前会将文件指针所指的地方再次读入一遍。。。居然把整个类读了两遍;

根据网上的方法,将p.eof()改为p.peek() != EOF,结果鸟用没有,效果一样

。。。

解决方法:(待补充)->已补充

。。。

凑合方法:在while语句后面加上一个   guys.pop_back();

就能删除最后重复的数据;


--------------------------------------------------------

本方法完美避免重复读取文件尾部的数据

    streampos pp,endpp;
    p.seekg(0,ios::end);
    endpp=p.tellg();                     //保存文件尾部指针
    p.seekg(0,ios::beg);
    //cout<<"the end point : "<<endpp<<endl;
    while(p.tellg()<endpp-1){                 //g++ 有警告,是不明确行为,改为(static_cast<int>(p.tellg())<static_cast<int>(endpp)-1)
        p>>temp.name>>temp.id>>temp.gender;
        guys.push_back(temp);
        pp=p.tellg();                      //更新当前文件指针
        //cout<<"now the point : "<<pp<<endl;
    }

本次利用的是文件指针来判断是否读取到文件尾部

发现p.seekg(0,ios:end)返回的总是文件读完后的数字+1,


------------------------------------------------------------

再次更新:强制类型转换还是越少越好

    streampos pp,endpp;
    p.seekg(-1,ios::end);     //直接改指向前一个位置
    endpp=p.tellg();
    p.seekg(0,ios::beg);
    cout<<"now the point : "<<endpp<<endl;
    while(p.tellg()<endpp){      //省去了类型转换
        p>>temp.name>>temp.id>>temp.gender;
        guys.push_back(temp);
        pp=p.tellg();
        cout<<"now the point : "<<pp<<endl;
    }

完整源文件

#include <iostream>
#include <fstream>
#include <string>
#include <list>

using namespace std;

struct student
{
    string name;
    int id;
    char gender;
    student(string ts, int ti, char tc):name(ts),id(ti),gender(tc){}
    student()=default;
};

void inputs(list<student> &guys)
{
    student temps;
    while(cin>>temps.name){
        cin>>temps.id>>temps.gender;
        guys.push_back(temps);
    }
}

int main()
{
    fstream p;
    p.open("C:\\Users\\用户名\\Desktop\\hh.txt");
    if(!p.is_open()){
        cout<<"打开失败我靠什么情况"<<endl;
        exit(1);
    }
    list<student> guys;
    student temp;
    streampos pp,endpp;
    p.seekg(-1,ios::end);
    endpp=p.tellg();
    p.seekg(0,ios::beg);
    cout<<"now the point : "<<endpp<<endl;
    while(p.tellg()<endpp){
        p>>temp.name>>temp.id>>temp.gender;
        guys.push_back(temp);
        pp=p.tellg();
        cout<<"now the point : "<<pp<<endl;
    }
    //guys.pop_back();
    for(auto &guy:guys){
        cout<<guy.name<<ends<<guy.id<<ends<<guy.gender<<endl;
    }
	p.close();

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值