2014-04-12 90 views
0

我正在查看istream類,我沒有看到一種方法可以完全清除緩衝區並將輸入設置爲爲下一個「乾淨」輸入做好準備。輸入不正確時清理istream

我定義的提取運算我的課,在我的主程序我問用戶的輸入,如:

while (true) { 
    try { 
     cout << "Enter input: "; 
     MyClass c; 
     cin >> c; 
     return c; 
    } catch(const MyException& e) { 
     cerr << "Error\n"; 
    } 
} 

如果我進入一個意想不到的不正確的輸入,我被困在一個無限循環。

在我的覆蓋extractin方法中,我控制何時輸入不正確並拋出異常,這一切都可以。我只想也清理istream對象,以防止無限循環。

+0

我真的不像無限while循環設計,但可能與重置流有關:http://stackoverflow.com/q/257091/1938163 –

+1

http://www.cplusplus.com/reference/ios/ios/clear/ – Veritas

回答

1

首先,你的類的插入/擴展器不應該拋出異常。 IOStream的設計不是爲了在默認情況下拋出異常並保持一致我建議您不要從I/O操作員拋出自定義異常。

正如Dieter所說,您最好在流狀態下設置std::ios_base::failbit標誌而不是拋出。您可以使用setstate()方法執行此操作。一旦你這樣做了,你可以用if()聲明檢查一個有效的提取。要回答你的問題,一旦你確定輸入是無效的,你清除流狀態,並通過調用ignore()清除新的輸入緩衝區丟棄其餘字符:

while (std::cout << "Enter input: ") 
{ 
    X x; 
    if (!(std::cin >> x)) 
    { 
     std::cout << "Invalid. Try again.\n"; 
     std::cin.clear(); 
     std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
     continue; // or break if needed 
    } 
    // handle good input and break if needed 
} 
+0

這些方法不要拋出異常,構造函數會這樣做,它在提取方法中被調用。清除和忽略方法對我有用,這是我正在尋找的答案,但是我在提取方法內部調用它們,而不是在其外部。清理緩衝區的責任應該是程序員的,而不是用戶的。 – dabadaba

+0

@dabadaba如果構造函數在提取器中拋出異常,那麼就好像提取器本身拋出異常。你仍然應該把構造函數包裝在try catch塊中,並且像我說的那樣在流中設置failbit。另外,我並不是100%同意清理應該是程序員的工作。例如,標準流不會清除無效輸入。此外,如果您要在無效輸入存在時清除流狀態,用戶將如何知道他是否首先輸入了無效輸入? – 0x499602D2

+0

@dabadaba我想你可以緩存流狀態,做清理,然後重置流中的流狀態。但是,這將是很好的。 – 0x499602D2