一个Student 结构体 一个Manage类(负责管理)
我先贴出两个类部分重要代码先:
Student:
#ifndef _STUDENT_H_
#define _STUDENT_H_
typedef struct student{
string name;
string sex;
int id;
float Chines;
float Math;
float English;
}Student;
#endif
Manage 类:
#ifndef _MANAGE_H_
#define _MANAGE_H_
class Manage{
public:
Manage(string);
Manage(){}
~Manage();
vector<Student>& Read(); //读入文件到顺序容器
vector<Student>& Record(); //手工录入成绩数据
bool Save(string&); //保存
void Display(); //显示
private:
Manage(Manage& rhs);
Manage& operator=(Manage& r);
vector<Student> m_StuList; //读入或手工录入数据到顺序容器
string m_FileName;
};
#endif
vector<Student>& Record(); //手工录入成绩数据:
vector<Student>& Manage::Record()
{
cout<<"Please input : Name Sex ID Chinese Math English and end by enter"<<endl;
Student stu;
for(;;)
{
cin>>stu.name>>stu.sex>>stu.id>>stu.Chines>>stu.Math>>stu.English;
if(stu.name=="end")
{
cout<<"Has Recorded "<<endl;
break;
}
else
m_StuList.push_back(stu);
}
return m_StuList;
}
vector<Student>& Read(); //读入文件到顺序容器:
vector<Student>& Manage::Read()
{
ifstream infile(m_FileName.c_str(),fstream::in|fstream::binary);
if(infile.is_open()&&infile.good())
{
infile.seekg (0, ios::end); //获取文件大小
int length = infile.tellg();
infile.seekg (0, ios::beg);
int num = length/sizeof(Student);
m_StuList.clear();
Student Temp;
for (int i = 0;i<num;i++)
{
m_StuList.resize(num);
infile.read((char*)&(m_StuList[i]),
m_StuList.size()*sizeof(Student));
}
infile.close();
}
else
cerr<<"Error : Unable to open the file"<<infile<<endl;
return m_StuList;
}
bool Save(string&); //保存:
bool Manage::Save(string& FilePath)
{
ofstream outfile(FilePath.c_str(),fstream::binary|fstream::out);
if (outfile.is_open()&&outfile.good())
{
if (!m_StuList.empty())
{
cout<<"Saving...."<<endl;
int num = m_StuList.size();
for (int i = 0; i<num;i++)
{
outfile.write((char*)(&(m_StuList[i])),sizeof(Student));
}
outfile.close();
}
else
return false;
}
else
{
cout<<"Save failed~! Unable to open the file :"<<FilePath<<endl;
return false;
}
return true;
}
main中这样调用:
string filePath("f:\\test3.dat");
Manage manage(filePath);
manage.Record();
manage.Save(filePath);
manage.Read();
manage.Display();
程序运行到 Read中红色部分时候引发了异常 中断了
中断后跳转到系统内部代码:
for (_Iterator_base12 **_Pnext = &_Myproxy->_Myfirstiter;
*_Pnext != 0; *_Pnext = (*_Pnext)->_Mynextiter)
(*_Pnext)->_Myproxy = 0;
_Myproxy->_Myfirstiter = 0;
}
麻烦各位大侠耐心帮忙看看哈
20 个解决方案
#1
string name;
这一类的对象的序列化存在问题。
简单说,你先把string对象写入文件,或者读出,都是一个问题。
你首先要了解string对象的结构,它至少含有一个char*成员。
所以,我问你,你把char* p = "hello world";写入文件,你写入的只是"hello world"的地址值,而不是内容。
所以你的string在Save()和Read()中的写入和读出都是不对的。
你研究一下序列化相关的内容。~
这一类的对象的序列化存在问题。
简单说,你先把string对象写入文件,或者读出,都是一个问题。
你首先要了解string对象的结构,它至少含有一个char*成员。
所以,我问你,你把char* p = "hello world";写入文件,你写入的只是"hello world"的地址值,而不是内容。
所以你的string在Save()和Read()中的写入和读出都是不对的。
你研究一下序列化相关的内容。~
#2
膜拜一下甘草大款
#3
我仔细测试过了 可以读取出来 也可以显示 就是显示完跳转到了异常中断那里
还有我是整个Student对象以二进制方式写进去的
还有我是整个Student对象以二进制方式写进去的
#4
帮顶 mark
#5
我仔细测试过了 可以读取出来 也可以显示 就是显示完跳转到了异常中断那里
还有我是整个Student对象以二进制方式写进去的
#6
楼主可在异常那行看下i的值是否大于m_StuList.size()
#7
那是因为你save了以后就去Read了,如果你这个文件保存了,exe再次启动,恐怕就Read不到什么了。
可靠的做法,就是把name和sex的信息存入前,把他们的字符串长度,按照两个字节或者四个字节先Write到file里面。然后写内容,读的时候,也是如此,先读长度,然后按照长度读内容,写入string对象。
#8
csdn 真烂 想把引发异常那段代码用红色标出来也标不了
引发异常的是 Read 的
infile.read((char*)&(m_StuList[i]),
m_StuList.size()*sizeof(Student));
引发异常的是 Read 的
infile.read((char*)&(m_StuList[i]),
m_StuList.size()*sizeof(Student));
#9
原来我是用push_back 的 后来改了用数组形式 还是那段代码
#10
嗯,我觉得lz没有意识到你的做法是完全行不通的,Student对象
不可以以你那种方式写入和读出。这个我非常肯定。
#11
可以啊 我后来调试我都是直接从文件读取的 没有手工录入
#12
我说过了,你先Save。而不去Read,
你程序再启动一次,不去Save,而是直接去Read,你试一试,
你的问题就是我10楼说的。。。
你程序再启动一次,不去Save,而是直接去Read,你试一试,
你的问题就是我10楼说的。。。
#13
无别的话可说……
十分同意草哥的讲法……
楼主应该好好google一下“为什么要 序列化”
十分同意草哥的讲法……
楼主应该好好google一下“为什么要 序列化”
#14
建议楼主偷窥一下std::string的源代码.
#15
好的 我试下
#16
假设楼主的代码是这样的
那直接write和read不会有问题。但如果是这样:
#ifndef _STUDENT_H_
#define _STUDENT_H_
typedef struct student{
char name[32];
char sex[32];
int id;
float Chines;
float Math;
float English;
}Student;
#endif
那直接write和read不会有问题。但如果是这样:
#ifndef _STUDENT_H_
#define _STUDENT_H_
typedef struct student{
char* name;
char* sex;
int id;
float Chines;
float Math;
float English;
}Student;
#endif
其中name和sex指向一个new出来的一段内存,那直接write和read还可取么?
std::string也是一样的,不能直接write和read,因为string可能是由指针实现的。
#17
我试了 把结果图贴上了吧 测试代码
[img=http://7dr6pa.blu.livefilestore.com/y1pAd4zMdb5UVlV1z3ELQ4TeFlBByvXbQR_IsvXbOl0OecOImu4RaUj9t7c-zOtmlIz8iBS8_gD6ebKuyBTLVMINqAC2Fx4slr4/%E6%9C%AA%E5%91%BD%E5%90%8D2.jpg?psid=1][/img]
运行结果:
[img=http://7dr6pa.blu.livefilestore.com/y1pSJd38c7jpevsjJ0Eh5bpSDS2VMo6mNkdFIUNlK23toEQYMlNSEo0I7aNcCAER8HO3hx3ikRpBHoucaerW3iWpWO-Iu-fZrrB/%E6%9C%AA%E5%91%BD%E5%90%8D.jpg?psid=1][/img]
这应该能说明可以读取文件了吧
#18
我相信你说的了 我把Student结构体的string对象都去掉 后 就正常了 那为什么上面我测试却对的?
#19
要想保存一个数据结构,首先要清楚这个数据结构的组织形式。对于一个用char指针表示的字符,其数据重点不是char指针的值是多少,而是它指向的那一块内存中存放的字符串。如果相反你把char指针的值保存到文件里,以后加载时再把指针的值读出来,那无异于刻舟求剑。可以肯定的是string类内部一定维护了一个char指针。为什么你之前的测试可以把字符串找回来呢?那是因为进程运行的内存环境没有变化,字符串还在原来的位置,相当于刻舟求剑船还没有开动,所以剑能找回来。
#20
其实我觉得你应该很好想明白。因为你把save写成了这样:
而没写成这样:
假如string可以直接以二进制写到文件里,那vector又有何不可呢?
if (!m_StuList.empty())
{
cout<<"Saving...."<<endl;
int num = m_StuList.size();
for (int i = 0; i<num;i++)
{
outfile.write((char*)(&(m_StuList[i])),sizeof(Student));
}
outfile.close();
}
而没写成这样:
outfile.write((char*)(&m_StuList), sizeof(vector<Student>));
假如string可以直接以二进制写到文件里,那vector又有何不可呢?
#21
#1
string name;
这一类的对象的序列化存在问题。
简单说,你先把string对象写入文件,或者读出,都是一个问题。
你首先要了解string对象的结构,它至少含有一个char*成员。
所以,我问你,你把char* p = "hello world";写入文件,你写入的只是"hello world"的地址值,而不是内容。
所以你的string在Save()和Read()中的写入和读出都是不对的。
你研究一下序列化相关的内容。~
这一类的对象的序列化存在问题。
简单说,你先把string对象写入文件,或者读出,都是一个问题。
你首先要了解string对象的结构,它至少含有一个char*成员。
所以,我问你,你把char* p = "hello world";写入文件,你写入的只是"hello world"的地址值,而不是内容。
所以你的string在Save()和Read()中的写入和读出都是不对的。
你研究一下序列化相关的内容。~
#2
膜拜一下甘草大款
#3
我仔细测试过了 可以读取出来 也可以显示 就是显示完跳转到了异常中断那里
还有我是整个Student对象以二进制方式写进去的
还有我是整个Student对象以二进制方式写进去的
#4
帮顶 mark
#5
我仔细测试过了 可以读取出来 也可以显示 就是显示完跳转到了异常中断那里
还有我是整个Student对象以二进制方式写进去的
#6
楼主可在异常那行看下i的值是否大于m_StuList.size()
#7
那是因为你save了以后就去Read了,如果你这个文件保存了,exe再次启动,恐怕就Read不到什么了。
可靠的做法,就是把name和sex的信息存入前,把他们的字符串长度,按照两个字节或者四个字节先Write到file里面。然后写内容,读的时候,也是如此,先读长度,然后按照长度读内容,写入string对象。
#8
csdn 真烂 想把引发异常那段代码用红色标出来也标不了
引发异常的是 Read 的
infile.read((char*)&(m_StuList[i]),
m_StuList.size()*sizeof(Student));
引发异常的是 Read 的
infile.read((char*)&(m_StuList[i]),
m_StuList.size()*sizeof(Student));
#9
原来我是用push_back 的 后来改了用数组形式 还是那段代码
#10
嗯,我觉得lz没有意识到你的做法是完全行不通的,Student对象
不可以以你那种方式写入和读出。这个我非常肯定。
#11
可以啊 我后来调试我都是直接从文件读取的 没有手工录入
#12
我说过了,你先Save。而不去Read,
你程序再启动一次,不去Save,而是直接去Read,你试一试,
你的问题就是我10楼说的。。。
你程序再启动一次,不去Save,而是直接去Read,你试一试,
你的问题就是我10楼说的。。。
#13
无别的话可说……
十分同意草哥的讲法……
楼主应该好好google一下“为什么要 序列化”
十分同意草哥的讲法……
楼主应该好好google一下“为什么要 序列化”
#14
建议楼主偷窥一下std::string的源代码.
#15
好的 我试下
#16
假设楼主的代码是这样的
那直接write和read不会有问题。但如果是这样:
#ifndef _STUDENT_H_
#define _STUDENT_H_
typedef struct student{
char name[32];
char sex[32];
int id;
float Chines;
float Math;
float English;
}Student;
#endif
那直接write和read不会有问题。但如果是这样:
#ifndef _STUDENT_H_
#define _STUDENT_H_
typedef struct student{
char* name;
char* sex;
int id;
float Chines;
float Math;
float English;
}Student;
#endif
其中name和sex指向一个new出来的一段内存,那直接write和read还可取么?
std::string也是一样的,不能直接write和read,因为string可能是由指针实现的。
#17
我试了 把结果图贴上了吧 测试代码
[img=http://7dr6pa.blu.livefilestore.com/y1pAd4zMdb5UVlV1z3ELQ4TeFlBByvXbQR_IsvXbOl0OecOImu4RaUj9t7c-zOtmlIz8iBS8_gD6ebKuyBTLVMINqAC2Fx4slr4/%E6%9C%AA%E5%91%BD%E5%90%8D2.jpg?psid=1][/img]
运行结果:
[img=http://7dr6pa.blu.livefilestore.com/y1pSJd38c7jpevsjJ0Eh5bpSDS2VMo6mNkdFIUNlK23toEQYMlNSEo0I7aNcCAER8HO3hx3ikRpBHoucaerW3iWpWO-Iu-fZrrB/%E6%9C%AA%E5%91%BD%E5%90%8D.jpg?psid=1][/img]
这应该能说明可以读取文件了吧
#18
我相信你说的了 我把Student结构体的string对象都去掉 后 就正常了 那为什么上面我测试却对的?
#19
要想保存一个数据结构,首先要清楚这个数据结构的组织形式。对于一个用char指针表示的字符,其数据重点不是char指针的值是多少,而是它指向的那一块内存中存放的字符串。如果相反你把char指针的值保存到文件里,以后加载时再把指针的值读出来,那无异于刻舟求剑。可以肯定的是string类内部一定维护了一个char指针。为什么你之前的测试可以把字符串找回来呢?那是因为进程运行的内存环境没有变化,字符串还在原来的位置,相当于刻舟求剑船还没有开动,所以剑能找回来。
#20
其实我觉得你应该很好想明白。因为你把save写成了这样:
而没写成这样:
假如string可以直接以二进制写到文件里,那vector又有何不可呢?
if (!m_StuList.empty())
{
cout<<"Saving...."<<endl;
int num = m_StuList.size();
for (int i = 0; i<num;i++)
{
outfile.write((char*)(&(m_StuList[i])),sizeof(Student));
}
outfile.close();
}
而没写成这样:
outfile.write((char*)(&m_StuList), sizeof(vector<Student>));
假如string可以直接以二进制写到文件里,那vector又有何不可呢?