2012-09-14 69 views
3

我适应这个代码编程:企图原理与实践在C++由Bjarne Stroustrup的检查给出的输入是有效的:C++的cout在while循环打印两次

#include <iostream> 
using namespace std; 

int main() 
{ 
    cout << "Please enter your first name and age: "; 
    string first_name = "???"; 
    int age = -1; 
    cin >> first_name >> age; 

    while (!cin) { 
     cin.clear(); 
     cout << "Sorry, can you enter that again? "; 
     cin >> first_name >> age; 
    } 

    cout << "Hello, "<<first_name<<"! (age "<<age<<")\n"; 
    return 0; 
} 

可正常工作,除字样"Sorry, can you enter that again? "正在打印两次,一次在第二次输入之前,一次在之后。

任何人都知道为什么会发生这种情况?谢谢。

+0

在Visual Studio 2010中对此进行了测试,并按预期工作,编译时使用了哪些编译器? – EddieBytes

+0

测试了gcc 4.6.3 @ ubuntu x64,确实打印了两次,非常奇怪:S – SingerOfTheFall

回答

1

这取决于你输入的内容!

  • 输入"Tim 29":Works,“Hello Tim(29)”。

  • 输入"Tim Tom 29":作品,一个重复,“你好汤姆(29)”。

  • 输入"Tim Tom Tina 29":作品,两个重复,“你好蒂娜(29)”。

我假设你正在尝试第三个。第一次失败是Tom,他不是一个数字。重置错误状态是好的,但它并没有摆脱Tom。我们仍然需要多一次失败的尝试才能消耗他(Tina上的失败,那时他不是一个数字)。只有这样,我们准备好了Tina

3

清除故障位还不够,还必须清除输入缓冲区中的任何剩余字符。此外,代码看起来比必要的更复杂。以下作品:

std::string name; 
int age; 

std::cout << "Please enter your name & age: "; 

while (not (std::cin >> name >> age)) { 
    std::cout << "Sorry, can you enter that again? "; 
    std::cin.clear(); 
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
} 

std::cout << "Hello " << name << " (" << age << ")\n"; 

噢,不要忘记刷新输出流,我不认为这将自动为您完成。

也就是说,标准输入/输出流是,所以它们并不真正适用于交互式输入。您应该使用适当的库,例如readlinencurses

为了说明为什么这很重要,想象用户输入“foo42”并按回车。你会希望程序现在说“对不起,你能再次输入吗?”但它不会。相反,它温顺地等待用户输入第二个标记。这当然是而不是你从可用性的角度期待什么。

+1

默认情况下,'std :: cin'绑定到'std :: cout',所以任何输出到'std :: cin'会自动刷新'std :: cout'。 –

+0

@James Ah,很高兴知道。你说的是“默认情况下”......我该如何改变它? /编辑发现它,'ios :: tie'。 –