直接读取对象

时间:2013-09-09 16:29:39

标签: c++

我会直截了当地说:

我有一个包含图书名称列表的文本文件。我知道如何阅读文本文件,例如:

string word;
file >> word;

但是,我说有一个名为“word”的课程。是否可以这样做:

word myWord;
file >> myWord;

如果是,那么这个对象将如何宣布?它会读取它包含的第一个公共字符串吗?

感谢您的时间!

2 个答案:

答案 0 :(得分:3)

简单的答案是肯定的,你可以做file >> myWord; 因为你为你的班级定义了>>运算符:

std::ostream&
operator>>( std::ostream& source, Word& word )
{
    //  ...
    return source;
}

有几个注意事项:

  • 此运营商不能成为会员;它必须是一个自由的功能。 (如果是会员,你的班级将是左手 参数。)如果它需要访问私有数据,你可能会 使它成为friend

  • 不要忘记错误检查和常规 istream表示错误。如果遇到输入则无法解析 进入你的班级,你需要设置std::ios::failbit。 (的 当然,很多时候,你会先前委托给他们 已定义>>,如果失败,std::ios::failbit已经存在 已经设定。)

编辑:

至于你应该在新重载的运算符中做什么, 有几种可能性(可以谨慎使用) 混合的):

  • 您可以调用现有的>>,例如,字符串或 内置类型。这是迄今为止最简单的,但它假设 你的输入可以很容易地被解析 现有的>>,这种情况很少见。

  • 您还可以使用未格式化的输入,例如istream::get(), 这通常与之前的解决方案并行使用, 输入分隔符或其他语法元素之类的东西 你的格式。

  • 或者你可以恢复直接从中读取字节 streambuf,并解析它们。如果你有这个是合适的 例如,一些全新的类型。如果你走这条路,那就行 如果您读取文件结尾,则忘记设置eofbit,即使 你可以成功解析。如果你这样做,你会 还必须在sentry的顶部创建一个>>对象, 只有好的才能继续(只有这样 operator>> std::ios::good是有意义的std::ios::good()。你绝不能 如果std::ios::eofbit尝试读取streambuf中的字符 返回false,您必须随时设置std::ios::good() 读取EOF(将导致所有未来的呼叫 >>返回false)。这非常重要 我倾向于使用一个小的包装器对象,并通读 它

在所有情况下,您可能必须使用格式 信息:作为一个简单的例子,如果你不想允许 输入中的空白区域,但您仍在使用nows 应设置>>(并在结束时恢复)。因此,大多数这样的 IOSave运算符将首先保存格式化状态,然后 最后恢复它。 (这通常通过以下方式完成 failbit类,无论如何都应该在工具包中。) 而且,如果输入格式中的某些内容不正确,那么 应设置>>

举一个简单的例子,考虑一个简单的Complex std::istream& operator>>( std::istream& source, Complex& dest ) { IOSave state( source ); // Skip leading whitespace, depending on formatting options. if ( (source.flags() & std::ios_base::skipws) != 0 ) { source >> std::ws; } source.unsetf( std::ios_base::skipws ); std::streamsize totalWidth = std::max( source.width() - 3, std::streamsize(0) ); ; std::streamsize imagWidth = totalWidth / 2; std::streamsize realWidth = totalWidth - imagWidth; if ( source.get() != '(' ) { source.unget(); source.setstate( std::ios::failbit ); } double real = 0.0; source >> std::setw( realWidth ) >> real; std::numpunct<char> const& np = std::use_facet<std::numpunct<char>>( source.getloc() ); if ( std::get() != (np.decimal_point() != ',' ? ',' : ';') ) { source.unget(); source.setstate( std::ios::failbit ); } double imag = 0.0; source >> std::setw( imagWidth ) >> imag; if ( std::peek() != ')' ) { source.unget(); source.setstate( std::ios::failbit ); } if ( source ) { dest = Complex( real, imag ); } return source; } 类:

Complex

这是一个非常简单的例子。一个真实的{{1}} 例如,class也会接受a + ib形式的输入。 但它应该让你知道你必须要做的事情 在编写这样的运算符时要考虑。

答案 1 :(得分:1)

当然不是。你必须为你的班级>>重载word运算符。您可以将其作为成员函数或非成员函数执行此操作。 要作为非会员超载,您可以写:

fstream& operator >> (fstream& arg1,word& arg2)
{
}

如果此功能需要访问word的私人成员,您可以使用:

class word{
    // somewhere in your class add this line
    friend fstream& operator >> (fstream&,word&);
}