在文件处理中使用C++字符串
Use C++ strings in file handling
如何在文件处理中使用C++字符串?我创建了一个类,该类将C++字符串作为其私有数据成员之一,但在读取文件时出错,即使我现在没有使用它,并且在构造函数中使用默认值进行了初始化。写入文件时没有问题。如果我使用C字符串,但我不想这样做,效果很好。有办法解决这个问题吗?
class budget
{
float balance;
string due_name,loan_name; //string objects
int year,month;
float due_pay,loan_given;
public:
budget()
{
balance=0;
month=1;
due_name="NO BODY"; //default values
loan_name="SAFE";
year=0;
balance = 0;
due_pay=0;
loan_given=0;
}
.
.
.
};
void read_balance() //PROBLEM AFTER ENTERING THIS FUNCTION
{
system("cls");
budget b;
ifstream f1;
f1.open("balance.dat",ios::in|ios::binary);
while(f1.read((char*)&b,sizeof(b)))
{ b.show_data();
}
system("cls");
cout<<"No More Records To Display!!";
getch();
f1.close();
}
字符串为non-POD data-type
。不能通过读/写函数在字符串中读/写。
basic_istream<charT,traits>& read(char_type* s, streamsize n);
30效果:表现为未格式化的输入函数(如中所述27.7.2.3,第1段)。在构建哨兵对象之后,如果!good()调用可能引发异常的setstate(failbit),然后返回。否则提取字符并将其存储到连续数组的位置,其第一个元素由s.323指定提取并存储字符,直到出现以下任一情况发生:--存储n个字符--输入时出现文件结尾序列(在这种情况下,函数调用setstate(failbit|eofbit),可能引发ios_base::failure(27.5.5.4))。31返回:*this。
关于std::string
的成员是如何放置的,没有任何内容。查看或使用boost::serialiation
。http://www.boost.org/doc/libs/1_50_0/libs/serialization/doc/index.html当然,您可以写入字符串的大小,然后写入数据,当读取-读取大小时,分配这个大小的数组,读取这个数组中的数据,然后创建字符串。但使用助推更好。
在读取类预算的字符串成员(due_name,loan_name)时,代码会逐字节填充它们。虽然它对浮点和int有意义,但对字符串不起作用。
字符串被设计为保留"无限"数量的文本,因此它们的构造函数、复制构造函数、连接等必须确保分配实际的内存来存储文本,并在必要时扩展文本(并在销毁时删除)。从磁盘以这种方式填充字符串将导致字符串对象内的指针无效(不指向包含文本的实际内存),实际上根本不会以这种方式读取文本。
解决这个问题的最简单方法是不在该类中使用C++字符串。计算出将要存储的每个字符串的最大长度,并制作一个长一个字节的char数组(以允许使用0-终止符)。现在,您可以将该类作为二进制读取和写入,而无需担心序列化等问题。
如果您不想这样做,就不能在类上使用iostream::read()。您将需要读取/写入流的成员函数。这就是序列化的意义。。。但是您不需要boost的复杂性。基本来说,你会做一些类似的事情:
// Read with no error checking :-S
istream& budget::read( istream& s )
{
s.read( (char*)&balance, sizeof(balance) );
s.read( (char*)&year, sizeof(year) );
s.read( (char*)&month, sizeof(month) );
s.read( (char*)&due_pay, sizeof(due_pay) );
s.read( (char*)&loan_given, sizeof(loan_given) );
size_t length;
char *tempstr;
// Read due_name
s.read( (char*)&length, sizeof(length) );
tempstr = new char[length];
s.read( tempstr, length );
due_name.assign(tempstr, length);
delete [] tempstr;
// Read loan_name
s.read( (char*)&length, sizeof(length) );
tempstr = new char[length];
s.read( tempstr, length );
loan_name.assign(tempstr, length);
delete [] tempstr;
return s;
}
ostream& budget::write( ostream& s )
{
// etc...
}
请注意,我们已经通过先写一个大小值,然后再写那么多字符来序列化字符串。