将结构体信息保存到文件中时,需要特别注意以下两点:
1. 最好不要将动态申请的地址(包括string 类)直接保存到文件中。
2. 如果设计的结构体中存在指针变量,并且需要保存结构体信息,那么不但需要保存结构体,而且保存指针指向的内容。
例如:
struct Book{
string title;
double price;
string author;
};
如果直接保存该结构体到文件中,那么在读取的时候程序很可能会出问题。
错误例子如下:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
int main()
{
using namespace std;
struct Book{
string title;
double price;
string author;
};
Book wbook;
ofstream fout;
fout.open("book.dat", ios_base::out|ios_base::trunc);
if(!fout.is_open())
{
cout << "open error!";
exit(1);
}
cout << "Enter the book title: ";
getline(cin, wbook.title);
cout << "Enter the book's price: $";
cin >> wbook.price;
cin.get();
cout << "Enter the book's author: ";
getline(cin, wbook.author);
//将结构体保存到文件中
fout.write((char *)&book, sizeof(Book));
fout.close();
//从文件中读取结构体的内容
Book rbook;
ifstream fin("book2.dat", ios_base::in);
fin.read((char *)&rbook, sizeof(Book));
cout << "title: " << rbook.title << endl;
cout << "price: $" <<r book.price << endl;
cout << "author: " << rbook.author << endl;
fin.close();
return 0;
}
运行结果是段错误。
主要原因是: 将book保存到文件中时,并没有把其中string类指向的字符串保存,而仅仅保存了string动态申请存储字符串的地址。
程序有2个问题:
1. 因为保存的是动态申请的地址, 程序再次运行时,文件中保存的动态地址没有任何意义。
2. 在程序读取文件后由于定义了wbook 和 rbook 两个变量, 其中的string 类保存的是相同的地址, 因此在变量生命周期结束后,将会释放相同的地址两次, 导致段错误。
修改方法:
1. 可以使用数组保存 title, 和author,这样不会有任何问题。
2. 读取文件内容时同样读取到wbook 变量中 ,也就是说不要定义两个变量, 这样就只会释放动态内存一次,但是这样只能保证程序单独一次运行正常, 保存的数据无任何意义。