2014-10-02 31 views
3

说我有两个数据成员的类:预期行为未能从一个IStream读取自定义类型时

class X { 
    std::string a; 
    int b; 
public: 
    ostream& print(ostream& os); 
    istream& read(istream& is); 
} 

print函数输出的所有数据格式良好的,像这样:

ostream& X::print(ostream& os) { 
    return os << a << ' ' << b; 
} 

现在,read函数应该做相反的事情:以指定的格式读取内容(例如,如horse 54,然后将导致a = "horse"b = 54)。

所以说一个输入不遵循这种格式。我的直觉说,只要遇到意想不到的字符(例如试图读取int时的字母),我们将failbit设置为将我们读取的每个字符放回到流。在这种情况下,read函数(或operator>>)的预期行为是什么?标准库的行为如何?如果读取失败,我们是否需要撤销所有字符提取?

+0

读取文档的[unget(http://en.cppreference.com/w/cpp/io/basic_istream/unget),它看起来像每当任何东西,但'goodbit'设置unget会专门失败(甚至可能是[throw](http://en.cppreference.com/w/cpp/io/basic_ios/exceptions)。所以我认为如果你需要在'operator >>'中处理不好的格式化,你通常希望使用例外。 – Jason 2014-10-02 22:55:21

回答

1

一般情况下,如果出现故障,您应该将涉及的任何对象置于有效状态。这是否意味着回滚正在写入的变量,部分写入该变量还是其他任何内容取决于您想要完成的内容以及您认为最适合用户的内容。无论如何,一定要记录你的选择,以便用户可以编程知道你的实现将如何表现。

正如安东已经说过的,标准库似乎没有做任何努力将字符放回到流中。另一个实际的例子,似乎更接近你正在做的,operator>>std::complex类,它实际上必须在完成之前读取序列中的多个标记。

template<typename _Tp, typename _CharT, class _Traits> 
    basic_istream<_CharT, _Traits>& 
    operator>>(basic_istream<_CharT, _Traits>& __is, complex<_Tp>& __x) 
    { 
    _Tp __re_x, __im_x; 
    _CharT __ch; 
    __is >> __ch; 
    if (__ch == '(') 
    { 
    __is >> __re_x >> __ch; 
    if (__ch == ',') 
     { 
     __is >> __im_x >> __ch; 
     if (__ch == ')') 
     __x = complex<_Tp>(__re_x, __im_x); 
     else 
     __is.setstate(ios_base::failbit); 
     } 
    else if (__ch == ')') 
     __x = __re_x; 
    else 
     __is.setstate(ios_base::failbit); 
    } 
    else 
    { 
    __is.putback(__ch); 
    __is >> __re_x; 
    __x = __re_x; 
    } 
    return __is; 
    } 
1

如果出现错误,标准库永远不会尝试将字符放入流中。例如,这里是从标准的摘录,关于如何short从流读取(27.7.2.2.2/2):

operator>>(short& val); 

的转换发生,如同通过下面的代码片断执行(使用相同的符号作为用于上面的代码片段):

typedef num_get<charT,istreambuf_iterator<charT,traits> > numget; 
iostate err = ios_base::goodbit; 
long lval; 
use_facet<numget>(loc).get(*this, 0, *this, err, lval); 
if (lval < numeric_limits<short>::min()) { 
    err |= ios_base::failbit; 
    val = numeric_limits<short>::min(); 
} else if (numeric_limits<short>::max() < lval) { 
    err |= ios_base::failbit; 
    val = numeric_limits<short>::max(); 
} else 
    val = static_cast<short>(lval); 
setstate(err); 

你看,即使数量不适合short,没有什么恢复。

相关问题