c++ - 直接读取对象

标签 c++

我就直接进入正题了:

我有一个文本文件,其中包含书名列表。我知道如何读取文本文件,例如:

string word;
file >> word;

但是,假设我有一个名为“word”的类。是否可以这样做:

word myWord;
file >> myWord;

如果是,那么如何声明这样的对象?它会读取它包含的第一个公共(public)字符串吗?

感谢您的宝贵时间!

最佳答案

简单的答案是肯定的,您可以执行 file >> myWord;,只要 正如您为您的类定义了 >> 运算符一样:

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

几个注意事项:

  • 该运算符(operator)不能是成员;它必须是一个免费函数。 (如果是成员(member)的话,你的类(class)就是左手 参数。)如果它需要访问私有(private)数据,你可能有 使其成为 friend

  • 不要忘记错误检查以及约定 istream 错误。如果遇到无法解析的输入 在你的类中,你需要设置std::ios::failbit。 (的 当然,很多时候,你会委托(delegate)给以前的 定义的 >>,如果失败,std::ios::failbit 已经 已设置。)

编辑:

至于你应该在新重载的运算符中做什么, 有几种可能性(小心地可以是 混合):

  • 您可以调用现有的 >>,例如,对于字符串或 内置类型。这是迄今为止最简单的,但它假设 您的输入可以轻松地根据以下内容进行唯一解析 现有的 >>,但这种情况很少见。

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

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

在所有情况下,您可能都需要调整格式 信息:作为一个简单的例子,如果您不想允许 输入中存在空格,但您仍在使用 >>,您 应该设置nows(并在最后恢复它)。因此,大多数这样的 >> 运算符将首先保存格式化状态,并且 最后恢复它。 (这通常是通过 IOSave 类,无论如何,您应该将其包含在您的工具包中。) 再说一遍,如果输入格式有误,您 应设置failbit

作为一个简单的例子,考虑一个 >> 来表示一个简单的复杂 类:

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;
}

这是一个极其简单的例子。真正的复杂 例如,类也接受 a+ib 形式的输入。 但它应该让你了解你必须做的事情 编写这样的运算符时请考虑。

关于c++ - 直接读取对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18702804/

相关文章:

c++ - 在 C++ (C++98) 中打印链表

c++ - Eclipse CDT 基于文件构建/运行

c++ - 即使在将新字符串复制到现有字符串后,旧包含也可用(在某些索引处)

c++ - wxThreadEvent::GetPayload() 后程序崩溃

c++ - 如何创建接受二维数组的构造函数

c++ - xcode 解决方案的 node-gyp 链接问题

c++ - 如何用 gtk 2.x 而不是 gtk3.x 编译 opencv

c++ - 对指针感到困惑

c++ - GL_DRAW/READ_FRAMEBUFFER 与 GL_FRAMEBUFFER?

c++ - 这些是将 printf 的输出设置为字符串的方法吗?