C ++家庭作业,坚持一些边缘案例和不寻常的输入

时间:2010-10-16 15:32:10

标签: c++

我将在接下来的几周内完成C ++任务。任务是

  1. 读取一行输入,其中包含0到89之间的3个分数,并从同一行读取名称。
  2. 将这些分数转换为分数,并根据分数给每个学生一个分数。
  3. 我的第一次切割完成了所有这些(尽管是以一种混乱的方式),现在我正在考虑无效的输入。我真正努力的输入是如何处理只是名字的用户:即Smith,B。

    或者,如果其中一个标记包含字母,即10 c 20 Smith,B。

    目前,我的程序只是将其作为一个int读取,我想并尝试继续 - 我希望它将此视为一个字符串并输出:“输入错误:Smith,B。”

    有经验的程序员有没有办法处理这样的事情?我不想在我的代码中到处创建一堆if语句,因为这很难理解。

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    //function to check input validity
    bool validateInput(int mark1, int mark2, int mark3, string name);
    //function to check the scores
    int checkScores(int mark1, int mark2, int mark3);
    
    int main()
    {
        int mark1 = 0, mark2 = 0, mark3 = 0;
        string name;
    
        cin >> mark1 >> mark2 >> mark3;
        getline (cin, name);
        // continue if the input is valid
        if (validateInput(mark1, mark2, mark3, name) == true)
        {
            checkScores(mark1, mark2, mark3);
        }
        else cout << "Bad Input Line: \t" <<
        mark1 << " " << mark2 << " " << mark3
        << " " << name << endl;
    
        return 0;
    }
    
    bool validateInput(int mark1, int mark2, int mark3, string name)
    {
        //return false if the scores are not valid
        if (mark1 < 0 || mark1 > 50 || mark2 < 0 || mark2 > 50 || mark3 < 0 || mark3 > 50)
        {
            return false;
        }
        return true;
    }
    
    int checkScores(int mark1, int mark2, int mark3)
    {
        int mark1Mark = 0, mark2Mark = 0, mark3Mark = 0;
        string candidateType;
        //return the mark for the mark1 test
        if (mark1 <= 10) mark1Mark = 1;
        else if (mark1 <= 20) mark1Mark = 2;
        else if (mark1 <= 30) mark1Mark = 3;
        else if (mark1 <= 40) mark1Mark = 4;
        else if (mark1 <= 50) mark1Mark = 5;
        //return the mark for the mark2 test
        if (mark2 <= 10) mark2Mark = 1;
        else if (mark2 <= 20) mark2Mark = 2;
        else if (mark2 <= 30) mark2Mark = 3;
        else if (mark2 <= 40) mark2Mark = 4;
        else if (mark2 <= 50) mark2Mark = 5;
        //return the mark for the mark3 test
        if (mark3 <= 10) mark3Mark = 1;
        else if (mark3 <= 20) mark3Mark = 2;
        else if (mark3 <= 30) mark3Mark = 3;
        else if (mark3 <= 40) mark3Mark = 4;
        else if (mark3 <= 50) mark3Mark = 5;
    
        if (mark1Mark >= 5 && mark2Mark >= 5 && mark3Mark >= 5)
            candidateType = "Exceptional";
        else if (mark3Mark >= 2 && mark2Mark >= 2  && mark1Mark >= 2)
            candidateType = "Pass";
        else candidateType = "Fail";
    
        cout << mark1Mark << " " << mark2Mark << " " << mark3Mark << " " << candidateType;
    }
    

3 个答案:

答案 0 :(得分:4)

到目前为止,你做得还不错。我建议你不要使用

cin >> mark1 >> mark2 >> mark3; 

cin因没有错误检查而臭名昭着,将内容留在输入中,而不是获取换行符等等。

而是将整行全部一次放入带有getline的字符串中,并使用std :: stringstream

进行错误检查解析
string input = "";
getline(cin, input);
stringstream instream(input);
if (instream >> mark1) {
  // number ok do something
}
else {
  // not a number in the input
  // report it
}

答案 1 :(得分:1)

无法转换格式错误的输入需要使用cin.fail()进行检查,如下所示。

   int x;
   cout << "enter choice:";
   cin >> x;
   while (x < 1 || x > 4)
   {
      cout << "Invalid choice, try again:";
      cin >> x;
      // not a numeric character, probably
      // clear the failure and pull off the non-numeric character
      if (cin.fail())
      {
         cin.clear();
         char c;
         cin >> c;
      }
   }

cin正在帮助您在此处预先验证输入,您只需要检查它告诉您的内容。

如果你想在错误时输出整个坏行,你可以像这样重构代码来捕获它然后解析,保留输入以显示错误:

string rawLine;
getline(cin, rawLine);
stringstream lineStream;

int mark1, mark2, mark3;
string name;
lineStream >> mark1 >> mark2 >> mark3 >> name;

if (lineStream.fail() ||  // malformed input
        !validateInput(mark1, mark2, mark3, name))  
                              // input valid but semantically incorrect
{
    cerr << "bad line :" << rawLine << endl;
}

答案 2 :(得分:0)

感谢您提供的所有帮助。我现在使用stringstream获取整行并检查输入 - 更可靠。我的main()现在看起来像这样:

int main()
{
string input;
getline(cin, input);
stringstream instream(input);

int mark1 = 0, mark2 = 0, mark3 = 0;
string name;
instream >> mark1 >> mark2 >> mark3 >> name;
// continue if the input is valid
if (validateInput(mark1, mark2, mark3, name) == true)
{
    checkScores(mark1, mark2, mark3);
}
else cout << "Bad Input Line: \t" << input << endl;

return 0;
}