C++ 用户定义类的输入流
对于一个用户定义的类,我重载了C++ 用户定义类的输入流,c++,operator-overloading,iostream,cin,istream,C++,Operator Overloading,Iostream,Cin,Istream,对于一个用户定义的类,我重载了,这将很困难。因为您不知道输入是什么,所以不知道它是整数还是浮点值 您可以做的是将输入读取为字符串,并使用例如将其转换为整数。如果它转换完整的字符串,那么您就有了第二种形式,应该读取另一个整数。否则,您将获得一个浮点值,然后使用例如将字符串转换为浮点值 另一种方法是,尝试使用普通输入运算符读取浮点值,如果失败,则读取两个整数 请注意,如果您在obj_j.somefloat上执行算术运算,则它可能不完全为零,因此您的条件将失败。现在,您执行此操作的方式使您很难知道在
,这将很困难。因为您不知道输入是什么,所以不知道它是整数还是浮点值
您可以做的是将输入读取为字符串,并使用例如将其转换为整数。如果它转换完整的字符串,那么您就有了第二种形式,应该读取另一个整数。否则,您将获得一个浮点值,然后使用例如将字符串转换为浮点值
另一种方法是,尝试使用普通输入运算符读取浮点值,如果失败,则读取两个整数
请注意,如果您在obj_j.somefloat
上执行算术运算,则它可能不完全为零,因此您的条件将失败。现在,您执行此操作的方式使您很难知道在读取此类对象的内容流时会发生什么。i、 你应该读浮点数、整数还是字符串
假设您可以更改输出运算符,则可以采取两种方法:
完全删除条件逻辑:
在我看来,最好的方法是将输出运算符重写为:
ostream& operator<<(ostream& os, const myObject& obj)
{
os << '(' << obj.somefloat << ')'
<< '(' << obj.oneint
<< '#' << obj.twoint << ')';
return os;
}
istream& operator>>(istream& is, myObject& obj)
{
char discard = 0;
is >> discard;
is >> obj.somefloat;
is >> discard >> discard;
is >> obj.oneint >> discard;
is >> obj.twoint >> discard;
return is;
}
(当然,还应该在读取之间添加错误处理)
序列化条件逻辑:
您可以将对象的“格式”保存为显式参数。这基本上是在大多数支持版本控制的文档序列化方案中所做的
enum SerializationMode {
EMPTY = 0,
FLOAT,
INT_PAIR
};
然后,输出运算符变为:
ostream& operator<<(ostream& os, const myObject& obj)
{
SerializationMode mode = EMPTY;
if (obj.somefloat != 0)
mode = FLOAT;
else if ( obj.oneint != 0 && obj.twoint != 0)
mode = INT_PAIR;
os << mode << '#';
if (FLOAT == mode)
os << "(" << obj.somefloat << ")";
else if (INT_PAIR == mode)
os << "(" << obj.oneint << "#" << obj.twoint << ")";
return os;
}
ostream和操作员丢弃;
打破
}
案例INT_对:{
is>>放弃>>obj.oneint>>放弃;
is>>obj.twoint>>丢弃;
打破
}
}
回报是;
}
这应该可以:
std::istream& operator>>( std::istream& in, myObject& obj_ )
{
char c;
if( in >> c )
{
if( c == '(' )
{
float f;
if( in >> f >> c ) // f reads also an int
{
if( c == ')' ) // single float format
{
if( f != 0.0 )
obj_.somefloat = f;
else
in.setstate( std::ios_base::failbit );
}
else if( c == '#' ) // two int format
{
if( float(int(f)) != f )
in.setstate( std::ios_base::failbit );
else
{
obj_.somefloat = 0;
obj_.oneint = int(f);
if( in >> obj_.twoint >> c && (c != ')' || (obj_.oneint == 0 && obj_.twoint == 0) ) )
in.setstate( std::ios_base::failbit );
}
}
else
in.setstate( std::ios_base::failbit );
}
}
else if( c == 'E' ) // "Empty Object"
{
const char* txt="Empty Object";
++txt; // 'E' is already read
for( ; *txt != 0 && in.get() == *txt && in; ++txt )
;
if( *txt == char(0) )
{
obj_.somefloat = 0;
obj_.oneint = 0;
obj_.twoint = 0;
}
else
in.setstate( std::ios_base::failbit );
}
else
in.setstate( std::ios_base::failbit );
}
return in;
}
if(在流*中找不到有效的myObj对象)
是.setstate(std::ios::failbit)代码>如何实现这一点,这意味着什么?我不知道你在说什么。这种遗传方法的问题在于,根据流的类型,两个不同的对象(例如int和float)很可能具有相似的表示形式。例如,对于二进制流,0x40000000
可能表示浮点值2.0f,或无符号值1073741824
istream& operator>>(istream& is, myObject& obj)
{
char discard = 0;
unsigned uMode = 0;
is >> uMode >> discard;
auto mode = static_cast<SerializationMode>(uMode);
switch(mode) {
default: break;
case FLOAT: {
is >> discard >> obj.somefloat >> discard;
break;
}
case INT_PAIR: {
is >> discard >> obj.oneint >> discard;
is >> obj.twoint >> discard;
break;
}
}
return is;
}
std::istream& operator>>( std::istream& in, myObject& obj_ )
{
char c;
if( in >> c )
{
if( c == '(' )
{
float f;
if( in >> f >> c ) // f reads also an int
{
if( c == ')' ) // single float format
{
if( f != 0.0 )
obj_.somefloat = f;
else
in.setstate( std::ios_base::failbit );
}
else if( c == '#' ) // two int format
{
if( float(int(f)) != f )
in.setstate( std::ios_base::failbit );
else
{
obj_.somefloat = 0;
obj_.oneint = int(f);
if( in >> obj_.twoint >> c && (c != ')' || (obj_.oneint == 0 && obj_.twoint == 0) ) )
in.setstate( std::ios_base::failbit );
}
}
else
in.setstate( std::ios_base::failbit );
}
}
else if( c == 'E' ) // "Empty Object"
{
const char* txt="Empty Object";
++txt; // 'E' is already read
for( ; *txt != 0 && in.get() == *txt && in; ++txt )
;
if( *txt == char(0) )
{
obj_.somefloat = 0;
obj_.oneint = 0;
obj_.twoint = 0;
}
else
in.setstate( std::ios_base::failbit );
}
else
in.setstate( std::ios_base::failbit );
}
return in;
}