So for my assignment I need to read a text file with student names and their test scores and display on screen the average test score and the highest test score.
The content of the text file is:
John Smith 99
Sarah Johnson 85
Jim Robinson 70
Mary Anderson 100
Michael Jackson 92
The code I have so far is:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
void inputFile(string, string, int, int, int, int);
int main()
{
string firstName;
string lastName;
int testScore = 0;
int totalScore = 0;
int avgScore = 0;
int highestScore = 0;
inputFile(firstName, lastName, testScore, totalScore, avgScore, highestScore);
system("pause");
return 0;
}
void inputFile(string firstName, string lastName, int testScore, int totalScore, int avgScore, int highestScore)
{
ifstream myFile("scores.txt");
int i = 0;
while (myFile >> firstName >> lastName >> testScore) {
totalScore = totalScore + testScore;
i++;
}
avgScore = totalScore / i;
cout << "Average score: " << avgScore << endl;
while (myFile >> firstName >> lastName >> testScore) {
if (highestScore < testScore) {
highestScore = testScore;
}
}
cout << "Highest score: " << highestScore << endl;
}
When I run the program it displays the average score correctly but when it comes to the highest score it just displays "0" every time rather than displaying "100" which is the largest number in the text file. How would I make it display "100" for 'highestScore' rather than "0"?
while (myFile >> firstName >> lastName >> testScore) {
if (highestScore < testScore) {
highestScore = testScore;
}
}
Why are you attempting to read the file again? You should have processed it at the same time as summing up:
while (myFile >> firstName >> lastName >> testScore) {
totalScore = totalScore + testScore;
if (highestScore < testScore) {
highestScore = testScore;
}
i++;
}
Or alternatively, rewind the file before trying to read again:
myfile.clear();
myfile.seekg(0);
while (myFile >> firstName >> lastName >> testScore) {
/* stuff... */
With the first loop you go through the file all the way to the end. And then it stays on the end, it will not "rewind" to the beginning automatically.
Either you have to seek back to the beginning for the second loop (and clear the end-of-file status). Or calculate the highest score in the first loop too.
Related
I am working on this problem for a college course and I'm unsure why it isn't working. I thought I had everything setup correctly, but when I try running the program the file won't open on the first attempt at inputting the file name and when I input it again I get an "Exception Thrown" error in the "xmemory" part that I have no idea what any of it means.
The input file that the program is taking data from is just a text file with the following data:
201742 Sponge Bob 82.6
201701 Patrick Star 14.1
201753 Squidward Tentacles 85.43
201744 Sandy Squirrel 75.61
201700 Plankton Plank 100.0
The final output of the program should display the highest and lowest grade with the students first and last name, the average score, and the number of students tested. Any help would be much appreciated.
// Zane Richards
// Lab 10 Q2
// 4/6/2020
#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
#include <fstream>
using namespace std;
struct student {
int ID;
string firstName;
string lastName;
float grade;
};
void maxGradeFunc(struct student* s, int size)
{
float maxGrade = 0;
string firstName, lastName;
for (int i = 0; i < size; ++i)
{
if (s[i].grade > maxGrade)
{
maxGrade = s[i].grade;
firstName = s[i].firstName;
lastName = s[i].lastName;
}
}
cout << "Maximum grade is " << maxGrade << endl;
cout << "The name of the student with the grade is: " << firstName << " " << lastName << endl;
}
void minGradeFunc(struct student* s, int size)
{
float minGrade = 999;
string firstName, lastName;
for (int i = 0; i < size; ++i)
{
if (s[i].grade < minGrade)
{
minGrade = s[i].grade;
firstName = s[i].firstName;
lastName = s[i].lastName;
}
}
cout << "Maximum grade is " << minGrade << endl;
cout << "The name of the student with the grade is: " << firstName << " " << lastName << endl;
}
void avgGradeFunc(struct student* s, int size)
{
float sum = 0;
for (int i = 0; i < size; ++i)
{
sum += s[i].grade;
}
float avg = sum / size;
cout << "Avearge grade is " << avg << endl;
cout << "The total number of students are: " << sum << " students" << endl;
}
int main()
{
ifstream inFile;
string fileName = "";
struct student s[5];
int ID;
string firstName, lastName;
float grade;
int i = 0;
cout << "Please enter the input file name: "; //File is named "Student.txt"
cin >> fileName;
while (!inFile.is_open()) {
cout << "Sorry, the file did not open. \nTry again, or type \"cancel\" to quit: ";
cin >> fileName;
if (fileName == "cancel") {
cout << "Cancelling..." << endl;
break;
}
else {
inFile.open(fileName);
}
}
while (inFile.is_open()) {
inFile >> ID;
s[i].ID = ID;
inFile >> firstName;
s[i].firstName = firstName;
inFile >> lastName;
s[i].lastName = lastName;
inFile >> grade;
s[i].grade = grade;
i++;
}
maxGradeFunc(s, 5);
minGradeFunc(s, 5);
avgGradeFunc(s, 5);
return 0;
}
Here is the error code I'm getting: https://i.stack.imgur.com/i35Oq.png
Figured out the issue, deleted the code that allowed for multiple attempts, and changed it to just open the file and that fixed it. Thanks for the help everyone, much appreciated!
The program for my class needs to return the average score, the high score with first and last name as well as the low score. I get an error for the functions that find the names for the high and low score and I'm not sure what the issue is.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
float highestVal(float highScore, float score);
float lowestVal(float lowScore, float score);
string highFirstFun(float highScore, float score, string firstNameHigh);
string highLastFun(float highScore, float score, string lastNameHigh);
string lowFirstFun(float lowScore, float score, string firstNameLow);
string lowLastFun(float lowScore, float score, string lastNameLow);
int main() {
ifstream inFile;
string fileName = "", firstName = "", lastName = "";
float score, average;
float highScore = 0;
float lowScore = 100;
float studentNum = 0;
float sum = 0;
int i;
string highFirst = "", highLast = "";
string lowFirst = "" , lowLast = "";
cout << "Please enter the input file name: ";
cin >> fileName;
inFile.open(fileName);
while (!inFile.is_open()) {
cout << "Sorry, the file did not open. \nTry again, or type \"cancel\" to quit: ";
cin >> fileName;
if (fileName == "cancel") {
cout << "Cancelling..." << endl;
break;
}
else {
inFile.open(fileName);
}
}
if (inFile.is_open()) {
cout << "The scores are as follows: \n";
while (!inFile.eof()) {
inFile >> firstName >> lastName >> score;
cout << firstName << " " << lastName << " scored " << score << endl;
sum += score;
studentNum++;
highScore = highestVal(highScore, score);
lowScore = lowestVal(lowScore, score);
highFirst = highFirstFun(highScore, score, firstName);
highLast = highLastFun(highScore, score, lastName);
lowFirst = lowFirstFun(highScore, score, firstName);
lowLast = lowLastFun(highScore, score, lastName);
}
average = (sum / studentNum);
cout << "There are " << studentNum << " students with an average grade of " << average << endl;
cout << "The high score was: " << highScore << " from " << highFirst << " " << highLast << endl;
cout << "The low score was: " << lowScore << " from " << lowFirst << " " << lowLast << endl;
inFile.close();
}
return 0;
}
float highestVal(float highScore, float score)
{
if (score > highScore) {
highScore = score;
}
return (highScore);
}
float lowestVal(float lowScore, float score)
{
if (score < lowScore) {
lowScore = score;
}
return (lowScore);
}
string highFirstFun(float highScore, float score, string firstNameHigh)
{
if (score > highScore) {
return (firstNameHigh);
}
}
string highLastFun(float highScore, float score, string lastNameHigh)
{
if (score > highScore) {
return (lastNameHigh);
}
}
string lowFirstFun(float lowScore, float score, string firstNameLow)
{
if (score < lowScore) {
return (firstNameLow);
}
}
string lowLastFun(float lowScore, float score, string lastNameLow)
{
if (score < lowScore) {
return (lastNameLow);
}
}
Here is the Text File that it is pulling from called "Scores.txt":
John Smith 99.0
Sarah Johnson 85.0
Jim Robinson 70.0
Mary Anderson 100.0
Michael Jackson 92.0
Any help would be much appreciated!
A function that has a return type must always return that type. The function
string highFirstFun(float highScore, float score, string firstNameHigh);
For example must always return a string when it is called. The issue is the definition of your function
string highFirstFun(float highScore, float score, string firstNameHigh)
{
if (score > highScore) {
return (firstNameHigh);
}
}
highFirstFun() Will only return a string if (and only if) score is higher than highScore. Well, what will happen if score is not higher than highScore? This will be a problem for the function because it's not designed to do anything if a condition like this happens, so the compiler will complain about it. This applies to all your functions. To make them work, you'll have to find a way to make them return a string is all scenarios.
for my csc 102 assignment, I need to create a class to hold a student's grades and name. Then output that information to a text file. The grades and name are both read from an input file. I got it to succesfully run one instance of student. However, I do not know how to make the next student object read from the next line.
the input file is in this format:
Jonathan Blythe 87 76 79 88
Jessica Blake 87 79 58 86
Jonathan Lee 88 86 69 100
Joseph Blake 78 89 50 69
My first Student object Student a; reads the correct line. However, when I call the function again for another Student object Student b;, it still reads the first line, and overwrites the output file. I thought if I didn't close the file until the end of main that it may read correctly. I will show the class header file, and the implementation file for Student below.
#include "Student.h"
Student::Student() {
cout << "Default Constructor" << endl;
}
void Student::getscores() {
ifstream infile;
infile.open("input.txt");
infile >> firstName >> lastName;
for (int i = 0; i <= 3; i++) {
infile >> scores[i];
}
infile.close();
}
void Student::getaverage() {
average = 0;
for (int i = 0; i < 4; i++) {
average = average + scores[i];
}
average = average / 4;
}
void Student::print()const {
ofstream outfile;
outfile.open("output.txt");
outfile << firstName << " " << lastName << endl;
cout << firstName << " " << lastName << endl;
for (int i = 0; i <= 3; i++) {
cout << scores[i] << " ";
outfile << scores[i] << " ";
}
cout << endl;
outfile << endl;
cout << "Average Score: " << average << endl;
outfile << "Average Score" << average << endl;
cout << "Letter Grade: " << grade << endl;
outfile << "Letter Grade: " << grade << endl;
//outfile.close();
}
void Student::getletter() {
if (average >= 90)
grade = 'A';
else if (average >= 80 && average < 90)
grade = 'B';
else if (average >= 70 && average < 80)
grade = 'C';
else if (average >= 60 && average < 70)
grade = 'D';
else if (average < 60)
grade = 'F';
}
Student::~Student() {
}
and
#pragma once
#include<iostream>
#include<string>
#include <fstream>
using namespace std;
class Student
{
string lastName;
string firstName;
int scores[4] = { 0,0,0,0 };
int average = 0;
char grade = 'n';
public:
Student();
Student(string, string, int, int, int, int, char);
~Student();
void getscores();
void getaverage();
void getletter();
void print()const;
};
How do I read incrementally to the next line everytime a function is called?
One option is to pass the input stream as an argument to the function.
You should read the input.txt line by line, for each line you need to parse to get the firstName, lastName, scores then use them to create a new object of Student class (you need some changes of Student class to create object from name, set scores, etc.)
I suggest the code skeleton is something like below:
char line[128] = {0,};
ifstream infile;
infile.open("input.txt");
if (!infile.is_open()) {
return;
}
while (infile.getline(line, sizeof(line) - 1)) { // read content of next line then store into line variable
// parse content of line to get firstName, lastName, scores
...
// create new object of Student class from firstName, lastName, scores you got
...
// clear content in line
memset(line, '\0', sizeof(line));
}
I am having issues figuring out how to properly display a student's ID, out of 10 students, along with the highest score. For examle, if student 4 had the highest score if would display said student's ID and their score. I would like to add the student's first and last name as well, if possible. My code is as follows:
// HW2.cpp : This file contains the 'main' function. Program execution begins and ends there.
#include <iostream>
using namespace std;
double TestScore(double score);
struct studentType {
string studentFName;
string studentLName;
double testScore;
int studentID;
double highScore;
};
int main()
{
// # of students
studentType student[10];
// For loop to get user input for the 10 students
for (int i = 0; i < 10; i++) {
cout << "Student ID: ";
cin >> student[i].studentID;
cout << "Student First Name: ";
cin >> student[i].studentFName;
cout << "Student Last Name: ";
cin >> student[i].studentLName;
cout << "Student's Test Score: ";
cin >> student[i].testScore;
cout << endl;
//Calls TestScore function
student[i].testScore = TestScore(student[i].testScore);
}
//Displays student ID and score v code that I need help on
//cout <<student[i].studentID << " has the highest score, which is "<< TestScore;
}
double TestScore(double score)
{
double newScore = 0;
//Determines student with highest score
for (int n = 0; n < 10; n++) {
if (score > newScore)
{
newScore = score;
}
}
return newScore;
}
It needs to :
1) read the students’ data into the array.
2) find the highest test score.
3) print the names of the students having the highest test score.
Your TestScore function doesn't really do anything. I've modified your code to have a function which returns the index of the student with the best score. Using this index, you can then access that element of the array, and print out its details.
#include <iostream>
using namespace std;
struct studentType {
string studentFName;
string studentLName;
double testScore;
int studentID;
double highScore;
};
int getBestStudent( studentType student[10] );
int main() {
// # of students
studentType student[10];
// For loop to get user input for the 10 students
for ( int i = 0; i < 10; i++ ) {
cout << "Student ID: ";
cin >> student[i].studentID;
cout << "Student First Name: ";
cin >> student[i].studentFName;
cout << "Student Last Name: ";
cin >> student[i].studentLName;
cout << "Student's Test Score: ";
cin >> student[i].testScore;
cout << endl;
}
// Displays student ID and score v code that I need help on
int best = getBestStudent( student );
cout <<student[best].studentFName << " " << student[best].studentLName << " has the highest score, which is "<< student[best].testScore;
}
int getBestStudent( studentType student[10] ) {
int best = 0;
//Determines student with highest score
for ( int n = 1; n < 10; n++ ) {
if ( student[n].testScore > student[best].testScore ) {
best = n;
}
}
return best;
}```
I'm writing a program that takes a text file with results of an ad campaign and need to find the average rating of the campaign for 4 different demographics. I think I have it all figured out just struggling with getting the data from the file and into char and int variables. Do I need to read it all as strings and then convert or can I read them into those variables?
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;
int main(){
//declare vars
ifstream fileIn;
string path;
string name;
char yn;
int age;
double rating;
double rate1 = 0;
double rate1Count = 0;
double avg1 = 0;
double rate2 = 0;
double rate2Count = 0;
double avg2 = 0;
double rate3 = 0;
double rate3Count = 0;
double avg3 = 0;
double rate4 = 0;
double rate4Count = 0;
double avg4 = 0;
double totalAvg = 0;
cout << fixed << showpoint << setprecision(2);
// prompt user
cout << "Please enter a path to the text file with results: ";
// get path
cin >> path;
cout << endl;
// open a file for input
fileIn.open(path);
// error message for bad file
if (!fileIn.is_open()){
cout << "Unable to open file." << endl;
getchar();
getchar();
return 0;
}
// read and echo to screen
cout << ifstream(path);
// restore the file
fileIn.clear();
fileIn.seekg(0);
cout << endl << endl;
// get average for demos
while (!fileIn.eof){
fileIn >> name;
fileIn >> yn;
fileIn >> age;
fileIn >> rating;
if (yn != 121 && age < 18){
rate1 += rating;
rate1Count++;
}
if (yn == 121 && age < 18){
rate2 += rating;
rate2Count++;
}
if (yn != 121 && age >= 18){
rate3 += rating;
rate3Count++;
}
if (yn == 121 && age >= 18){
rate4 += rating;
rate4Count++;
}
}
avg1 = rate1 / rate1Count;
avg2 = rate2 / rate2Count;
avg3 = rate3 / rate3Count;
avg4 = rate4 / rate4Count;
cout << yn << age << rating;
// pause and exit
getchar();
getchar();
return 0;
}
The text file
Bailey Y 16 68
Harrison N 17 71
Grant Y 20 75
Peterson N 21 69
Hsu Y 20 79
Bowles Y 15 75
Anderson N 33 64
Nguyen N 16 68
Sharp N 14 75
Jones Y 29 75
McMillan N 19 8
Gabriel N 20 62
Ditch the cout << ifstream(path); ... fileIn.seekg(0); - that's all unhelpful.
For input, use:
while (fileIn >> name >> yn >> age >> rating)
{
...
That will exit when there's some problem getting the input - whether due to invalid characters for the type (e.g. letters when reading a number), or end-of-file.
Do I need to read it all as strings and then convert or can I read them into those variables?
As above, you don't need to, but you can get better quality input validation and error messages for the user if you get each complete line as a string then attempt to parse out the values:
std::string line;
for (int line_num = 1; getline(fileIn, line); ++line_num)
{
std::istringstream iss(line);
if (iss >> name >> yn >> age >> rating >> std::ws &&
iss.eof())
...use the values...
else
std::cerr << "bad input on line " << line_num
<< " '" << line << "'\n";
// could exit or throw if desired...
}