【问题标题】:Does anyone actually use stream extraction operators?有人真的使用流提取运算符吗?
【发布时间】:2011-01-19 13:23:08
【问题描述】:

我已经编写了大量的 operator<<(std::ostream &, const T &) 函数——它们非常有用。

我从未在实际代码中编写过operator>>(std::istream &, T &) 函数,甚至从未将提取运算符用于内置类型(好吧,也许是std::string)。这些仅适用于简短的示例程序和教科书吗? operator>> 是 C++ 的失败特性吗?

有人询问了有关safely overloading stream operators 的问题。我想知道是否有人在实践中这样做。

即使对于像reading input from a file in C++ 这样简单的东西,我也不建议使用operator>>。编写能够检测和处理输入错误的健壮代码太难了(或者我不知道如何)。

如果您不同意,请举一个使用operator>> 的好例子——也许可以回答我链接到的最后一个问题。


总结:感谢大家的回复,很多好的意见。曼努埃尔的回答让我重新考虑我不愿意使用op>>,所以我接受了那个。

【问题讨论】:

标签: c++ iostream formatted-input


【解决方案1】:

我认为流提取器运算符与std::copy 等STL 算法和std::istream_iterator 类结合使用时会非常有用。

阅读this answer 了解我在说什么。

【讨论】:

  • 我喜欢这种技术。有时间我一定要试试。
【解决方案2】:

是的,我确实使用过运算符>>(尽管不像运算符

例如,考虑一个代表水果的枚举类型。可以使用 operator>> 解析字符串(如“apple”、“banana”等),获取正确的枚举值。

std::istream &operator>>(std::istream &is, Fruit &fruit)
{
    std::string str;
    is >> str;
    if (str == "apple")
        fruit = APPLE;
    else if (str == "banana")
        fruit = BANANA;
    // other fruits
    else
        is.setstate(std::ios::failbit);
    return is;
}

还要注意在遇到未知字符串时使用 istream 上的 setstate 方法来设置流的失败状态。使用该算子时,可以通过如下方式检查流的failstate:

Fruit fruit;
std::cin >> fruit;
if (std::cin.fail())
   std::cout << "Error: Unknown Fruit!" << std::endl;

【讨论】:

    【解决方案3】:

    值的打印频率高于读取频率,因此operator&lt;&lt; 的使用频率高于operator&gt;&gt;。不过,如果您想读取值,operator&gt;&gt; 很有用。

    您必须检查错误并非特定于operator&gt;&gt;,显然任何其他读取值的方式都必须以某种方式检测无效输入。

    【讨论】:

      【解决方案4】:

      我从不写它们,也很少使用“内置”的。提取操作符对于读取交互式用户输入毫无用处,因为流很容易出错。编写自定义解析例程几乎总是更容易和更健壮。当涉及到序列化时,如果我想将某些内容保存为文本,我会将其保存为行业标准格式,例如 XML,提取操作符显然不适合阅读这些格式。否则我将数据存储在数据库或二进制文件中,这又一次不适合与提取器一起使用。

      【讨论】:

        【解决方案5】:

        operator&gt;&gt; 在将文本形式的数字转换为内部表示时很有用。

        它在为对象加载数据时也很有用。不像scanf不能为不同类型重载,对象可以重载operator&gt;&gt;。因此它为加载对象提供了更多的数据隐藏,无需知道内部表示即可将数据读入对象。

        【讨论】:

          【解决方案6】:

          Operator >> 基本上是反序列化。在我有限的轶事经验中,C++ 中的大多数序列化/反序列化都是在比流库更低的级别实现的。它不必在较低级别实施 - 通常是这样。

          实现自定义反序列化并不总是一个小问题,但即使您不使用流提取语法实现它,您也可能会遇到同样的问题。

          下面是流提取运算符的一个俗气的用法,它至少有点用处: http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.2

          在这个有限的范围内,正确的用法似乎相当简单。

          【讨论】:

          • 这是一个有趣的例子,因为它将string 放入istringstream。结果是,如果解析失败,则可以将原始输入显示给用户。比。如果代码直接从istream 读取,那么在发生故障时,显示错误输入已经太迟了。
          • 文件和网络流也是有用的例子。在字节流级别实现任何类型的反序列化都会很混乱,除非您的需求非常基本。对于更大的需求,你应该设计一个协议,然后实现它。可以设计特定的错误处理(可能还有错误恢复和/或数据冗余),在这种情况下,代码将变得显而易见。
          【解决方案7】:

          我大量使用运算符OOFILE 数据库 API 中将排序指令列表、字段组合到数据库视图等中。

          由于某种原因,大量用户发现使用运算符>> 到append a sort field which was a reverse sort 很直观。我不知道最初是谁建议的,但它吸引了足够多的人,因此它在 API 中实现了。

          例如:

          dbSorter arcSort;  // declare a sorter
          arcSort << reverse(Date) << FileName; // "normal" way to specify two sort fields
          arcSort >> Date << FileName;  // shorthand way that evolved to specify 
          

          我们还常规使用 operator>> 从流中解析整个 dbTable

          【讨论】:

          • 好的,但这不是 istream 提取器。我使用 op>> 编写编组代码,我可以完全控制输入/输出并且任何错误都是致命的。但我从来没有发现它对文本处理有用。
          • 我刚刚更正了自己 - OOFILE 使用传统的运算符模式>> 为表和字段调用虚拟插入方法。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-03
          • 1970-01-01
          • 1970-01-01
          • 2022-07-22
          • 1970-01-01
          相关资源
          最近更新 更多