2011-11-04 167 views
-2

一個哪種模式最好?

:data_input 
    [input code here]; 
    if ([validation test]) { 
     std::cout << "Invalid data. "; 
     goto data_input; 
    } 

do { 
    [input code here]; 
while ([validation test] && std::cout << "Invalid data. "); 

Ç

do { 
    [input code here]; 
} 
while ([validation test] && (std::cout << "Invalid data. ") || 1); 

你會選擇什麼方法跳回到代碼的輸入段,爲什麼?

+2

您認爲B和C之間的區別是什麼? – Archie

+1

這是功課嗎? –

+0

哈哈@「最好」。什麼是「最好」? 「最佳」爲了什麼?據誰?什麼時候?在什麼條件下?通過什麼指標? –

回答

1

我用的scanf(在C)中使用的訣竅是以下內容:

while (scanf("%d", &myInt)!=1) { 
    printf("Invalid Data!\n"); 
} 

這基本上結合了數據輸入和確認步驟:scanf的嘗試讀取一個int,並返回的事物的數量它閱讀成功。如果它不是1,則出現問題,顯示錯誤消息,並且scanf再次運行。

所以,如果你能以某種方式將你的輸入和驗證步驟合併成一個語句。所以,你可以嘗試:

int data; // or whatever 
while (!validate(data = getData())) { 
    [error code] 
} 

(我不是C++方面的專家,因此,雖然我知道這是可能,我不知道這是否就一定是好的作風C++神,如果。這不是地道的,告訴我,我會編輯)

如果這是不可能的,我會去這樣的事情:

[input data] 

while ([validation test fails]) { 
    std::cout << "Invalid data." 
    [input data again] 
} 

我不喜歡,因爲goto語句:)

我不喜歡B或C,因爲我認爲這是濫用& &和|| - 利用短路是好的,但這些運營商的輸入應該是返回有意義的值的表達式,而不是語句。

+0

理想情況下,你只有'[input data]'代碼一次。同意'goto'在這裏有點矯枉過正,但是如果我改變了我讀取數據的方式,用這個解決方案我不得不在兩個地方改變它 - 並且在凌晨4點,當我半醒時,只是試圖獲得睡覺前做的東西,這一切都保證,我會忘記其中一個。 – cHao

+0

這是真的,但我仍然認爲這個代碼比三個建議的例子更好。不過,我並不是說它是最優的。 – Ord

0

要投擲另一個在混合:

bool validateData([data]) 
{ 
    bool valid; 

    [validation logic, sets valid true or false] 

    if(!valid) 
    { 
     std::cout << "Invalid data."; 
     return false; 
    } 
    return true; 
} 

然後

do 
{ 
    [input data] 
} while(!validateData([data])); 

則a)它是可讀和b)是validateData可以是任意的,並且是易於維護。

0

如果您正在使用C++流和希望做一些與數據,我會做到這一點的方法是:

std::istream& operator<<(std::istream& i, Data& d) 
{ 
    if (!(i >> d.member) || !(i >> d.othermember)) 
     d.markInvalid(); // the istream is automatically marked invalid 
    return i; 
} 

// In another function: 

    Data myData; 
    while (std::cout << "Please enter the data: " && 
      std::cin >> myData) // Or another stream, of course) 
    { 
     if (!data.isValid()) 
     { 
      std::cout << "Invalid data.\n"; 
      continue; 
     } 
     // Operate on data 
    } 

這給你一個意外的EOF不會有循環運行和優勢沒有gotos。如果您希望繼續輸入錯誤,只需將第二個&&更改爲||並進行循環檢查myData.isValid(),並在出現故障時顯示錯誤消息continue;

或者,如果你正在寫一個函數讀取並返回數據(不是很優雅,在我看來),你可以使用

Data GetData(std::ostream& o, std::istream& i) { 
    Data myData; 
    while (o << "Please enter the data: " && 
      i >> myData.member && 
      i >> myData.otherMember && 
      !myData.isValid()) 
    { 
     o << "Invalid data! Please try again.\n"; 
    } 
    if (!i) 
    { 
     myData.markInvalid(); // Make sure the caller knows the data is not good. 
     // Alternatively, throw an exception. 
    } 
    return myData; 
} 

// In another function: 
    Data myData = GetData(std::cout, std::cin); 
    if (myData.isValid()) 
    { 
     // Operate on data 
    } 

在這兩種情況下,你可能不能夠完全創建對象,並將需要某種方式來報告。您需要檢查是否輸入了錯誤格式的數據(然後您可能會忽略無效輸入以便您可以獲得新輸入),或者數據流是否死亡(在這種情況下,您可能需要保釋出)。 C++ FAQ有關於此問題的一些信息here,包括使用整型類型執行此類操作的函數示例。