我想将一个Item写入二进制文件,关闭它,然后再打开它来读取它.代码简单明了,使用Visual Studio 2008编译和运行时没有错误.
但是,当使用GCC编译器运行时,它会出现"段错误".
我究竟做错了什么?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class Item
{
private:
string itemID;
string itemName;
string itemState;
public:
Item( const string& id = "i0000", const string& name = "Zero item", const string& state = "not init" )
: itemID( id ) , itemName( name ) , itemState( state )
{
}
string& operator []( int x )
{
if ( 0 == x )
return itemID;
if ( 1 == x )
return itemName;
if ( 2 == x )
return itemState;
return ( string& )"";
}
const string& operator []( int x ) const
{
if ( 0 == x )
return itemID;
if ( 1 == x )
return itemName;
if ( 2 == x )
return itemState;
return ( string& )"";
}
public:
friend istream& operator >>( istream& i, Item& rhs )
{
cout << " * ItemID: ";
getline( i, rhs.itemID );
cout << " - Item Name: ";
getline( i, rhs.itemName );
cout << " - Item State: ";
getline( i, rhs.itemState );
return i;
}
friend ostream& operator <<( ostream& o, const Item& rhs )
{
return o << "ID = " << rhs.itemID
<< "\nName = " << rhs.itemName
<< "\nState = " << rhs.itemState << endl;
}
};
void write_to_file( const string& fn, const Item& item )
{
fstream outf( fn.c_str(), ios::binary | ios::out );
Item temp( item );
outf.write( reinterpret_cast<char *>( &temp ), sizeof( Item ) );
outf.close();
}
void read_from_file( const string& fn, Item& item )
{
fstream inf( fn.c_str(), ios::binary | ios::in );
if( !inf )
{
cout << "What's wrong?";
}
Item temp;
inf.read( reinterpret_cast<char *>( &temp ), sizeof( Item ) );
item = temp;
inf.close();
}
int main()
{
string fn = "a.out";
//Item it( "12", "Ipad", "Good" );
//write_to_file( fn, it );
Item temp;
read_from_file( fn, temp );
cout << temp;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这两行:
outf.write( reinterpret_cast<char *>( &temp ), sizeof( Item ) );
Run Code Online (Sandbox Code Playgroud)
和
inf.read( reinterpret_cast<char *>( &temp ), sizeof( Item ) );
Run Code Online (Sandbox Code Playgroud)
错了.您正在编写对象的二进制布局,包括std::string实例.这意味着您正在编写指向文件的指针值并将其读回.
你不能简单地从文件中读取指针并假设它们指向有效的内存,特别是如果它由一个临时std::string实例保存,当它超出范围时应该释放它的析构函数中的内存.我很惊讶你用任何编译器"正确"运行它.
你的程序应该写的内容和使用读回operator<<和operator>>方法.它应该如下所示:
void write_to_file( const string& fn, const Item& item )
{
fstream outf( fn.c_str(), ios::binary | ios::out );
outf << item << std::endl;
outf.close();
}
void read_from_file( const string& fn, Item& item )
{
fstream inf( fn.c_str(), ios::binary | ios::in );
if( !inf )
{
cout << "What's wrong?";
}
inf >> item;
inf.close();
}
Run Code Online (Sandbox Code Playgroud)
奖励:您的代码有一些怪癖.
幸运的是,这个陈述目前在您的程序中未使用(该方法未被调用).
return ( string& )"";
Run Code Online (Sandbox Code Playgroud)
它无效,因为您将返回对临时字符串对象的引用.记住,字符串文字""不是一个std::string对象,你不能得到它的类型的引用std::string&.你应该提出异常,但你可以逃脱:
string& operator []( int x )
{
static string unknown;
if ( 0 == x )
return itemID;
if ( 1 == x )
return itemName;
if ( 2 == x )
return itemState;
return unkonwn;
}
Run Code Online (Sandbox Code Playgroud)
考虑到字符串是通过引用返回的,这是一个很差的解决方案.它可以被调用者修改,因此它可能不会总是返回""您认为的值.但是,它将删除程序的未定义行为.
对象的.close()方法调用std::fstream不是必需的,当对象超出范围时,析构函数会自动调用它.插入呼叫会有额外的混乱.
另外,冗余命名约定是什么?
class Item
{
private:
string itemID;
string itemName;
string itemState;
// ...
};
Run Code Online (Sandbox Code Playgroud)
出了什么问题打电话给他们ID,name和state?
| 归档时间: |
|
| 查看次数: |
3119 次 |
| 最近记录: |