1

我一直在学习 C++,这段代码来自一个简单的评分程序。但是当我尝试获取用户输入时,出现了问题。如果我输入一个数字,无论是小于 0 还是大于 100,或者介于两者之间,我的循环都可以正常工作。但是,如果我输入任何字母或任何非字母数字字符(例如:+、(、% 等),我会得到一个无限循环,并永远打印“请输入介于 0 和 100 之间的等级值”。我在做什么错误的?

谢谢。

int _tmain(int argc, _TCHAR* argv[])
{
using namespace std;

int grade = -1; // grade will hold grade value; initialized to -1
do {
    cout << "Please enter a grade value between 0 and 100." << "\n";
    cin >> grade;
} while (grade < 0 || grade > 100);

cout << grade << "\n";

printGrade(grade);

return 0;
}
4

4 回答 4

2

如果cin>>grade失败(又名不能解析为 int)它不会消耗流。你可以试试:

int main()
{ using namespace std;

int grade = -1; // grade will hold grade value; initialized to -1
do {
    cout << "Please enter a grade value between 0 and 100." << "\n";
    if (!(cin >> grade))
    {
      cin.clear();
    }
} while (grade < 0 || grade > 100);

cout << grade << "\n";

return 0;

}

但这只是问题的一部分。确实,您应该使用 std::getline 并将成绩解析为整行以正确输入。

于 2013-08-08T19:56:57.497 回答
1

如果 cin 没有接收到数据类型 (int) 的有效输入,则变量等级不会更改并保持为 -1。您可以像这样测试输入是否成功

bool success = (cin >> grade);
if (! success)
{
    cin.clear();
    cout << "bad input\n";
    break;
}

您也可以将其用作快捷方式if (! (cin >> grade))

请注意,您需要在再次使用它之前clear的错误状态。cin

于 2013-08-08T19:55:21.030 回答
1

我很确定 cin 失败了,所以你可能需要重置它的失败标志或类似的东西。

将此添加到您的循环中:

if (cin.fail())
{
    cout << "failed";
    cin.clear();
}
于 2013-08-08T19:56:18.730 回答
1

在获得有效输入之前正确安全地阅读比您想象的要复杂得多。如果输入无效,例如字母,则流将设置为“失败”状态,并拒绝读取更多字符,直到您清除该状态。但是即使你清除了状态,那个输入仍然在那里等待,顺便说一句。所以你必须忽略这些字符。最简单的做法是在下一个回车键之前忽略所有内容,然后再次尝试输入。

但它变得更加复杂,因为如果流有错误,它会被设置为“坏”状态,或者如果它到达流的末尾,它会被设置为“eof”状态。这两个都不可恢复,因此您必须检测它们并退出程序以避免无限循环。更令人恼火的是,istreams 有一个功能.fail(),但它会检查它是否在fail or bad中,这在我看来几乎没用。所以我写了一点invalid_input来检查流是否可以继续。

请注意,如果输入超出范围,则手动 get_grade设置标志。fail

#include <iostream>
#include <stdlib.h>
#include <limits>

bool invalid_input(std::istream& in)
{return in.rdstate() == std::ios::failbit;}

std::istream& get_single_grade(std::istream& in, int& grade) {
    std::cout << "Please enter a grade value between 0 and 100." << "\n";
    if (in>>grade && (grade<0 || grade>100))
        in.setstate(std::ios::failbit);
    return in;
}

bool get_grade(std::istream& in, int &grade) {
    while(invalid_input(get_single_grade(in, grade))) { //while we failed to get data
         in.clear(); //clear the failure flag
         //ignore the line that the user entered, try to read the next line instead
         in.ignore(std::numeric_limits<std::streamsize>::max(),'\n'); 
    }
    return in.good();
}

int main(int argc, char* argv[]) {    
    int grade = -1; // grade will hold grade value; initialized to -1
    if (get_grade(std::cin, grade) == false) {
        std::cerr << "unxpected EOF or stream error!\n";
        return false;
    }    
    std::cout << grade << "\n";
    return EXIT_SUCCESS;
}

正如您在此处看到的,当给出超出范围的数字、文件结尾、流失败或无效字符时,这不会进入无限循环。

于 2013-08-08T20:32:03.663 回答