The output for this program, thanks to you guys, is fixed. Except for the studentNumber. I read the comment that I never set a value to it and that confused me.
void process_file(ifstream& input)
{
int thisStudent = 0;
StudentRecord student = StudentRecord();
while (thisStudent++ < CLASS_SIZE)
{
student.input(input, thisStudent);
student.computeGrade();
student.output();
}
}
would this not set studentNumber equal to 0 then add +1 every time it runs through the loop.
// Author:
// Assignment 8
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
ofstream outputfile("output.txt");
const int MAX_FILE_NAME = 35;
const int CLASS_SIZE = 5;
class StudentRecord
{
public:
void input( ifstream& input,int studentid);
void computeGrade();
void output();
private:
int studentNumber;
double exam1;
double exam2;
double exam3;
double exam4;
double average;
char grade;
};
void open_input(ifstream& input, char name[]);
void process_file(ifstream& input);
int main()
{ char again;
char file_name[MAX_FILE_NAME + 1];
ifstream input_numbers;
cout << "This program can calculate the exam average and grade for\n"
<< "each student.\n" << endl;
system("pause");
do
{
system("cls");
open_input(input_numbers, file_name);
process_file(input_numbers);
input_numbers.close();
cout << "\nDo you want to process another file (Y/N)? ";
cin >> again;
cin.ignore(256, '\n');
} while ( again == 'y' || again == 'Y');
cout << "\nEnd of Program!" << endl;
outputfile << "\n\nThanks for using GradeCalc!\f";
outputfile.close();
return 0;
}
void process_file(ifstream& input)
{
int thisStudent = 0;
StudentRecord student = StudentRecord();
while (thisStudent++ < CLASS_SIZE)
{
student.input(input, thisStudent);
student.computeGrade();
student.output();
}
}
void open_input(ifstream& input, char name[])
{ int count = 0;
do
{ count++;
if (count != 1)
{ cout << "\n\aInvalid file name or file does not exist. Please try again."
<< endl;
}
cout << "\nEnter the input file name (maximum of " << MAX_FILE_NAME
<< " characters please)\n:> ";
cin.get(name, MAX_FILE_NAME + 1);
cin.ignore(256, '\n');
input.clear();
input.open(name,ios_base::in);
} while (input.fail() );
}
void StudentRecord::input(ifstream& input, int studentid)
{
input >> exam1 >> exam2 >> exam3 >> exam4;
}
void StudentRecord::computeGrade()
{
average = (exam1 + exam2 + exam3 + exam4) / 4 ;
if (average >= 90)
grade = 'A';
else if (average >= 80)
grade = 'B';
else if (average >= 70)
grade = 'C';
else if (average >= 60)
grade = 'D';
else if (average < 60)
grade = 'F';
}
void StudentRecord::output()
{
cout << "\n\nThe record for student number:" << setw(8) << studentNumber << endl;
cout << "The exam grades are:" << setw(8) << exam1 << exam2 << exam3 << exam4 << endl;
cout << "The numeric average is:" << setw(8) << average << endl;
cout << "and the letter grade assigned is:" << setw(8) << grade << endl;
}
Well, studentNumber is garbage because you never put a value in it. So it just has whatever happened to already be in memory at that location.
The exam grades print out wrong because commas in C++ don't do what you think they do, and that's also why adding an endl; to it gives you an error.
The formatting I'm going to let you work out for yourself. You should consider reading up on output or at least doing some trial and error.
One of the errors is that instead of this:
cout << "The exam grades are:" << setw(8) << exam1, exam2, exam3, exam4;
I think you mean this:
cout << "The exam grades are:" << setw(8) << exam1 << exam2 << exam3 << exam4 << endl;
CLASS_SIZE is defined as 5, so this loop:
while (thisStudent++ < CLASS_SIZE)
will iterate 6 times.
Also
cout << "The exam grades are:" << setw(8) << exam1, exam2, exam3, exam4;
This outputs exam1, and then evaluates and does nothing with the rest of the variables.
70 80 90 95 95 85 90 80 75 85 70 80 55 85 50 70 45 50 40 35
does it have the spaces? If yes, you need to ignore them. input >> exam1 >> exam2 >> exam3 >> exam4; would load space into one of the exam variables.
-- edit for MooingDuck --
#include <iostream>
#include <sstream>
using namespace std;
int main() {
cout << "main() ENTRY" << endl;
stringstream s1(ios_base::in | ios_base::out),
s2(ios_base::in | ios_base::out);
int i = -1;
s1 << "111 222";
s1 >> i; cout << i << endl;
s1 >> i; cout << i << endl;
s2 << "111 222";
s2 >> noskipws;
s2 >> i; cout << i << endl;
s2 >> i; cout << i << endl;
return 0;
}
Output:
main() ENTRY
111
222
111
0
Related
#include <fstream> // For file handling
#include <iomanip> // For formatted output
#include <iostream> // For cin, cout, and system
#include <string> // For string data type
#include "CourseGrade.h"
using namespace std;
CourseGrade* maximumGrade(CourseGrade* course0, CourseGrade* course1)
{
}
int main()
{
cout << "Course Grade App!" << endl;
cout << "--------------------------" << endl;
cout << endl;
//Prompting and creating CourseGrade objects and pointer values from inputs
int c1;
float g1;
cout << "Please enter the first course and its grade: ";
cin >> c1 >> g1;
CourseGrade Course0(c1, g1);
CourseGrade* ptrCourse0;
ptrCourse0 = &Course0;
int c2;
float g2;
cout << "Please enter the second course and its grade: ";
cin >> c2 >> g2;
CourseGrade Course1(c2, g2);
CourseGrade* ptrCourse1;
ptrCourse1 = &Course1;
int c3;
float g3;
cout << "Please enter the third course and its grade: ";
cin >> c3 >> g3;
CourseGrade Course2(c3, g3);
CourseGrade* ptrCourse2;
ptrCourse2 = &Course2;
cout << "-----------------------------------" << endl;
cout << "Course" << setw(10) << "Grade" << endl;
cout << "-----------------------------------" << endl;
cout << ptrCourse0->getCourse() << setw(10) << ptrCourse0->getGrade() << endl;
cout << ptrCourse1->getCourse() << setw(10) << ptrCourse1->getGrade() << endl;
cout << ptrCourse2->getCourse() << setw(10) << ptrCourse2->getGrade() << endl;
cout << "-----------------------------------" << endl;
cout << "The course with the maximum grade is: " << maximumGrade(ptrCourse0, ptrCourse1) << endl;
cout << "The average grade is: " << (ptrCourse0->getGrade() + ptrCourse1->getGrade() + ptrCourse2->getGrade()) / 3 << endl;
}
// End of main.cpp
void CourseGrade::setCourse(int c)
{
if (c >= 1000 && c <= 9999)
{
course = c;
}
}
void CourseGrade::setGrade(float g)
{
if (g >= 0.00 && g <= 100.00)
{
grade = g;
}
}
int CourseGrade::getCourse() const
{
return course;
}
float CourseGrade::getGrade() const
{
return grade;
}
CourseGrade::CourseGrade(int c, float g)
{
if (c >= 1000 && c <= 9999)
{
course = c;
}
else
{
course = 1000;
}
if (g >= 0.00 && g <= 100.00)
{
grade = g;
}
else
{
grade = 0.00;
}
}
Can you guys please help me out? I have three objects due to the prompt, but it only asks for two pointers? I am completely unaware of how to get the maximumGrade to show the course with the largest grade. I have tried using if statements to compare the grades of the two pointers showing the values of the grades. It HAS to use pointers to compare the course grades. Thank you guys!
I have three objects due to the prompt, but it only asks for two pointers?
The only way to make sense of two pointers passed to maximumGrade is to assume that these are the beginning and end of an array which contains the three objects.
CourseGrade courses[3] = { Course0, Course1, Course2 };
cout << "The course with the maximum grade is: "
<< maximumGrade(courses, courses+3)->getCourse() << endl;
The body of maximumGrade can then be e. g.
CourseGrade *c = NULL;
float g = 0; // current maximum
for (; course0 < course1; ++course0) if (g <= course0->getGrade())
g = (c = course0)->getGrade();
return c;
The goal of this assignment for my class is to ask the user for how many students are in the class.
Using the Vector library create a vector of Strings to hold the students names.
Create a vector of type double to hold a students grade average.
I have a couple two compiler errors that are preventing my code from running. Line 73 & 83. The following errors I am given:
main.cpp: In function ‘void add_student()’: main.cpp:73:11: error: request for member ‘push_back’ in ‘grade’, which is of non-class type ‘double’
73 | grade.push_back(grade);
| ^~~~~~~~~
main.cpp: In function ‘void remove_student()’: main.cpp:83:23: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::__cxx11::basic_string<char> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
83 | for (int i = 0; i < students.size(); i++)
| ~~^~~~~~~~~~~~~~~~~**
Any help would be much appreciated. Below is my entire code
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
using namespace std;
vector<string> students;
vector<double> grade;
void add_student();
void remove_student();
void menu();
void print_summary();
int main()
{
int numStudent;
char menuSelection;
cout << "Welcome to the Student roaster!" << endl;
cout << "How many students are in your class?:" << endl;
cin >> numStudent;
for (int i = 0; i < numStudent; i++)
{
add_student();
}
cout << "Thank you for entering class information!" << endl;
//calls menu for the user
menu();
while (1)
{
cout << "selection:" << endl;
cin >> menuSelection;
if (menuSelection == 'a')
{
add_student();
}
else if (menuSelection == 'r')
{
remove_student();
}
else if (menuSelection == 'p')
{
print_summary();
}
else if (menuSelection == 'm')
{
menu();
}
else if (menuSelection == 'q')
break;
else
cout << "Not a valid selection" << endl;
}
return 0;
}
void add_student()
{
string firstName, lastName;
double grade;
//ask for student info
cout << "Please enter student (Fisrt Last Grade) info: " << endl;
cin >> firstName >> lastName >> grade;
firstName += " ";
firstName += lastName;
//inserts new student
students.push_back(firstName);
grade.push_back(grade);
}
void remove_student()
{
string first, last;
cout << "Enter the student (First Last) to remove :\n";
cin >> first >> last;
first += " ";
first += last;
int loc = 0;
for (int i = 0; i < students.size(); i++)
{
if (students[i] == first)
{ // finding the location to erase
loc = i;
break;
}
}
students.erase(students.begin() + loc); //removing using erase function
grade.erase(grade.begin() + loc);
}
void menu()
{
cout << "Please choose one of the following options:\n";
cout << "a: add a student\n";
cout << "r: remove a student\n";
cout << "p: print the class summary\n";
cout << "m: print menu\n";
cout << "q: quit program\n";
}
void print_summary()
{
cout << "class summary" << endl;
cout << "--------------------------------" << endl;
cout << "Name" << setw(20) << "Grade" << endl;
cout << "-------" << setw(20) << "--------" << endl;
int n = students.size();
double total = 0;
//cycles through each student
for (int i = 0; i < n; i++)
{
int temp = students[i].size();
int loc = 20 - temp;
cout << students[i] << setw(loc) << grade[i] << endl;
total += grade[i];
}
cout << "Number of students: " << endl;
cout << "------------------" <<endl;
cout << n << " " << endl;
total = (total) / n;
cout << "Average Grade: " << endl;
cout << "--------------" << endl;
//limits the deciaml places to 2
cout << fixed << setprecision(2) << total << " " << endl;
}
The name of the local variable was the same as the name of the global variable.
So you should rename local variable.
62) double grade_;
66) cin >> firstName >> lastName >> grade_;
73) grade.push_back(grade_);
I have looked in the forum but can't seem to find anything specific to what I need.
I am writing a program that asks the user to input a number of students. Depending on the number of students they enter they will then have to enter the students name and a series of 10 grades, or pressing 999 to cancel. The program will later have to display all students entered with their average grade. What I have now just overrides the previous inputs and displays the last one entered.
This is what I have so far:
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
int main() {
std::string teacherName = "";
std::string classDesignation ="";
int numStudents = 0;
std::string studentName = "";
double grade[10];
double averageGrade = 0.00;
char letterGrade;
std::cout << "Enter the teacher's name: ";
getline(std::cin, teacherName);
std::cout << "Enter the class designation: ";
getline(std::cin, classDesignation);
std::cout << "Enter the number of students ( 1 or more ): ";
std::cin >> numStudents;
std::cin.ignore();
for (int x = 0; x <= numStudents - 1; x++) {
std::cout << "Enter the student's name: ";
getline(std::cin, studentName);
for (int i = 0; i <= 9; i++) {
std::cout << "Enter grade from 0 - 100 or 999 to stop: ";
std::cin >> grade[i];
if (grade[i] == 999){
break;
}
averageGrade += grade[i];
if (averageGrade <= 59){
letterGrade = 'F';
}
if (averageGrade >= 60 || averageGrade <= 69){
letterGrade = 'D';
}
if (averageGrade >= 70 || averageGrade <= 79){
letterGrade = 'C';
}
if (averageGrade >= 80 || averageGrade <= 89){
letterGrade = 'B';
}
if (averageGrade > 90){
letterGrade = 'A';
}
}
}
std::cout << "Teacher: " << teacherName << std::endl;
std::cout << "Class: " << classDesignation << std::endl;
std::cout << "Student Name: " << studentName;
std::cout << std::setw(19) << "Average: " << averageGrade;
std::cout << " Grade: " << letterGrade << std::endl;
std::cout << "Student count: " << numStudents << std::endl;
std::cout << "Student average: " << std::endl;
std::cout << "A's: " << std::endl;
std::cout << "B's: " << std::endl;
std::cout << "C's: " << std::endl;
std::cout << "D's: " << std::endl;
std::cout << "F's: " << std::endl;
return 0;
}
Any tips?
Thank you!
#Hansel, here's what I think will work. We'll change this line to get what we want:
averageGrade += grade[i];
To:
//to declarations:
double averageGradeSum = 0.00;
//then change the line mentioned before to:
averageGradeSum += grade[i];
Then:
//if for some reason you're indexing starts at 1
averageGrade = averageGradeSum/i;
//if indexing starts at 0 like usual C++ use:
averageGrade = averageGradeSum/(i+1);
I'm not going to test this. It should make sense and if I screwed up the syntax it should be an easy google adventure to fix. Enjoy :)
From what I see, you can store them in associative vectors, one for the student name, and one for the average grade. You can also have a doubly linked list of student nodes which would look something like this:
struct student
{
std::string student_name;
int ave_grade;
// Head points to the previous student in the array.
// Tail points to the next student in the array.
student *head;
student *tail;
}
Declare a struct that everything hangs from to prevent memory leaks: student list_head; and each time you have an input, add a new node to the list.
So I am working to read text from a file (line by line) and output the ID, average of 4 grades following the ID, and the letter grade. So the letter grade for any average grade of 50 or above is S, anything below 50 is a U, and 2 excused classes results in the letter grade I. (No S or U if more than or equal to 2 excused).
So lets say file has the numbers:
42 50 51 57 52
48 90 -1 60 -1
40 46 -1 59 45
47 50 -1 49 50
The output should look something like this:
ID=42 Avg=52.5 Grade=S
ID=48 Excused=2 Grade=I
ID=40 Avg=50.0 Grade=S
ID=47 Avg=49.7 Grade=U
Number of Grades of Type
S U I
2 1 1
This is the output I am receiving from my code
It is reading all the numbers, but i need it to read the first number as ID and following 4 numbers as grade.
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
ifstream in;
ofstream results;
string filename;
char grade;
int S = 0, U = 0, I = 0, i = 0, ID, excused = 0, avg;
double allscores = 0;
cout << "Enter the name of the file that has the scores of students: " << endl;
cin >> filename;
cout << "Enter the number of scores for each student: " << endl;
cin >> ID;
in.open(filename);
results.open("results.txt");
if (in)
{
while (in >> ID)
{
int first = 0
for (i = 0; i<=4; i++)
{
if (first == -1)
excused++;
else
allscores += first;
}
if (first > 4)
{
avg = allscores / (4 - excused);
if (avg >= 50.0)
{
grade = 'S';
S++;
cout << "ID=" << ID << " Avg=" << avg << " Grade =" << grade << endl;
}
else
{
grade = 'U';
U++;
cout << "ID=" << ID << " Avg=" << avg << " Grade =" << grade << endl;
}
}
else
{
grade = 'I';
I++;
cout << "ID=" << ID << " Excused=" << excused << " Grade =" << grade << endl;
}
}
}
else
{
cout << "Couldn't open file\n";
}
cout << "Number of Grades of Type" << endl;
cout << "S " << "U " << "I" << endl;
cout << S << " " << U << " " << I << endl;
in.close();
results.close();
system("pause");
return 0;
}
Your variable int first=0 is not being assigned any value other than 0 in your code so the statement if(first>4) will always be false and result the output your are getting.
You can do something like this:
while (in >> ID)//this is supposed to get the ID of each student, in order for that to happen you need to read all the 4 scores inside this loop before coming here and reading the next ID,otherwise everything will read as an ID
{
int first = 0
excused=0;//you need to reset excused on every iteration
allscores=0;//you need to reset allscore on every iteration
for (i = 0; i<4; i++)
{//here you need to get all the 4 scores
in>>first;//get each score in first
if (first == -1)
excused++;
else
allscores += first;
}
if(excused<2)//instead of if(first>4)
...//do your calculation for average score
else
...//set the grade to 'I'...
}
Here is my final solution:
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
ifstream in;
ofstream results;
string filename;
char grade;
int S = 0, U = 0, I = 0, i = 0, ID, excused = 0, avg;
double allscores = 0;
cout << "Enter the name of the file that has the scores of students: " << endl;
cin >> filename;
cout << "Enter the number of scores for each student: " << endl;
cin >> ID;
in.open(filename);
results.open("results.txt");
if (in)
{
while (in >> ID)
{
int first = 0;
excused = 0;
allscores = 0;
for (i = 0; i < 4; i++)
{
in >> first;
if (first == -1)
excused++;
else
allscores += first;
}
if (excused < 2)
{
avg = allscores / (4 - excused);
if (avg >= 50.0)
{
grade = 'S';
S++;
results << "ID=" << ID << " Avg=" << avg << " Grade =" << grade << endl;
}
else
{
grade = 'U';
U++;
results << "ID=" << ID << " Avg=" << avg << " Grade =" << grade << endl;
}
}
else
{
grade = 'I';
I++;
results << "ID=" << ID << " Excused=" << excused << " Grade =" << grade << endl;
}
}
}
else
{
cout << "Couldn't open file\n";
}
results << "Number of Grades of Type" << endl;
results << "S " << "U " << "I" << endl;
results << S << " " << U << " " << I << endl;
in.close();
results.close();
system("pause");
return 0;
}
After the code I have it output to a file named "results".
Thanks for the help. I guess my while loop was the biggest mistake.
Especially not adding in the in >> first portion.
I'm having trouble getting my cin loop to terminate in my program. My program uses Linux redirection to read in input from the file hw07data, the data file look like this:
100 20 50 100 40 -1
A34F 90 15 50 99 32 -1
N12O 80 15 34 90 22 -1
The first portion is the total points for the class, the next lines are the students ID number followed by their scores, all terminated by -1.
My issue: my while loop never terminates when i run the command ./a.out < hw07data, could anyone look over my code and give me some hints? I dont want the answer, as this is homework, i just need some guidance. Thanks!!
#include <iostream>
#include <iomanip>
using namespace std;
const int SENTINEL = -1; //signal to end part of file
const int LTAB = 8; //left tab
const int RTAB = 13; //right tab
int main()
{
cout << "Grant Mercer Assignment 7 Section 1002\n\n";
cout << setprecision(2) << fixed << showpoint;
cout << left << setw(LTAB) << "ID CODE" <<
right << setw(RTAB) << "POINTS" <<
setw(RTAB) << "PCT" << setw(RTAB) <<
"GRADE" << endl;
double Percentage, //holds students percentage
AvgPercentage;
int Earnedpoints, //earned points for specific student
Totalpoints, //total points possible for all students
AvgPoints, //average points for all students
NumClass; //counts the number of students
Totalpoints = Earnedpoints = //set all vals equal to zero
AvgPoints = AvgPercentage = Percentage = NumClass = 0;
//first and last char for studentID
char Fchar,Lchar, Num1, Num2, Grade;
int TmpVal = 0; //temporary value
cin >> TmpVal;
while(TmpVal != -1) //reading in TOTAL POINTS
{
Totalpoints += TmpVal; //add scores onto each other
cin >> TmpVal; //read in next value
}
while(cin) //WHILE LOOP ISSUE HERE!
{
//read in student initials
cin >> Fchar >> Num1 >> Num2 >> Lchar >> TmpVal;
while(TmpVal != -1)
{
Earnedpoints += TmpVal; //read in points earned
cin >> TmpVal;
}
//calculate percentage
Percentage = ((double)Earnedpoints / Totalpoints) * 100;
AvgPercentage += Percentage;
NumClass++;
if(Percentage >= 90) //determine grade for student
Grade = 'A';
else if(Percentage >= 80 && Percentage < 90)
Grade = 'B';
else if(Percentage >= 70 && Percentage < 80)
Grade = 'C';
else if(Percentage >= 60 && Percentage < 70)
Grade = 'D';
else if(Percentage < 60)
Grade = 'F';
//display information on student
cout << left << Fchar << Num1 << Num2 << setw(LTAB) << Lchar << right << setw(RTAB-3) << Earnedpoints <<
setw(RTAB) << Percentage << setw(RTAB) << Grade << endl;
TmpVal = Earnedpoints = 0;
}
AvgPercentage /= NumClass;
cout << endl << left << setw(LTAB+20) << "Class size: " << right << setw(RTAB) << NumClass << endl;
cout << left << setw(LTAB+20) << "Total points possible: " << right << setw(RTAB) << Totalpoints << endl;
cout << left << setw(LTAB+20) << "Average point total: " << right << setw(RTAB) << AvgPoints << endl;
cout << left << setw(LTAB+20) << "Average percentage: " << right << setw(RTAB) << AvgPercentage << endl;
}
The output continues to ask for new input.
You may find answer there How to read until EOF from cin in C++
So you can read cin line by line using getline and parse the resulting lines, like that:
#include <iostream>
#include <sstream>
#include <string>
int main() {
int a, b;
std::string line;
while (std::getline(std::cin, line)) {
std::stringstream stream(line);
stream >> a >> b;
std::cout << "a: " << a << " - b: " << b << std::endl;
}
return 0;
}
EDIT: Do not forget to check parsing results and stream state for any failure!
You should always check that you input was successful:
if (std::cin >> TmpVal) {
// do simething with the read value
}
else {
// deal with failed input
}
In case of a failure you night want to check eof() inducating that the failure was due to having reached the end of the input.
To deal with errors, have a look at std::istream::clear() and std::istream::ignore().