C++ How to tally grade range in a file - c++

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;
}

Related

What problem present in my program? Why the final output cannot be displayed

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.

get average grade for 10 students c++

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

Average, Maximum and Minimum assignment for C++

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.

Trouble with an if else if statement c++

I am working on a grade book project that has 5 students that I want to read the names in for and then with an inner loop grab 4 grades for each student. Something is not working on this loop. This what I am getting:
Please enter the name for student 1: Dave
Please enter the grade number 1 for Dave: 100
Please enter the grade number 2 for Dave: 100
Please enter the grade number 3 for Dave: 100
Please enter the grade number 4 for Dave: 10
Please enter the name for student 2: James
Please enter the grade number 5 for James: 100
Please enter the name for student 3: Sam
Please enter the grade number 5 for Sam: 100
Please enter the name for student 4: Jack
Please enter the grade number 5 for Jack: 100
Please enter the name for student 5: Mike
Please enter the grade number 5 for Mike: 100
It should grab 4 grades before it jumps to the next student. I have not been able to figure this out for the last couple hours. Here is the code I have so far:
#include <iostream>
#include <string>
using namespace std;
const int STUDENTS = 5; //holds how many students we have
const int SCORES = 4;
void getNames(string names[], double student1[SCORES], double student2[SCORES],
double student3[SCORES], double student4[SCORES], double student5[SCORES], int SCORES, int STUDENTS);
int main()
{
string names[STUDENTS] = {""};
char grades[STUDENTS] = {""};
double student1[SCORES] = {0};
double student2[SCORES] = {0};
double student3[SCORES] = {0};
double student4[SCORES] = {0};
double student5[SCORES] = {0};
getNames(names, student1, student2, student3, student4, student5, SCORES, STUDENTS);
// Make sure we place the end message on a new line
cout << endl;
// The following is system dependent. It will only work on Windows
system("PAUSE");
return 0;
}
void getNames(string names[], double student1[SCORES], double student2[SCORES],
double student3[SCORES], double student4[SCORES], double student5[SCORES], int SCORES, int STUDENTS)
{
for (int i = 0; i < STUDENTS; i++)
{
cout << "Please enter the name for student " << i+1 << ": ";
cin >> names[i];
cout << endl;
if (i == 0)
{
int count1 = 0;
for (count1; count1 < SCORES; count1++)
{
cout << "Please enter the grade number " << count1+1 << " for " << names[i] <<": ";
cin >> student1[count1];
cout << endl;
}
}
else if (i == 1)
{
int count2 = 0;
for (count2; count2 < SCORES; count2++);
{
cout << "Please enter the grade number " << count2+1 << " for " << names[i] <<": ";
cin >> student2[count2];
cout << endl;
}
}
else if (i == 2)
{
int count3 = 0;
for (count3; count3 < SCORES; count3++);
{
cout << "Please enter the grade number " << count3+1 << " for " << names[i] <<": ";
cin >> student3[count3];
cout << endl;
}
}
else if (i == 3)
{
int count4 = 0;
for (count4; count4 < SCORES; count4++);
{
cout << "Please enter the grade number " << count4+1 << " for " << names[i] <<": ";
cin >> student4[count4];
cout << endl;
}
}
else
{
int count5 = 0;
for (count5; count5 < SCORES; count5++);
{
cout << "Please enter the grade number " << count5+1 << " for " << names[i] <<": ";
cin >> student5[count5];
cout << endl;
}
}
}
}
Thanks for any help on this!
There's some pretty rough stuff going on in here, but the problem is that you have a semi-colon on all your inner loops except the first one:
for (count2; count2 < SCORES; count2++);
Remove the semi-colon, and the stuff in the braces will become part of the loop.
I'm going to suggest you make your code a little tidier and less error-prone by chucking all those function arguments into their own array when you enter the function, like this:
double *scores[5] = { student1, student2, student3, student4, student5 };
Then you take OUT all that repetition - the copy/paste is what caused your problems to begin with:
for (int i = 0; i < STUDENTS; i++)
{
cout << "Please enter the name for student " << i+1 << ": ";
cin >> names[i];
cout << endl;
for (int s = 0; s < SCORES; s++)
{
cout << "Please enter the grade number " << s+1 << " for " << names[i] <<": ";
cin >> scores[i][s];
cout << endl;
}
}
Why can't you use two nested loops like
for (int studix=0, stduix<STUDENTS; studix++) {
//...
for (int gradix=0; gradix<SCORE; gradix++) {
//...
}
//....
}
BTW, the condition could be a more complex one, e.g. with the internal loop being
bool goodgrade=true;
for (int gradix=0; goodgrade && gradix<SCORE; gradix++) {
// you could modify goodgrade or use break; inside the loop
}
Don't forget the possible use of continue and break inside a loop.
And please, take time to read some good C++ programming book
Building on Basile's answer and my comments:
int main()
{
string names[STUDENTS] = {""};
char grades[STUDENTS] = {""};
double student1[SCORES] = {0};
double student2[SCORES] = {0};
double student3[SCORES] = {0};
double student4[SCORES] = {0};
double student5[SCORES] = {0};
double *gradeArray[STUDENTS];
gradeArray[0] = student1;
gradeArray[1] = student2;
gradeArray[2] = student3;
gradeArray[3] = student4;
gradeArray[4] = student5;
for (int studix=0, stduix<STUDENTS; studix++) {
// get the name of the student
for (int gradix=0; gradix<SCORE; gradix++) {
// put the grades in gradeArray[studix][gradix]...
}
//....
}
Yes, I know about 2 D arrays, but I am trying to make explicit how this can be done with "five individual arrays". Clumsy, but I believe this works.

How to count array items within a numeric range

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];
}