【问题标题】:Inputting Grades with Looping C++使用循环 C++ 输入成绩
【发布时间】:2015-07-26 05:43:49
【问题描述】:

我们只对 [0,100] 范围内的 # 感兴趣。可能有超出范围 [0, 100] 的数字,但它们不是我们计算的一部分(即可以输入低于 0 和高于 100 的数字,但在计算和计数器中将被忽略)。 假设我们将 ABCDF 指定为 [85,100]:一个 [75,85): B [65,75): C [55,65): D [0,55): F 对于五个字母等级中的每一个,输出该等级的分数,如果分数不为0,则输出该等级的平均分数。另外,如果有效分数(in [0, 100])不为0,则输出所有分数的平均值

我遇到了这个循环问题。当我输入多个分数时,它会错误地循环它们并为每个输入输出两组分数,而不是上面显示的示例答案。另外,我不确定输入单词时是否正确放置了中断以退出程序。任何帮助将不胜感激!

这是我的代码:

    #include <iostream>
    #include <cmath>
    #include <cstdlib>
    #include <string>
    using namespace std;

    int main(){
        double scores;
        unsigned countA = 0;
        unsigned countB = 0;
        unsigned countC = 0;
        unsigned countD = 0;
        unsigned countF = 0;
        char grade;
        double sumA = 0, sumB = 0, sumC = 0, sumD = 0, sumF = 0;
        cout << "Enter scores: ";
        for (scores; cin >> scores;){
            if (scores > 85 && scores <= 100){
                grade = 'A';
                countA++;
                sumA += scores;
            }
            else if (scores > 75){
                grade = 'B';
                countB++;
                sumB += scores;
            }
            else if (scores > 65){
                grade = 'C';
                countC++;
                sumC += scores;
            }
            else if (scores > 55){
                grade = 'D';
                countD++;
                sumD += scores;
            }
            else{
                grade = 'F';
                countF++;
                sumF += scores;
            }
            if (!cin){
                break;
            }
        if (countA == 0){
            cout << "# A's: 0 " << endl;
        }
        else {
            cout << "# A's: " << countA << " Average = " <<  sumA/countA << endl;
        } if (countB == 0){
            cout << "# B's : 0 " << endl;
        }
        else{
            cout << "# B's: " << countB << " Average = " << sumB /countB << endl;
        } if (countC == 0){
    cout << "# C's: 0 " << endl;
        }
        else{
            cout << "# C's: " << countC << " Average = " << sumC /countC << endl;
        } if (countD == 0){
            cout << "# D's: 0 " << endl;
        }
        else {
            cout << "# D's: " << countD << " Average = " << sumD /countD << endl;
        } if (countF == 0){
            cout << "# F's: 0 " << endl;
        }
        else {
            cout << "# F's: " << countF << " Average = " << sumF /countF << endl;
        }
    }

【问题讨论】:

  • 我修改了我的代码,删除了最后的一堆 if 和 else 语句:cout
  • 我不明白你在说什么问题是,尽量清楚一点。但我可以看到for (scores; cin &gt;&gt; scores;){ 应该是while (cin &gt;&gt; scores){if (!cin){ break; } 是不必要的(如果永远不会是真的)并且应该被删除。
  • Swap for (scores; cin &gt;&gt; scores;) for while (cin &gt;&gt; scores) 做同样的事情(循环直到输入非双精度的内容),但更简洁。 if (!cin) 不需要。并且循环缺少终止括号,使其余代码成为循环的一部分。而且不编译,但你不能总是赢。
  • @user4581301,你应该这样回答,你显然是对的。
  • 我的意思是让我说我​​在我的程序中输入 3 个分数。 96 98 99. 我的程序应该输出“#As: 3 Average = 97.6667”,但它会一次输出每个数字,其中 #As 始终为 1,平均值始终为输入的数字。我也做了这些更改,但它仍然显示相同的格式。我认为这可能是一个大括号问题,但不完全确定@user4581301

标签: c++ loops for-loop while-loop


【解决方案1】:

TL;DR 版本:缺少 for 循环上的右大括号。循环永远不会结束并导致 OP 的输出代码也循环。

长版:

这是工作代码。我改的东西是用cmets标记的。

#include <iostream> //removed a bunch of unused includes.
using std::cin;    // including all of namespace::std is overkill and often
using std::cout;   // leads to hard-to-solve bugs. Only use what you need
using std::endl;

int main()
{
    double scores;
    unsigned countA = 0;
    unsigned countB = 0;
    unsigned countC = 0;
    unsigned countD = 0;
    unsigned countF = 0;
    char grade;
    double sumA = 0, sumB = 0, sumC = 0, sumD = 0, sumF = 0;
    cout << "Enter scores: ";
//    for (scores; cin >> scores;){
    while (cin >> scores) // cleaner
    {
        if (scores > 85 && scores <= 100)
        {
            grade = 'A';
            countA++;
            sumA += scores;
        }
        else if (scores > 75)
        {
            grade = 'B';
            countB++;
            sumB += scores;
        }
        else if (scores > 65)
        {
            grade = 'C';
            countC++;
            sumC += scores;
        }
        else if (scores > 55)
        {
            grade = 'D';
            countD++;
            sumD += scores;
        }
        else
        {
            grade = 'F';
            countF++;
            sumF += scores;
        }
// this test is made redundant by the loop condition
//        if (!cin)
//        {
//            break;
//        }
    } // this was missing. The loop kept going and included all of
      // the following code in the loop.
    if (countA == 0)
    {
        cout << "# A's: 0 " << endl;
    }
    else
    {
        cout << "# A's: " << countA << " Average = " << sumA / countA << endl;
    }
    if (countB == 0)
    {
        cout << "# B's : 0 " << endl;
    }
    else
    {
        cout << "# B's: " << countB << " Average = " << sumB / countB << endl;
    }
    if (countC == 0)
    {
        cout << "# C's: 0 " << endl;
    }
    else
    {
        cout << "# C's: " << countC << " Average = " << sumC / countC << endl;
    }
    if (countD == 0)
    {
        cout << "# D's: 0 " << endl;
    }
    else
    {
        cout << "# D's: " << countD << " Average = " << sumD / countD << endl;
    }
    if (countF == 0)
    {
        cout << "# F's: 0 " << endl;
    }
    else
    {
        cout << "# F's: " << countF << " Average = " << sumF / countF << endl;
    }
}

【讨论】:

  • 谢谢你的解释!!!我被困了一段时间,我真的很感谢你的帮助!
【解决方案2】:

您的问题有点令人困惑,我认为您的主要问题是输出部分。目前您的代码生成this.

如您所见,在输入每个分数后,我们得到了中间输出。要改变这一点,需要将循环分成两个循环:一个用于输入,一个用于在第一个循环之后运行的输出:

while (/* we get scores */) {
 // update the counters and sums
}
for (/* every score */) {
 // print count and average
}

要在循环中生成输出,您需要以某种“可循环”的方式存储数据。目前您有多个局部变量。将其更改为数组(由相应的等级索引)允许我们循环数据:

unsigned counter[5];
double sum [5];
// A -> 0, B -> 1, ..., F -> 4
for (std::size_t it = 0; it < 5; ++it) {
 // use sum[it] and counter[it]
}

但是原始数组(作为原始指针)是邪恶的——只有在绝对必要时才使用它们——我们使用标准库中的std::array。为了简化迭代和改进逻辑封装,最好将每个等级的总和和计数放在一起:

struct grade_info {
 unsigned count = 0;
 double sum = 0;
};
// ... later in the main function
 std::array<grade_info, 5> grades;
 // input
 for (auto const & grade : grades) { // C++11 shorthand to iterate over a collection
  // use grade.count and grade.sum
 }

关于您的意见:

for (scores; cin >> scores;){

这样做是正确的,但有点奇怪。由于scores 只会在该循环内使用,而不是将其声明为main 的局部变量,因此我们只在循环内声明它:

for (double score; // only a single score is in that variable at any time
     cin >> score; // ends the loop on eof or failure to convert to double (when text got entered)
     // no step instructions, the above check does that already
     ) {

现在也无需在循环内测试cinoperator&gt;&gt; 返回(引用)它的第一个参数 cin,因此 for 循环中的测试已经测试了 cin,不需要 if (! cin) { break; }

那么你就有了这样的代码

grade = 'A';

当您从不使用存储在grade 中的值时。删除它。

最后但并非最不重要的是,您的输入验证不起作用(我的测试用例中的 101 被视为 B 级):

if (scores > 85 && scores <= 100) {
 // scores between (85, 100]
}
// scores is either <= 85 OR > 100
else if (scores > 75){
 // scores is in (75, 85] OR > 100
}

理想情况下,您应该将输入验证和业务逻辑分开:

if (not input_is_valid(score)) {
 continue; // the loop
}
// business logic, assuming valid input

所以,最终的代码可能是

#include <iostream>
#include <array>

struct grade_info {
 unsigned count = 0;
 double sum = 0;
 char const name;
 grade_info(char n) : name(n) {
 }
};
bool input_is_valid(double score) {
 return (score >= 0) and (score <= 100);
}
std::size_t score_to_grade_index(double score) {
 if (score >= 85) {
  return 0;
 } else if (score >= 75) {
  return 1;
 } else if (score >= 65) {
  return 2;
 } else if (score >= 55) {
  return 3;
 } else {
  return 4;
 }
}

int main(int, char**) {
 std::array<grade_info, 5> grades {'A', 'B', 'C', 'D', 'F'};
 for (double score; std::cin >> score;) {
  if (not input_is_valid(score)) {
   continue;
  }
  auto index = score_to_grade_index(score);
  ++(grades[index].count);
  grades[index].sum += score;
 }
 for (auto const & grade : grades) {
  std::cout << "# " << grade.name << ": "
                  << grade.count;
  if (grade.count > 0) {
   std::cout << " avg: " << (grade.sum / grade.count);
  }
  std::cout << std::endl;
 }
 return 0;
}

Live here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-29
    • 2014-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多