My issue lies in the minimum function toward the end and the program pulls from a fill of about 25 names with 5 grades each. The average and maximum are running smoothly but I can't seem to hammer out the minimum. I managed to get it to pull a few names but then the program crashes. Can anyone help me understand what I am overlooking here? Please and thank you.
If you plug it in a compiler the min function is located between the 200-250 lines and a simple txt file is used to pull names and grades from.
// Headers
#include <iostream> // cout, cin
#include <cstdlib> // exit()
#include <string> // strings
#include <fstream> // file processing
#include <iomanip> // stream manipulation
using namespace std;
// Global variables
const int MAX_STUDENTS = 25; // We will not process more than 25 students even if the file contains more
const int MAX_GRADES = 5; // Each student has exactly 5 grades
const string FILENAME = "NamesGrades.txt"; // The name of the file that you will read
// Function declarations
int loadStudentNamesGrades(string students[], int grades[][MAX_GRADES], string fileName, int maxStudents);
void displayAverages(string students[], int grades[][MAX_GRADES], int studentCount);
void displayMax(string students[], int grades[][MAX_GRADES], int studentCount);
void displayMin(string students[], int grades[][MAX_GRADES], int studentCount);
string getLetterGrade(double grade);
int getLongestNameLength(string students[], int studentCount);
int main()
{
int studentCount = 0; // You need one to keep up with the actual number of students
int grades[MAX_STUDENTS][MAX_GRADES]; // You need a two dimensional arry for the grades of the students
string students[MAX_STUDENTS]; // You need and array of strings for the student names
char choice; // You need a variable to hold the choice of the user for the menu
// Get students and grades
studentCount = loadStudentNamesGrades(students, grades, FILENAME, MAX_STUDENTS);
// Loop until user says to quit (Do loop suggested)
do
{
// present menu and get user's choice
cout << "\nGrade Report Program\n\n";
cout << "\t1. Display Average Grade\n";
cout << "\t2. Display Maximum Grade\n";
cout << "\t3. Display Minimum Grade\n";
cout << "\t4. Quit Program\n";
cout << "\nEnter your choice (1-4): ";
cin >> choice;
// Process the choice
switch( choice )
{
case '1': // Average
displayAverages(students, grades, studentCount);
break;
case '2': // Maximum
displayMax(students, grades, studentCount);
break;
case '3': // Minimum
displayMin(students, grades, studentCount);
break;
case '4': // Quit
break;
default:
cout << "Invalid option.\n\n";
}
if(choice != '4' )
{
cout << endl;
system("PAUSE");
system("CLS");
}
} while( choice != '4' );
cout << endl;
return 0;
}
/***********************************************************
loadStudentNameGrades opens and read fileName. It will read in two strings, concatenate them, and then save
to the students array. It then reads five integers and save each to the grades array. The function will return
the actual number of student/grade combinations read
PARAM: students is an array of strings that can hold up ot maxStudents values
grades is a two dimensional array for holding the grades of each student
fileName is the name of the file that will be opened and read
maxStudents is the maximum number of students that we will read from the file
PRE: students[] is large enough to contain up to maxStudents elements
grades[] is large enough ot contain up to maxStudents elements
POST: students[] contains the names of up to maxStudents
grades[][] contains the grades for up to maxStudents
The number of student/grade combinations actually read from the file is returned. This value can range
between 0 <= numStudents <= maxStudents
NOTE: students[] and grades[] are meant to be parralel arrays. students[0] and grades[0] are the same student
************************************************************/
// Check 16:15
int loadStudentNamesGrades(string students[], int grades[][MAX_GRADES], string fileName, int maxStudents)
{
ifstream inFile; // input file stream
string studentsName, letterGrade; // Name of the student and grade character (char)
int numStudents = 0; // number of students actually read
// Open the file
inFile.open(fileName.c_str());
if( inFile.fail())
{
cout << "Could not open file" << endl;
system("PAUSE");
exit(1);
}
for( int i = 0; i < maxStudents && (inFile >> studentsName >> letterGrade); i++, numStudents++)
{
for( int j = 0; j < MAX_GRADES; j++ )
{
inFile >> grades[i][j];
}
students[i] = studentsName + " " + letterGrade;
}
inFile.close();
return numStudents;
}
/***********************************************************
displayAverages calculates the average of each student and displays the
students name, average, and letter grade of the average in a table
PARAM: students[] is an array of strings that contains the names of studentCount students
grades[] is an array of integers that contains the grades of studentCount students
studentCount contains the value of the number of elements in the students[] and grades[] arrays
PRE: students[] and grades[] contain values for studentCount elements
POST: table of student names, averages, and letter grades is displayed
************************************************************/
// Check 16:15
void displayAverages(string students[], int grades[][MAX_GRADES], int studentCount)
{
double average; // Average grades of students
int total; // total of all grades (accumulator)
int maxLength = getLongestNameLength(students,studentCount);
cout << setprecision(1) << fixed << showpoint;
// Setup table header
cout << "\n\nGrade Averages\n";
cout << setw(maxLength + 1) << left << "Name" << setw(4) << right << "Average" << setw(6) << "Grade" << endl;
for( int i = 0; i < studentCount; i++ )
{
cout << setw(maxLength + 1) << left << students[i];
total = 0;
for( int j = 0; j < MAX_GRADES; j++ )
{
total += grades [i][j];
}
average = (double)total / MAX_GRADES;
cout << setw(7) << right << average << setw(6) << getLetterGrade(average) << endl;
}
}
/***********************************************************
displayMax calculates the maximum grade of each student and displays the
students name, maximum grade, and letter grade of the maximum grade in a table
PARAM: students[] is an array of strings that contains the names of studentCount students
grades[] is an array of integers that contains the grades of studentCount students
studentCount contains the value of the number of elements in the students[] and grades[] arrays
PRE: students[] and grades[] contain values for studentCount elements
POST: table of student names, maximum grades, and letter grades is displayed
************************************************************/
// Check 16:15
void displayMax(string students[], int grades[][MAX_GRADES], int studentCount)
{
int maxGrade;
int maxLength = getLongestNameLength(students,studentCount);
cout << "\n\nGrade Maximums\n";
cout << setw(maxLength + 1) << left << "Student" << setw(4) << right << "Max" << setw(6) << "Grade" << endl;
for( int i = 0; i < studentCount; i++ )
{
cout << setw(maxLength + 1) << left << students[i];
maxGrade = 0;
for( int j = 0; j < MAX_GRADES; j++ )
{
if(maxGrade < grades [i][j]) maxGrade = grades [i][j];
}
cout << setw(4) << right << maxGrade << setw(6) << getLetterGrade(maxGrade) << endl;
}
}
/***********************************************************
displayMin calculates the minimum grade of each student and displays the
students name, minimum grade, and letter grade of the minimum grade in a table
PARAM: students[] is an array of strings that contains the names of studentCount students
grades[] is an array of integers that contains the grades of studentCount students
studentCount contains the value of the number of elements in the students[] and grades[] arrays
PRE: students[] and grades[] contain values for studentCount elements
POST: table of student names, minimum grades, and letter grades is displayed
************************************************************/
/* Notes:
Program seems to pull 2 names and freeze on the third. Unsure as to why?
Assigns Leslie Carter 36C and code seems to break down afterwords.
Issue is undetected any where else and seems to be isolated in this function.
*/
void displayMin(string students[], int grades[][MAX_GRADES], int studentCount)
{
int minGrade;
int maxLength = getLongestNameLength(students,studentCount);
cout << "\n\nGrade Minimums\n";
cout << setw(maxLength + 1) << left << "Student" << setw(4) << right << "Min" << setw(6) << "Grade" << endl;
for( int i = 0; i < studentCount; i++ ) // > is null result, < is result
{
cout << setw(maxLength + 1) << left << students[i];
minGrade = 101; // Produced a result in the correct direction
for( int j = 0; j < MAX_GRADES; j++ )
{
if(minGrade > grades [i][j]) minGrade = grades [i][j]; // Produced a result in the correct direction
}
cout << setw(4) << right << minGrade << setw(6) << getLetterGrade(minGrade) << endl;
}
}
/***********************************************************
getLetterGrade converts a numerical grade to a letter grade
PARAM: grade is the numerical grade to convert. Expected range is 0 <= grade <= 100
PRE: grade contains a value in the correct range
POST: The corresponding letter grade of the numerical grade is returned
************************************************************/
// Check 16:15
string getLetterGrade(double grade)
{
if(grade > 90 )
return "A";
else if( grade > 80)
return "B";
else if( grade > 70)
return "C";
else if( grade > 60)
return "D";
else if( grade > 50)
return "F";
}
/***********************************************************
getLongestNameLength returns the length of the longest string from a list of strings
PARAM: students[] is an array of strings that contains the name of students
studentCount is the size of the students[] array
PRE: students[] contains studentCount names
POST: The length of the longest string in students[] is returned
************************************************************/
// Check 16:15
int getLongestNameLength(string students[], int studentCount)
{
int maxLength = 0;
for( int i = 0; i < studentCount; i++)
{
if( students[i].length() > maxLength ) maxLength = students[i].length();
}
return maxLength;
}
Your getLetterGrade function doesn't return anything when grade is less than 50. Try to build with as many warnings turned on as possible. -Wall would have warned you about this mistake.
Related
The final result cannot be displayed.
/*A Teacher has five students who have taken four tests. The teacher uses the following grading scale to assign a letter grade to a student, based on the average of his or her four test scores:
90-100 A
80-89 B
70-79 C
60-69 D
0-59 F
Write a program that uses an array of string objects to hold the five students' names, an array of five characters to hold the five students' letter grades, and five arrays of four doubles each to hold each student's set of test scores. enter code here
The program should allow the user to enter each student's name, and his or her four test scores. It should then calculate and display each student’s average test score, and a letter grade based on the average.
Input Validation: Do not accept test scores less than zero or greater than 100.*/
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
const int SUBJECT=4,STUDENT=5;
string name[5];
char grade[5];
double score[SUBJECT][STUDENT];
double average[5];
int i,j,k,l;
for (k=0;k<STUDENT;k++)
{
cout<<"Enter the name of student "<<k+1<<":"<<endl;
getline(cin,name[k]);
}
for (i=0;i<STUDENT;i++)
{
double sum=0;
for (j=0;j<SUBJECT;j++)
{
cout<<"Enter the test scores of subject "<<j+1<<" for "<<name[i]<<":";
cin >> score[i][j];
while (score[i][j] < 0||score[i][j] > 100)
{
cout<<"Invalid test score! Test scores can't be less than 0 or greater than 100."<<endl;
cout<<"Enter again the test scores of subject "<<j+1<<":";
cin >> score[i][j];
}
sum+=score[i][j];
average[i]=sum / SUBJECT;
}
}
cout<<setw(30)<<"Student's name"<<setw(25)<<"Average test score"<<setw(15)<<"Letter Grade"<<endl;
cout<<"------------------------------------------------------------------------------------------"<<endl;
for (l=0;l<STUDENT;l++)
{
if (average[l]>=90)
{
grade[l]='A';
}
else if (average[l]<90 && average[l]>=80)
{
grade[l]='B';
}
else if (average[l]<80 && average[l]>=70)
{
grade[l]='C';
}
else if (average[l]<70 && average[l]>=60)
{
grade[l]='D';
}
else
{
grade[l]='F';
}
cout<<setw(30)<<name[l]<<setw(25)<<average[l]<<setw(9)<<grade[l];
}
return 0;
}
The final result name,average and grade did not be displayed before the program terminated.
There are several issues in your code :
In this line cin >> score[i][j]; , i is related to a student and j is related to a subject, while the declaration was score[SUBJECT][STUDENT]
the average must be calculated after the subject loop
you should avoid magic constants, like in name[5]
It is better to avoid using namespace std;
It is better to better encapsulate variables such as i, j, and therefore not to declare them as global
This is a working example. Note that the final output still needs to be optimised but I let you do it!
#include <iostream>
#include <iomanip>
#include <string>
//using namespace std;
int main()
{
const int SUBJECT = 4,STUDENT = 5;
std::string name[STUDENT];
char grade[STUDENT];
double score[STUDENT][SUBJECT];
double average[STUDENT];
for (int i = 0; i < STUDENT;i++)
{
std::cout << "Enter the name of student " << i+1 << " : " << std::endl;
getline (std::cin,name[i]);
}
for (int i = 0; i < STUDENT; i++)
{
double sum = 0;
for (int j = 0; j < SUBJECT; j++)
{
std::cout << "Enter the test scores of subject "<<j+1<<" for "<<name[i]<<": ";
std::cin >> score[i][j];
while (score[i][j] < 0||score[i][j] > 100)
{
std::cout<<"Invalid test score! Test scores can't be less than 0 or greater than 100." << "\n";
std::cout<<"Enter again the test scores of subject " << j+1 << ": ";
std::cin >> score[i][j];
}
sum += score[i][j];
}
average[i] = sum / SUBJECT;
}
std::cout << std::setw(30) << "Student's name" << std::setw(25) << "Average test score" << std::setw(18) << "Letter Grade" << "\n";
std::cout<<"------------------------------------------------------------------------------------------" << "\n";
for (int i = 0;i < STUDENT; i++)
{
if (average[i]>=90)
{
grade[i]='A';
}
else if (average[i]<90 && average[i]>=80)
{
grade[i]='B';
}
else if (average[i]<80 && average[i]>=70)
{
grade[i]='C';
}
else if (average[i]<70 && average[i]>=60)
{
grade[i]='D';
}
else
{
grade[i]='F';
}
std::cout<<std::setw(30)<<name[i]<<std::setw(25)<<average[i]<<std::setw(20)<<grade[i]<<"\n";
}
return 0;
}
How about adding a <<endl statement to the last cout expression. This should flush the internal buffer to the output.
Good afternoon, I'd like to preface by saying this is my first semester working with C++, so I apologize if the answers to the errors I've run into are obvious/simple to answer.
I am trying to implement a program that requests a file from a user that contains a range of grades from students (total of 20). The program asks the user for the range inputs for traditional letter grades (i.e. A = 90-100, B = 80-89, C = 70-79, etc to F), then tallies the number of grades in the input file the user provided.
As of now my program loops through each letter grade to gather the grade range from the user, but I have issues when it comes to tallying the number of grades in the file. It keeps outputting "the number of grades in this range is 29."
(Side note, my code also produces a histogram based off of the tallied number of each grade in the file. Obviously, my histogram output looks super whack at the moment because my tally function needs some fixing.)
Again, apologies if the answer to this is simple. I am very new at this and am learning as I go. Thanks for reading.
#include "SFML/Graphics.hpp"
#include <iostream>
#include <fstream>
#include <string>
const float WIDTH = 550.0; // width of the window for display
const float HEIGHT = 750.0; // height of the window for display
const int FONT_SIZE = 25; // character size
const float LEFT_X = 100.0; // Left X position for label
const float LOW_Y = 700.0; // LOW Y position for label
const float HIGH_Y = 50.0; // HIGH Y position for label
using namespace std;
void readConfig() {
int numGrades = 5;
int maxInGrade = 20;
string filename;
cout << "Enter the number of possible different grades: " << endl;
cin >> numGrades;
cout << "Enter the maximum number of students receiving the same letter grade: " << endl;
cin >> maxInGrade;
cout << "Enter the filename containing the scores: " << endl;
cin >> filename;
}
void initFrequency() {
string letters;
int numGrades = 5;
int freqLetters, low, high;
//below defines the lowest range for each grade
int grade_range_a = 90;
int grade_range_b = 80;
int grade_range_c = 70;
int grade_range_d = 60;
int grade_range_f = 0;
cout << "For each grade enter the" << endl << endl
<< "(1) string representing the grade," << endl
<< "(2) lowest possible score in that range, and" << endl
<< "(3) highest possible score in that range." << endl;
ifstream infile("/Users/quinntortellini/CLionProjects/cop3014-p7-f18/cop3014-p8-f18-attempt2/resources/hist.in");
if(!infile)
{
cout << "Can't open file hist.in";
exit(EXIT_FAILURE);
}
int sum=0, number;
for (int i=0; i<numGrades; i++)
{
cout << "Grade string: " << endl;
cin >> letters;
cout << "Lowest possible score: " << endl;
cin >> low;
cout << "Highest possible score: " << endl;
cin >> high;
cout << "The number of grades in this range is " << endl;
while (infile >> low)
{
if (low == grade_range_a||grade_range_b||grade_range_c||grade_range_d||grade_range_f);
counter = counter += 1;
}
{
cout << counter << endl;
}
infile.close();
}
}
int main() {
int numGrades = 5; // number of different letter grades
int maxInGrade = 20; // maximum number of students in any letter grade
string filename; // name of input file containing scores
//
// implementing readConfig, initializes numGrades, maxInGrade, and
// filename
//
readConfig();
string letters[numGrades]; // each entry represents string representing the grade
int freqLetters[numGrades]; // each entry records occurrence of grades corresponding
// to the letter grade
initFrequency();
//
//
//
sf::RenderWindow window(sf::VideoMode(600, 800), "COP3014 Grade Histogram");
sf::Font font;
font.loadFromFile("resources/arial.ttf");
// You are free to change the following code. However, as it is, it should work
sf::Text min, max;
min.setFillColor(sf::Color::Yellow);
min.setFont(font);
min.setString("0");
min.setCharacterSize(FONT_SIZE);
max.setFillColor(sf::Color::Yellow);
max.setFont(font);
max.setString(to_string(maxInGrade));
max.setCharacterSize(FONT_SIZE);
min.setPosition(LEFT_X-FONT_SIZE*2, LOW_Y-FONT_SIZE);
max.setPosition(LEFT_X-FONT_SIZE*2, HIGH_Y-FONT_SIZE/2);
sf::RectangleShape bars[numGrades];
sf::Text labels[numGrades];
float x_incr = (WIDTH - 100)/numGrades;
float x_offset = LEFT_X+FONT_SIZE;
float height_unit_pixels = (HEIGHT - (HIGH_Y + FONT_SIZE)) / maxInGrade;
int count = 0;
for (int i=0; i < numGrades; i++) {
float height = freqLetters[i] > maxInGrade ? maxInGrade : freqLetters[i];
bars[i].setSize(sf::Vector2f(x_incr-50, height*height_unit_pixels));
bars[i].setPosition(x_offset+x_incr/2, LOW_Y);
bars[i].rotate(180);
labels[i].setFillColor(sf::Color::Yellow);
labels[i].setFont(font);
labels[i].setString(letters[i]);
labels[i].setCharacterSize(FONT_SIZE);
labels[i].setFillColor(sf::Color::Red);
labels[i].setPosition(bars[i].getPosition().x-FONT_SIZE, LOW_Y+FONT_SIZE);
x_offset += x_incr;
}
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
window.close();
break;
default:
window.clear();
window.draw(min);
window.draw(max);
for (int i = 0; i < numGrades; i++) {
window.draw(bars[i]);
window.draw(labels[i]);
}
window.display();
}
}
}
return 0;
}
This program will need to handle all grades for 10 students.
Each student has a first and last name, an id number,
3 homework grades, 3 labs grades, 3 test grades, and 1 final exam grade.
display the final course grade in both numbered and letter version
The equation only works for the first set of grades then it adds a little bit to the next average I just can't figure out whats wrong.
/*This program will need to handle all grades for 10 students.
Each student has a first and last name, an id number,
3 homework grades, 3 labs grades, 3 test grades, and 1 final exam grade.
display the final course grade in both numbered and letter version
*/
#include <iostream> // main library
#include <string> //enables use of strings
#include <iomanip> // for setw
#include <Windows.h> // used to set console title
using namespace std; // for cout and cin
const int MAXSTUDENTS = 2;
const int MAXGRADES = 3;
const int MINGRADES = 1;
int main()
{// Get names form students
SetConsoleTitle("Gradebook");
double hwGrade[MAXSTUDENTS][MAXGRADES];
double labGrade[MAXSTUDENTS][MAXGRADES];
double testGrade[MAXSTUDENTS][MAXGRADES];
double feGrade[MAXSTUDENTS];
double final_num_grade[MAXSTUDENTS];
double hwAve =0, labAve=0, testAve=0; // this will be used to calculate the averages
string fName[MAXSTUDENTS];
string lName[MAXSTUDENTS];
string line; // to set the two string variables
string id[MAXSTUDENTS]; // id will be a whole number so int was apropiate
//first for statement. ensuere that the program is run 10 times
for (int s = 0; s < MAXSTUDENTS; s++) {
cout << "Enter student's first name: "; // ask the user for the first name
getline(cin, fName[s]); // accepts students first name
cout << "Enter stedent's last name: "; //ask the user for last name
getline(cin, lName[s]); // accepts students last name
cout << "Enter student's id: "; // ask user for student id
getline(cin, id[s]);
// this loop will ask for three homework grades
for (int n = 0; n < MAXGRADES; n++) {
cout << "Homework grade " << n + 1 << " is "; //tells the user waht the program needs
cin >> hwGrade[s][n]; //lets the user input the homework grades
hwAve += hwGrade[s][n];
}
hwAve = hwAve / 3;
// this loop will ask for three lab grades
for (int l = 0; l < MAXGRADES; l++) {
cout << "Lab grade " << l + 1 << " is ";
cin >> labGrade[s][l]; //lets the user input the LAB grades
labAve += labGrade[s][l];
}
labAve = labAve / 3;
//this loop will ask for three test grades
for (int t = 0; t < MAXGRADES; t++) {
cout << "Test grade " << t + 1 << " is ";
cin >> testGrade[s][t]; //lets the user input the test grades
testAve += testGrade[s][t]; // the average is calculated
}
testAve = testAve / 3;
cout << "Final exam grade: "; // asks user for final exam grade
cin >> feGrade[s];
// equation to get the final course grade
final_num_grade[s] = (hwAve * 0.20) + (labAve * 0.25) + (testAve * 0.30) + (feGrade[s] * 0.25);
line.assign(50, '-');
cout << line << endl;
}
for (int i = 0; i < MAXSTUDENTS; i++) {
cout << "Final Course Grade for " << fName[i] << " " << lName[i] << " with the id " << id[i] << " is " // displays name of student
<< showpoint << fixed << setprecision(1) << final_num_grade[i]; //set to 1 decimal place
//if statement shows the letter grade
if (final_num_grade[i] >= 89.5) { //A if student made 89.5 or more
cout << " (A)\n";
}
else if (final_num_grade[i] >= 79.5) { //B if student made 79.5 to 89.4
cout << " (B)\n";
}
else if (final_num_grade[i] >= 69.5) { // C if student made 69.5 yo 79.4
cout << " (C)\n";
}
else if (final_num_grade[i] >= 59.5) { // D if student made 59.5 to 69.4
cout << " (D)\n";
}
else { // F if student made less than 59.4
cout << " (F)\n";
}
}
return 0;
}
You haven't reset these variables to zero : hwAve, labAve, testAve which makes the second student's grade will be slightly higher
I've created a program that allows the user to enter 10 grades. I've used a while loop to store grades in the array, but if the user only has 5 grades to input, he can type done to exit the program.
After the loop has finished, it will then calculate and display. the highest grade, lowest grade, and the average grade within the array
Unfortunately, when the user types done, the program will display the rest of the grade lines that were not entered.
Can you help me find out how to stop the while loop from displaying the rest of unentered grades of the loop?
#include <iostream>
using namespace std;
int main()
{
const int SIZE = 10;
int grade[SIZE];
int count = 0;
int lowestGrade;
int highestGrade;
bool done = false;
cout << "This program is limited to entering up to 10 grades." << endl;
while ( grade[count] != done && count < SIZE)
{
cout << "Enter a grade #" << count + 1 << " or done to quit: ";
cin >> grade[count];
count++;
}
//LOWEST GRADE
lowestGrade = grade[0];
for (count = 0; count < SIZE; count++)
if (grade[count] < lowestGrade)
{
lowestGrade = grade[count];
}
//HIGHEST GRADE
highestGrade = grade[0];
for (count = 0; count < SIZE; count++)
{
if (grade[count] > highestGrade)
{
highestGrade = grade[count];
}
}
//AVERAGE GRADE
double total = 0;
double average;
for (int count = 0; count < SIZE; count++)
total += grade[count];
average = (total / SIZE);
cout << endl;
cout << "Your highest grade is: " << highestGrade << endl;
cout << "Your lowest grade is: " << lowestGrade << endl;
cout << "Your average grade is: " << average << endl;
system("pause");
return 0;
}
Here are two problems with your code.
First:
....
cout << "Enter a grade #" << count + 1 << " or done to quit: ";
cin >> grade[count];
count++;
....
The code above will attepmpt to read word "done" into integer variable, producing 0. Not what you want to do!
Second:
...
for (count = 0; count < SIZE; count++)
...
Code above will try to iterate over all possible elements (SIZE). However, you might have enetered less than that! You need to use count calculated in the previous loop as your boundary (and of course, use a different name for control variable in the loop).
There are a couple of things to unpack here.
Basically, the input you are retrieving is a char * and the >> operator is casting that to an int to fit into your array of grades.
Next what you are checking with grade[count] != done is if the integer in "grade" at the id "count" is not equal to the bool false. This will always return true in this case.
For your use case what you want to be checking is if your input is equal to the char * "done"
This cannot be happening in the predicate of the while loop because your grade array stores only int.
Therefore the simplest solution to the problem in my opinion, is to check whether the input is equal to "done".
If it is you want to set the done boolean to true
Otherwise we can try to cast it to an int and store that in the grades array.
Here is the revised loop:
while (!done && count < SIZE)
{
cout << "Enter a grade #" << count + 1 << " or done to quit: ";
string input = "";
cin >> input;
if (input == "done")
{
done = true;
}
else
{
grade[count] = stoi(input);
}
count++;
}
The following is somewhat outside the scope of the question, but an additionnal advantage to using stoi() is that it ignores input that is not a number, which will shield against someone entering invalid input like "potato". This is why I immediately cast the input into a string.
Use another variable to store the amount ofgrades the user entered. You also cannot store a string in your integer array:
std::string input = "";
while(count < SIZE)
{
cout << "Enter a grade #" << count + 1 << " or done to quit: ";
getline(cin, input);
if(input == "done")
break;
try
{
grade[count] = std::stoi(input);
count++;
}
catch(std::invalid_argument)
{
cout << "not a valid number\n";
}
}
int actualsize = count;
and then use this variable to abort your for loops:
for (int i = 0; i < actualsize; i++)
There are two simple ways to solve your problem:
You can read strings instead of integers and in case the read string is "done", break the loop, else, convert the read string to an integer, something as follows:
```
// rest of the code
int total_count = 0;
while (count < SIZE) {
cout << "Enter a grade #" << count + 1 << " or done to quit: ";
string temp;
cin >> temp;
if(temp == "done") {
break;
} else {
grade[count] = stoi(temp);
count++;
total_count = count;
}
}
// rest of the code
```
If you don't want to use strings, then, assuming grades will be non-negative, you can stop reading input when the user types a negative number, say "-1". So, you will need to do something as follows:
```
// rest of the code
int total_count = 0;
while (count < SIZE) {
cout << "Enter a grade #" << count + 1 << " or -1 to quit: ";
int temp;
cin >> temp;
if(temp == -1) {
break;
} else {
grade[count] = temp;
count++;
total_count = count;
}
}
// rest of the code
```
Also, don't forget to replace SIZE by total_count in rest of the loops i.e. the ones computing 'LOWEST GRADE', 'HIGHEST GRADE' and 'AVERAGE GRADE'.
NOTE: You will have to do #include <string> at the top as well, if you use the first option.
I am tasked with trying to create a histogram from a set of sample values that a user provides. I've created the part of the program that creates the array from sample value input, but now I must take a user input for the histogram. They give min value, max value, and number of bins. So, I'm assuming the number of bins specifies the size of the array for the histogram. But I'm stumped as to how I go to my other array and count how many values are in the specified range for a particular bin. I hope this makes sense. Here is my code for the program thus far:
#include <iostream>
using namespace std;
#define MAX_SAMPLES 100
#define MAX_BINS 20
#define DOUBLE_TOLERANCE 0.0000005
#define EXIT_VALUE -999
int promptUserAndGetChoice(); //function prototype for the menu
//for information describing sample set of data and functions that operated on //those data
class SamplingClass
{
private:
char charID; //the user enters an id for his sample set
int numbOfValues; // the number of good values the user enters
double sampleValues[MAX_SAMPLES]; //for the set of sample values.
//max is 100
public:
bool readFromKeyboard(); //prototype function
bool printToScreen();//protype function
SamplingClass(); //constructor
};
SamplingClass::SamplingClass() //initializing charID
{
charID = 0;
}
bool SamplingClass::readFromKeyboard()
{
int i = 0;
cout << "Enter character identifier for this sample:";
cin >> charID;
cout << "you entered " <<charID << "\n";
cout << "Enter all samples, then enter -999 to end:\n";
while (i < MAX_SAMPLES)
{
cin >> sampleValues[i];
if
(sampleValues[i] < EXIT_VALUE + DOUBLE_TOLERANCE && sampleValues[i] > EXIT_VALUE - DOUBLE_TOLERANCE)
{
break;
}//End if/else
i++;
}//End while
numbOfValues = i;
return true;
}
//this function checks whether charID is empty and then performs accordingly
bool SamplingClass::printToScreen()
{
if (numbOfValues == 0) ///either make a test for existance first or charID
{
cout << "ERROR: Can not print uninitialized sampling!\n";
return false;
}
else
{
cout << "Data stored for sampling with identifier " << charID << ":\n";
cout << "Total samples:" << numbOfValues << "\n";
cout << "Samples (5 samples per line):\n";
int i;
for(i=0; i<numbOfValues;i++)
{
cout << sampleValues[i] << " ";
if (((i+1) % 5) == 0)
{
cout << endl;
}
}
cout << endl;
return true;
}
}
class HistogramClass
{
private:
double minBinValue; //specified by user
double maxBinValue; // specified by user
int numbBins; //specified by user, max of 10
int histoBinCounts[MAX_BINS];
public:
bool setupHistogram(); //prototype function
bool addDataToHistogram(SamplingClass &sampling);//protype function
bool printHistogramCounts();
bool displayHistogram();
};
bool HistogramClass::setupHistogram()
{
cout << "Enter minimum value:";
cin >> minBinValue;
cout << "Enter maximum value:";
cin >> maxBinValue;
cout << "Enter number of bins:";
cin >> numbBins;
cout << "\n";
if (numbBins <= MAX_BINS)
{cin >> numbBins;}
else
cout << "Sorry, the maximum amount of bins allowed is 20. Try again!\n";
}
//function for the menu options that display to user
int promptUserAndGetChoice()
{
cout << "1. Enter a sample set of data values\n";
cout << "2. Print the contents of the current sample set\n";
cout << "3. Reset / Provide values for setting up a histogram\n";
cout << "4. Add the contents of current sample set to histogram\n";
cout << "5. Print bin counts contained in histogram\n";
cout << "6. View the histogram in graphical form\n";
cout << "0: Exit the program\n\n";
}
int main()
{
const int enter_option = 1;
const int printContents_option = 2;
const int reset_option = 3;
const int add_option = 4;
const int printBin_option = 5;
const int viewHist_option = 6;
const int exit_option = 7;
int menuChoice;
SamplingClass sampleSet;
HistogramClass histoSet;
do
{
promptUserAndGetChoice();
cout << "Your Choice: ";
cin >> menuChoice;
if (menuChoice == 1)
{
sampleSet.readFromKeyboard();
cout << "Last Operation Successful: YES\n\n";
}
else if (menuChoice == 2)
{
sampleSet.printToScreen();
}
else if (menuChoice == 3)
{
histoSet.setupHistogram();
}
}
while (menuChoice != 7);
return 0;
}
Each bin in a histograms is typically the same size. So when the user gives you the min, max and number of bins, you can compute the size, and therefore the range, of each bin. Each bin will be of size
bin_size = (max-min)/#_of_bins.
Now to figure out which bin a value goes into, compute
bin = ceil(value/bin_size)
(Or take the floor if you start numbering your bins at 0). And increment the count in this bin. Once you do this for all values, you can print out the count in each bin and this is your histogram.
Update: If min != 0, then the formula is:
bin = (int) (value-min)/bin_size
Using the cast here b/c codemesserupper can't use libs. bin here will be 0-indexed.
If you know the min and max, then any particular value x should be considered to fall into the array at index:
(x - min) / (max - min) * #bins
This will span the range 0..#bins inclusive, so just round down from #bins to #bins-1 when necessary.
EDIT: to be more explicit, and ignoring the object boundaries, the basic approach is to 0 the histoBinCounts then:
for (int i = 0; i < numbOfValues; ++i)
{
double x = sampleValues[i];
int bin = (x - minBinValue) / (maxBinValue - minBinValue) * numbBins;
if (bin >= 0 && bin < numbBins)
++histoBinCounts[bin];
}