我必须显示学生成绩的直方图。我已将成绩存储在dyn中。数组,但我的目标是将它们存储在向量中。解决这个问题的正确方法是什么?希望这有道理。
编辑:
我尝试使用向量
void displayHistogram(int minGrade, vector<int> ptrV) {
cout << endl;
for (int i = 0; i <= minGrade; i++) {
if (ptrV[i] != 0) {
cout << "Number of " << i << "'s: " << ptrV[i] << endl;
}
}
}
void histogram() {
int minGrade = 0, grade;
const int grade_max = 100;
vector<int> ptrV(grade_max, 0);
cout << "Enter the student's grades (-1 to stop entering): \n";
do {
cin >> grade;
if (grade > minGrade) {
minGrade = grade;
}
if (grade >= 0) {
ptrV.push_back(grade);
}
} while (grade != -1);
displayHistogram(minGrade, ptrV);
}
答案 0 :(得分:1)
但是我的目标是将它们存储在向量中。
问题似乎是您已经确定矢量的大小以容纳grade_max
个条目。但是,在填充矢量时,您正在使用push_back
。通过使用push_back
,您将在向量的末尾添加更多条目,这不是您想要执行的操作。
解决方案是
vector<int> ptrV(grade_max, 0);
更改为此vector<int> ptrV;
并仅留下对push_back
的呼叫,或者vector<int> ptrV(grade_max, 0);
,而只使用ptrV[i] = grade;
答案 1 :(得分:1)
您的基本错误是,您试图将向量强制为原始数组。它为您做东西,让它。例如,它知道尺寸。你不需要
void displayHistogram(int minGrade, vector<int> ptrV) {
cout << endl;
for (int i = 0; i <= minGrade; i++) {
相反,您可以使用vector::size
:
void displayHistogram(vector<int> ptrV) {
cout << endl;
for (size_t i=0; i<ptrV.size(); i++) {
(更好的做法是:void displayHistogram(const vector<int>& ptrV)
表示此处ptrV并未更改,并避免每次使用引用调用函数时都将其复制。)
(如果您不使用i
,因为它是年级,并且如果您使用的是较新的编译器,则建议为每个循环使用a。通常是这样做的方式,您有一种罕见的情况并非如此。)
同样,您首先设置向量的大小,然后再增加它,对我而言,这意味着您不信任它:
vector<int> ptrV(grade_max, 0);
在这一点上,您有一个包含一百个全为零的条目的向量。如果只需要一百个条目,则无需稍后调整大小。 vector::push_back
调整其大小。但是请注意,将其设置为100意味着[100]不是有效位置,最后一个是[99],因为我们开始从零开始计数。您需要将其设置为101,以使有效地址的范围为零和百。
我会将您的代码更改为:
const int grade_max = 100;
vector<int> ptrV(grade_max+1, 0); //changed it to +1 here as prtV[100] should be legal
cout << "Enter the student's grades (-1 to stop entering): \n";
while (true)
{
int grade; // put stuff in the smallest scope possible
cin >> grade;
if(grade == -1) break; // doing that here means we don't have to think about it anymore - the do while does it at last, I do it at first, handling all the special cases at the start and then assume I have the regular case.
if(grade < 0 or grade > grade_max) continue; // continue jumps to the top of the most inner loop. Note that I make sure to catch illegal but possible input.
ptrV[grade] += 1; // personal preference, I use ++ only to iterate
}
displayHistogram(ptrV);
我使用while(true)
重新编写了结构,我认为这样做的方式更直观,但是会有人对此表示反对,并且还会写类似的东西
if(grade == -1)
{
break;
}
为此,有一些很好的论据,主要是一个良好的惯例例程,总是做大括号来避免错误。但是,我更喜欢一种衬纸来减少冗长。
一种改进还可以告诉用户输入错误:
if(grade < 0 or grade > grade_max)
{
cout << "Input not in valid range. Please choose number within 0 to " << grade_max << endl;
continue;
}
现在,要做的另一件事是顺便说一下离开程序部分。
选择class GradeHistogram
,其中包含所有这些功能,就像
GradeHistogram histogram;
histogram.take_input();
histogram.display();
但这是当您使代码正常工作时。
(CodeReview上我的回答更多是一篇评论,但我认为这是您所需要的,而不是小的修复。这是我只能向您推荐的代码,在CodeReview上运行。)
答案 2 :(得分:0)
如果要显示的是直方图,那么最简单的方法是使用std::map
(从年级到年级)。
类似这样的东西:
#include <iostream>
#include <map>
int main() {
std::cout << "Enter the student's grades (-1 to stop entering): \n";
std::map<int, int> grades_map;
int input_grade = -1;
do {
cin >> input_grade;
if (input_grade > -1) {
grades_map[input_grade]++;
}
} while (input_grade != -1);
// Print histogram
for (const auto& [grade, count] : grades_map) {
std::cout << "Students with grade << grade << ": ";
for (int i = 0; i < count; ++i) {
std::cout << '*';
}
std::cout << '\n';
}
}