2012-09-12 70 views
2

我有一個遊戲,用戶需要輸入x和y座標在一定範圍內,一次一個。現在我輸入的代碼如下:要求有效的輸入與cout/cin

do { 
    printf("\n"); 
    cout << "X: "; 
    cin >> x; 
    cout << "Y: "; 
    cin >> y; 
} while (cin.fail()); 

我是新來的C++,但閱讀文檔,使我相信,這是驗證用戶輸入一個可以接受的方法。當輸入有效時,它可以很好地工作,但是當輸入是不同類型的(例如輸入「a」)時,它會以「X:Y:」無限循環。我需要做什麼不同的事情才能讓它等待用戶輸入,就像第一次讀取這些行一樣?要如何處理錯誤

std::cout << "X: "; 
if (!(std::cin >> x)) { /* error */ } 
std::cout << "Y: "; 
if (!(std::cin >> y)) { /* error */ } 

這是給你:

+1

有重複,但你需要檢查成功,清除壞標誌,並放棄不良輸入。 – chris

+2

查看常見問題:[我如何才能讓'std :: cin'跳過無效輸入字符?](http://www.parashift.com/c++-faq/istream-and-ignore.html) – ildjarn

+0

@ildjarn謝謝!我現在開始工作了。仍然有很多東西要學.. – Chris

回答

4

試圖解析每個變量的最大問題是,當用戶犯了一個錯誤,他們的整個輸入變得可疑。

請考慮如果我跳過無效輸入並輸入:「3e4 40」。我的意思是「34 40」,但是跳過e可能會使「3 4」離開「40」,或者可能會離開「4 40」。

考慮使用getline來讀取整行並對其進行解析,例如使用istringstream,就像現在一樣 - 任何錯誤都會成爲錯誤,而不會使輸入流處於奇怪的狀態。

+1

請勿使用cplusplus.com。你可以在那裏找到很多錯誤.. – 2012-09-13 18:43:23

+0

@ jons34yp你有一個具體的參考網站,你找不到很多錯誤的建議嗎? –

+0

http://en.cppreference.com在stackoverflow用戶中有良好的聲譽。到目前爲止,我還沒有發現該網站和標準之間的任何差異.. – 2012-09-13 22:14:23

5

您應該檢查每一個輸入操作。你可以早點返回,從循環中斷開,拋出異常......這一切都依賴於。

請注意,您可能會循環,直到您得到可解析的東西,但如果用戶關閉輸入流,則這是危險的。更好地線讀取一行並解析:

std::cout << "Please enter an integer X: "; 
int x; 
bool success = false; 

for (std::string line; std::getline(std::cin, line);) 
{ 
    std::istringstream iss(line); 
    if (iss >> x >> std::ws && iss.get() == EOF) // #1 
    { 
     success = true; 
     break; 
    } 
    std::cout << "Sorry, please try again: "; 
} 

if (!success) 
{ 
    std::cerr << "Unexpected end of input stream!\n"; 
    std::exit(1); 
} 

這樣一來,如果用戶按下[Ctrl]鍵-D在會話中,該程序將立即關閉,並不會嘗試讀取多個值封閉的輸入流。

標記爲#1的行上的條件既測試了整數的成功分析,也測試了到達行結束(吞噬中間空白)的情況。