2010-02-05 42 views
9

我正在介紹C++類,並且想知道更好的方法來檢查輸入是否是所需的類型。安全地提示是/否使用cin

這是做這件事的好方法嗎?我來自一個PHP/PERL背景,這讓我非常擔心使用while循環。

char type; 
while (true) { 
    cout << "Were you admitted? [y/n]" << endl; 
    cin >> type; 

    if ((type == 'y') || (type == 'n')) { 
     break; 
    } 
} 

這是這樣做的安全方式還是我打開自己了傷的世界,我懷疑?在繼續之前,確保獲得我想要的輸入信息會更好嗎?

+2

什麼是在這種情況下,10號的意義是什麼? – froadie

+0

沒有什麼實際意義,我的意思是說循環會運行多長時間是有限制的。但即使存在風險,如果我從不增加。 – Levi

+2

我猜標題確實應該是while(condition)vs while(true){if(condition)break。 –

回答

25

我個人會一起去?

do 
{ 
    cout << "Were you admitted? [y/n]" << endl; 
    cin >> type; 
}while( type !='y' && type !='n'); 
+9

這不好。如果'cin'被關閉,它會永遠循環噴射「你承認了嗎?[y/n]」到'cout'。在測試應該讀取的內容之前,始終測試輸入操作的成功非常重要。 –

+1

比我的代碼更具可讀性和簡潔性!是不是通常用於確保輸入是正確的,如果不是再問一次? – Levi

+2

Do-Whiles主要用於在檢查條件之前要採取某些操作的情況,如果您的條件屬實,則會重複此操作。在用戶輸入的情況下,在檢查你想要輸入的條件之前,Do-Whiles很方便。 – Alex

1

沒關係。如果您希望在發生多次故障後超時,則可以使用i<10,但不值得。

4

使用可以使用

do { 
    program; 
} while (condition_to_repeat); 

如果算法類似,你的榜樣。否則,這個例子是「安全的」,但我不確定可讀性。

do 
{ 
    cout << "Were you admitted? [y/n]" << endl; 
    cin >> type; 
} 
while(!cin.fail() && type!='y' && type!='n'); 
2

爲什麼不能做這種方式:

+0

你怎麼知道'cin >> type'工作? –

+0

我認爲目標...這是C++類的介紹。在這些早期的類中假定cin連接到命令行/操作系統,並且它不會失敗。 – Erich

+0

^Windows中的Z或Unix中的^ D將導致命令行cin第一次返回EOF,第二次失敗。 – jmucchiello

0

我從來沒有編寫PERL/PHP之前,但基於你的問題,這裏的例子是一個簡單的解決方案。

char c; 
while(true){ 
    cout << "Were you admitted? [y/n]" << endl; 
    cin >> c; 
    if(c == 'y') 
     break; 
} 
cin.get(c); 
return 0; 

您將繼續提示,直到您在輸入'y'後輸入'y',這個簡單的程序將退出。

+0

這是什麼解決?你是否決定假設示例代碼片段是整個'main()'? – Potatoswatter

+1

所以,你只是把Levi的代碼片段(這是個問題)移除到'n'條件(?!?!?!??!?!)的等式並將其作爲解決方案發布?!?!?!? – Alex

9

就我個人而言,我會提示一個單獨的函數,這使得它將提示輸出和讀取響應的邏輯表達式放在while循環中。

測試讀取是否成功對於代碼的正確運行至關重要。

我也傾向於使用std::getline來一次獲得一行,因爲它有助於減少由於讀取部分讀取到較早的用戶響應而導致的半讀取行剩餘部分所導致的錯誤。

bool PromptForChar(const char* prompt, char& readch) 
{ 
    std::string tmp; 
    std::cout << prompt << std::endl; 
    if (std::getline(std::cin, tmp)) 
    { 
     // Only accept single character input 
     if (tmp.length() == 1) 
     { 
      readch = tmp[0]; 
     } 
     else 
     { 
      // For most input, char zero is an appropriate sentinel 
      readch = '\0'; 
     } 
     return true; 
    } 
    return false; 
} 

void f() 
{ 
    char type = '\0'; 

    while(PromptForChar("Were you admitted? [y/n]", type)) 
    { 
     if (type == 'y' || type == 'n') 
     { 
      // Process response 
      break; 
     } 
    } 
} 
+0

+1。使用for循環來確定變量的範圍。返回流是更多功能,仍然允許測試,如果它是一個布爾。 – 2010-02-07 02:36:19

+0

哪個變量應該被作用域? '類型'? –

1

不要忘記讓潛在用戶的生活更輕鬆地解釋每一步,甚至提供不區分大小寫的輸入。

#include <iostream> 

#define MAX_USER_INPUT_ATTEMPTS 3 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
char input_value = ' '; 
int current_attempt = 1; 

while(true) 
{ 
    std::cout << "Please confirm your choice (press y[es] or n[o] and Enter): "; 

    std::cin >> input_value; 

    input_value = tolower(input_value); 

    if(input_value=='y' || input_value=='n') 
    { 
     break; 
    } 
    else 
    { 
     std::cout << "You have used " << current_attempt << " of " << MAX_USER_INPUT_ATTEMPTS << " attempts" << std::endl; 
     ++current_attempt; 
    } 

    if(current_attempt > MAX_USER_INPUT_ATTEMPTS) 
    { 
     std::cout << "Warning: Maximum number of attempts reached." << std::endl; 
     break; 
    } 
} 

return 0; 
} 
+0

長碼是looong –

0

的做... while結構爲這種做,但你也可以做循環條件的所有工作:

while (std::cout << "Were you admitted [y/n]\n" && std::cin >> answer && !(answer == 'y' || answer == 'n')); 

:)

如果你不想測試std::cin >> answer的成功(例如想用Ctrl + Z無限循環),可以用逗號替換&& :)

不是完全認真的,儘管methinks把提示條件有時可以增強此類循環的邏輯(避免中斷)。

0

我在這裏看到兩個「問題」。第一個是使用while(true)。我認爲這不是一個好的做法(儘管這可能是許多人的口味問題)。一個循環內打破然而有趣的搜索:

for(i = 0; i < MAX; ++i) { 
    if (v[ i ] == searchedElement) { 
     break; 
    } 
} 

這是不言自明:你運行,直到向量的末尾,但如果該元素被發現,你在到達之前打破。這是合理的。

關於從控制檯獲取信息,直接從cin讀取可能會遇到很多麻煩,例如,如果輸入有一個,則僅返回內容直到第一個空格。 getline()是一個讀取字符串的實用函數,它幾乎總是安全的。 getline()在工具頭中定義。你還需要字符串標題。和cstdio如果你想使用EOF。

int main() 
{ 
    int ch; 
    std::string type; 

    do { 
     getline(std::cin, type); 

     if (cin.fail()) { 
      ch = EOF; 
      break; 
     } 

     ch = tolower(type[ 0 ]); 
    } while(ch != 'y' && ch != 'n'); 

    // interesting things here... 

    return 0; 
} 
1

基於行的輸入不必是冗長的,你可以把它succinct,你寫一次單一的功能,仍然處理邊界情況:

bool yesno_repeat(char const* prompt) { 
    using namespace std; 
    while (true) { 
    cout << prompt << " [yn] "; 
    string line; 
    if (!getline(cin, line)) { 
     throw std::runtime_error("unexpected input error"); 
    } 
    else if (line.size() == 1 and line.find_first_of("YyNn") != line.npos) { 
     return line == "Y" || line == "y"; 
    } 
    } 
} 

int main() try { 
    if (yesno_repeat("Blow up?")) { 
    take_off_every<Zig>(); // in the future, a zig is a nuclear missile... 
    } 
    return 0; 
} 
catch (std::exception& e) { 
    std::cerr << e.what() << '\n'; 
    return 1; 
} 
0

修改什麼@McAden說,試着修復這個錯誤,如果你輸入多個字符,測試只檢查第一個字母。

char type; 
    char buffer[128]; 
    do 
    { 
     cout << "Were you admitted? [y/n]" << endl; 
     cin >> buffer; 
     type = buffer[0]; 
     cout << type << "\n"; 
    }while(!cin.fail() && type!='y' && type!='n'); 
0

這是另一種提示y/n的方法。 「雖然」你沒有得到你想要的,「切換」你的輸入。做任何你喜歡的事情;它只是工作。

#include "stdafx.h" 
#include <iostream> 

int main() 
{ 
    bool play = true; // Initialize play to true. 
    char choice; 
    while (play) // While play is true, do the following: 
    { 
     std::cout << "Play again? [y/n] -> "; 
     std::cin >> choice; 
     switch (choice) 
     { 
     case 'n':   // We can fall through here because we 
      play = false; // don't do anything with 'y' anyway. 
     case 'y':   // Remember; play is already true unless 
      break;   // we changed it to false with 'n'. 
     default: // We'll simply assume anything else is a fail! 
      std::cin.clear(); 
      std::cin.ignore(1024, '\n'); 
      break; 
     } 
     // Break out here and check the "while" condition again... 
    } 
    // When play becomes false, we exit the while statement. 
} 

這是沒有不良後效應!

0

另一種提示y/n的方法。 「做」這個「而」你沒有得到你想要的。做任何你喜歡的事情;它只是工作。

#include "stdafx.h" 
#include <iostream> 

int main() 
{ 
    bool accepted; 
    char answer; 
    do 
    { // Ask for 'y' or 'n' at least once 
     std::cout << "Accepted? [y/n] -> "; 
     std::cin >> answer; 
     if (std::cin.fail()) 
     {        // not a valid character? 
      std::cin.clear(); 
      std::cin.ignore(1024, '\n'); 
     } 
     if (answer == 'n') 
     {        // character is 'n'? 
      accepted = false; 
     } 
     else 
     {        // character is 'y'? 
      accepted = true; 
     } 
     // not valid |or| not 'n'  |or| not 'y' 
    } while (std::cin.fail() || !(answer == 'n') || !(answer == 'y')); 
} 

這也沒有不良後效應!

1

這裏是一個較短的方式

char type; 
while (type != 'y') 
{ 
    cout << "Were you admitted? [y/n]" << endl; 
    cin >> type; 
}