使用循环C ++输入成绩

时间:2015-07-26 05:43:50

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

我们只对[0,100]范围内的#感兴趣。可能存在[0,100]范围之外的数字,但它们不是我们计算的一部分(即,可以输入低于0且高于100的数字,但在计算和计数器中将被忽略)。 假设我们将ABCDF指定为     [85,100]:A     [75,85]:B     [65,75]:C     [53,55]:D     [0,55]:F 对于五个字母等级中的每一个,输出该等级的分数,并且如果分数的数量不是0,则输出该等级的平均分数。此外,如果有效分数(在[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;
        }
    }

2 个答案:

答案 0 :(得分:1)

TL; DR版本:缺少for循环的关闭括号。循环永不结束,导致OP的输出代码也循环。

长版:

这是工作代码。我改变的东西标有评论。

SELECT FK_ID , 
       SOME_VALUE as "CURRENT", 
       PREV_VALUE as Previous
FROM (
    SELECT t1.*,
           lag( some_value ) over (partition by fk_id order by some_date ) prev_value
    FROM t1
) x
JOIN t2 on t2.id = x.fk_id
     and t2.fk_current = x.id

答案 1 :(得分:0)

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

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

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

要在循环中生成输出,您需要将数据存储在某些&#34; loopable&#34;办法。目前您有多个局部变量。将其更改为数组(由相应的等级索引)允许我们循环数据:

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>>返回(引用)其第一个参数,即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