2012-09-12 67 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的行上的条件既测试了整数的成功分析,也测试了到达行结束(吞噬中间空白)的情况。