【问题标题】:What did the author mean with his comment about the input of a user-defined type?作者对用户定义类型的输入的评论是什么意思?
【发布时间】:2015-05-31 23:12:06
【问题描述】:

这是一个示例,摘自 B. Stroustrup 所著的《C++ 编程语言》第二版中的10.3.3 用户定义类型的输入部分。代码很旧,但仍然可以通过细微的更改进行编译。示例:

#include <istream>
#include <complex>

using namespace std;

istream& operator>>(istream& s, complex<double>& a)
{
    // input formats for a complex; "f" indicates a float:
    //
    //   f
    //   (f)
    //   (f, f)

    double re = 0, im = 0;
    char c = 0;

    s >> c;
    if( c == '(' ) {
        s >> re >> c;
        if( c == ',' ) s >> im >> c;
        if( c != ')' ) s.clear(ios::badbit);  // set state
    }
    else {
        s.putback(c);
        s >> re;
    }

    if( s ) a = complex<double>(re, im);
    return s;
}

尽管错误处理代码很少,但这实际上可以处理 大多数类型的错误。 局部变量c被初始化以避免 在操作失败后意外地获得了 '(' 的值。 流状态的最终检查确保参数的值 如果一切顺利,a 将被更改。

我没听懂上面强调的那句话。

【问题讨论】:

    标签: c++ istream


    【解决方案1】:

    如果s &gt;&gt; c 失败,则不会写入c

    如果c 未初始化,则在测试if( c == '(' ) 时仍保持未初始化状态。读取未初始化的 char 会导致未定义的行为。

    作者正在讨论这种未定义行为可能表现出来的一种可能方式。


    char c = 0; 的建议修复依赖于这样一个事实:如果s 不是good()s.putback(c); 什么都不做。没关系,尽管恕我直言,写起来会更清楚:

    char c;
    s >> c;
    
    if ( !s )
        return s;
    

    然后任何阅读代码的人都可以立即看到它在出现错误时表现正常;而不必在函数流中穿梭,并检查没有其他操作会做任何意外的事情。

    【讨论】:

    • "s.putback(c); 将被执行。这实际上会放回一个空字节" - 不是这样,好像s &gt;&gt; c 失败了流留在错误状态和putback 哨兵检查失败,成为无操作。 (另外,从 C++11 开始,s &gt;&gt; c 在失败时将 c 设置为 0,因此不需要在代码中显式初始化。)
    • @TonyD OK - 原来我是在 streambuf putback 阅读,而不是 istream putback
    • @M.M 为什么上面的声明if ( c != ')' ) s.clear(ios::badbit);中的s.clear(ios::badbit);
    • @JohnKalane 您似乎有一个新问题,请使用“”按钮发布。如果您认为该帖子与您的问题相关,您可以添加指向该帖子的链接。
    【解决方案2】:

    考虑如果我们没有初始化c会发生什么:

    char c;
    s >> c;
    if (c == '(') { ... }
    

    我们不会检查&gt;&gt; 是成功还是失败。所以如果c == '(',可能是以下两个原因之一:

    1. &gt;&gt; 成功,我们从 istream 检索到字符 '('
    2. &gt;&gt; 失败,但在创建 c 时恰好在内存中的随机字节是 '('

    如果将c 初始化为0,则情况2 是不可能的:如果操作失败,我们知道c 将是0...所以我们可以确定如果我们得到一个@ 987654335@ 这是因为它来自istream

    【讨论】:

      猜你喜欢
      • 2018-05-04
      • 2015-02-09
      • 2011-03-29
      • 1970-01-01
      • 2016-12-18
      • 1970-01-01
      • 2016-08-28
      • 2016-11-14
      • 1970-01-01
      相关资源
      最近更新 更多