2014-10-02 28 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,沒有什麼恢復。

相關問題