Using files and structs to read data and output it - c++

Mike 85 83 77 91 76 CSC
Mark 80 90 95 93 48 CSC
Anderson 78 81 11 90 73 BUSS
Blair 92 83 30 69 87 ECE
Suzy 23 83 30 69 87 ARC
Karlos 46 76 90 54 38 MASS-COMM
So i have this file and i am required to read the data of it and output it through the console using structs, i have managed to read Mike's Name and his scores and Faculty but that's where i am stuck, how can i continue reading ?
Here is my code
struct student {
string name;
int scores[5];
string faculty;
};
void main() {
student x;
ifstream myfile("D:\\Test\\MIUCS.txt");
myfile >> x.name;
for (int j = 0; j < 5; j++) {
myfile >> x.scores[j];
}
myfile >> x.faculty;
cout << x.name << " ";
for (int k = 0; k < 5; k++) {
cout << x.scores[k] << " ";
}
cout << x.faculty << endl;
}
Hint: My Prof said to use an array of type student (the struct) which i can't really implement, any help would be appreciated thank you.

how can i continue reading ?
Wrap the code around reading/writing in a while loop. Keep reading and writing until there is nothing to read.
while ( myfile >> x.name )
{
for (int j = 0; j < 5; j++)
{
myfile >> x.scores[j];
}
myfile >> x.faculty;
// If there was any error in reading from myfile, break out of the loop.
if ( !myfile )
{
break;
}
cout << x.name << " ";
for (int k = 0; k < 5; k++)
{
cout << x.scores[k] << " ";
}
cout << x.faculty << endl;
}
You can simplify the loop by moving the code for reading and writing to their own functions.
while ( myfile >> x )
std::cout << x << std::endl;
In order to use the above, you will need to overload the operator>> function and the operator<< function as:
std::istream& operator>>(std::istream& in, student& s);
std::ostream& operator<<(std::ostream& out, student const& s);
I'll leave it to you to take it to the next step.

Related

How can I correctly call this function?

I'm having trouble calling this function. It's supposed to reformat a name from "First Mid Last" to "Last, First MidInitial" (If a middle name is available, else just "Last, First)). Though if I change the function type to string, it gives a different list of errors:
In function âvoid getData(StudentType*, int)â:
71:43: error: invalid use of void expression
Anyone have any suggestions?
PROGRAM FILE
using namespace std;
#include "StudentType.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <climits>
#include <string>
const int MAX_STDS = 20;
void getData(StudentType[], int&);
void sortData(StudentType[], int&);
void getFormat(string& name);
void computeAverages(StudentType[], int&);
void printData(StudentType[], int&);
int main () {
StudentType students[MAX_STDS];
StudentType();
int n;
getData(students, n);
sortData(students, n);
computeAverages(students, n);
printData(students, n);
return 0;
}
void getData(StudentType students[], int n){
ifstream fin;
int grade;
string filename, name;
bool done = false;
cout << "Enter filename: ";
cin >> filename;
fin.open(filename.c_str());
while(true) {
try {
fin.open(filename.c_str());
if(!fin) {
throw(string("Could not open " + filename + "."));
}
break;
}
catch (string s) {
cout << s << endl;
cout << "Enter a different file name: ";
cin >> filename;
}
}
n=0;
while(n<MAX_STDS && getline(fin, name)) {
students[n].setName(getFormat(name));
for(int i = 0; i < NUM_GRDS; ++i) {
fin >> grade;
students[n].setGrade(grade, i);
}
getline(fin, name);
++n;
}
}
void printData(StudentType students[], int n) {
for(int i = 0; i < n; ++i) {
students[i].printLine();
}
}
void computeAverages(StudentType students[], int n) {
for(int i = 0; i < n; ++i) {
students[i].computeAverage();
}
}
void sortData(StudentType students[], int n) {
for(int i=0; i<n-1; i++) {
for(int j=0; j < n-1-i; ++j) {
if(students[j].getName() > students[j+1].getName()) {
swap(students[j], students[j+1]);
}
}
}
}
void getFormat(string name) {
string first;
string middle;
string last;
char n, m;
int size = 0;
n = name.find(' ');
first = name.substr(0, n);
m = name.find(' ', n + 1);
size = name.size();
if (m != string::npos) {
middle = name.substr(n+1, m-(n+1));
last = name.substr(m+1, size - (m+1));
}
else {
middle = "";
last = name.substr(n + 1, size - (n + 1));
}
name = last + ", " + first;
if (middle != "") {
name = (name + ' ') + middle[0];
}
}
HEADER FILE
#ifndef STUDENTTYPE__H
#define STUDENTTYPE__H
#include <string>
#include<iostream>
const int NUM_GRDS = 10;
class StudentType {
public:
StudentType();
void setName(std::string);
void setGrade(int, int);
void computeAverage();
std::string getName() const;
void printLine(std::ostream& = std::cout) const;
private:
std::string name;
int grades[NUM_GRDS];
float avg;
};
#endif
IMPLEMENTATION FILE
#include "StudentType.h"
#include <iomanip>
StudentType::StudentType(){
name = "";
for(int i =0; i <NUM_GRDS; ++i){
grades[i] = 0;
}
avg = 0.0;
}
void StudentType::setName(std::string newName){
name = newName;
}
void StudentType::setGrade(int grade, int num){
grades[num] = grade;
}
void StudentType::computeAverage(){
float total = 0;
for(int i = 0; i<NUM_GRDS; ++i){
total += grades[i];
}
avg = total/NUM_GRDS;
}
std::string StudentType::getName() const{
return name;
}
void StudentType::printLine(std::ostream& out) const {
// out.setf(ios::left);
// out.setf(ios::fixed);
// out.setf(ios::showpoint);
out << "\n" << std::setw(25) << "Student" << std::setw(50)
<< "Grades" << std::setw(10) << "Average" << std::endl;
out << "_____________________________________________________________________________________" << std::endl;
out << std::left << std::setw(25) << name << std::right << ' ';
for(int i = 0; i < NUM_GRDS; ++i){
out << std::setw(5) << grades[i] << ' ';
}
out << std::setprecision(2) << std::setw(6) << avg << std::endl;
}
int main (){
return 0;
}
My output should look like this after the program compiles...
Enter file name: grades.dat
Student Grades Average
________________________________________________________________________________________
Last, First 90 80 70 60 50 40 30 20 10 0 45.00
Last, First 40 40 40 40 40 40 40 40 40 40 40.00
Last, First 54 98 65 32 21 87 54 65 98 32 60.60
Flames, Blood A 9 8 7 6 5 4 3 2 1 0 4.50
Bottoms, Car 32 65 98 87 54 24 56 89 78 68 65.10
Guitars, Dean 10 10 10 10 10 10 10 10 10 10 10.00
Honer, Ruth T 78 56 12 23 45 89 31 64 97 79 57.40
Hot, Zepher R 12 54 87 89 56 32 51 46 97 31 55.50
.
.
.
The input file should have this format and include over 20 students for testing purposes:
g0, g1,...g9 should be 10 grades ranging from 0 to 100
First Middle Last
g0 g1 g2 g3 g4 g5 g6 g7 g8 g9
First Last
g0 g1 g2 g3 g4 g5 g6 g7 g8 g9
The error specifies that you are misusing a function with a void return type.
In your example, you can see this line:
students[n].setName(getFormat(name));
According to the definition, the getFormat() function is returning void and the setName method is expecting std::string.
Also, I spotted a multiple definition for main() which will fail to link. Look at the end of your student type implementation file.

multiple line reading from txt file C++

From file txt.
44 55 77 88
79 88 100 99
77 99 98 99
100 88 89 100
55 56 40 77
how do i read line by line to add and get the average? This is what I have so far.
int main()
{
ifstream numberInputFile;
int sum = 0.0, average = 0.0;
int test1, test2, test3, test4;
numberInputFile.open("grades.txt");
if (numberInputFile)
{
while (numberInputFile >> test1 >> test2 >> test3 >> test4)
{
sum += (test1 + test2 + test3 + test4);
//find the average
average = sum / 4;
if(average >= 90 && average <= 100)
{
cout << average << " A" <<endl;
}
else if(average >= 80 && average < 90)
{
cout << average << " B" <<endl;
}
else if(average >= 70 && average < 80)
{
cout << average << " C" <<endl;
}
else if(average >= 60 && average < 70)
{
cout << average << " D" <<endl;
}
else if(average < 60)
{
cout << average << " F" <<endl;
}
else
numberInputFile.close();
}
}
return 0;
}
Instead of :
if (numberInputFile)
{}
while (numberInputFile >> test1 >> test2 >> test3 >> test4)
{}
Try :
string line;
while(getline(inFile, line))
{
std::istringstream iss(line)
while(iss >> test)
{ sum+=test;
.
.
..
}
//Check average here, outside the loop
}

How do I print out an class of array objects that has multiple scores within those objects using the arrow pointer?

// Proj7.cpp
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
#include "Proj7.h"
int main()
{
//Student *records = new Student [15];
Student *records [15];
Student *temp;
string ID;
string name;
int average;
double testScores;
double Average(int, double);
ifstream inFile;
ofstream outFile;
inFile.open("Proj7_input.txt");
outFile.open("Proj7_output.txt");
if(inFile.is_open())
{
while(!inFile.eof())
{
for(int i = 0; i < 15; i++)
{
temp = new Student();
//ID
inFile >> ID; //read from file
temp ->setID(ID); //set ID
outFile << "Student's ID: " << temp ->getID(); //get and display
//NAME
getline(inFile, name);//read entire line including spaces
outFile << endl;
//temp ->setName(name);
outFile << "Student's name: " << name << endl;
cout << name;
//outFile << endl;
//TEST SCORES
for(int j = 0; j < 10; j++)
{
inFile >> testScores;
temp ->setScores(testScores);
outFile << "Test score " << j + 1 << ": " << testScores;
}
//AVERAGE
outFile << temp ->getName() << "'s average is: " << temp ->getAverage();
outFile << endl;
outFile << endl;
records[i] = temp;
}
}
}
}
===========================================================================
#ifndef PROJ7_H_INCLUDED
#define PROJ7_H_INCLUDED
//Proj7.h
using namespace std;
class Student
{
private:
string ID;
string name;
double testScores;
double average;
public:
void setID(string i_d) { ID = i_d; }
void setName(string n) { name = n; }
void setScores(double s) { testScores = s; }
void setAverage(double a) { average = a; }
double Average(double testScores[][10],double avg[]);
double getScores() const { return testScores; }
double getAverage() const { return average; }
string getID() const { return ID; }
string getName() const { return name; }
string display() const;
};
double Student::Average(double testScores[][10],double average[])
{
for(int i = 0; i < 15; i++)
{
double sum = 0;
for(int j = 0; j < 10; j++)
sum += testScores[i][j];
average[i] = sum/ 10;
}
return 0;
}
#endif // PROJ7_H_INCLUDED
===========================================================================
A0375
Daenerys Targaryen
90
88
79
95
79
80
88
76
79
99
A0376
Tyrion Lannister
77
86
80
81
83
85
90
94
95
87
A0377
Brienne of Tarth
99
98
97
79
80
89
85
96
97
100
I've been having the most trouble working with the for loop to print out all 10 of the test scores for each of the 15 students, while also
adding them up to calculate the average. Also, I'm lost with how to
use the pointer. This is what continues to print out almost
infinitely:
Student's ID: A0375 Student's name: Test score 1: 0Test score 2: 0Test score 3: 0Test score 4: 0Test score 5: 0Test score 6: 0Test
score 7: 0Test score 8: 0Test score 9: 0Test score 10: 0's average is:
0
and ends with the same student ID..
you need to flush the input stream before getline() I think its skipping getline() which would make it print out infinitely.
inFile.ignore();
getline(inFile, name);

Array Struct Not Printing Correctly

My Array struct won't print correctly. Can someone please help me?`I have to print an array struct of student grades data. The code seems to work, but I don't know what is going on when it prints the array struct. And it looks like the calcAvg function isn't functioning properly for some reason.
Code:
#include <iostream>
#include <fstream>
#include <cctype>
#include <cstring>
#include <iomanip>
using namespace std;
double calcAvg(double [][6], int);
double calcLow(double [][6], int);
double calcHigh(double [][6], int);
struct studInfo{
char fname[10];
char lname[10];
double low;
double high;
double average;
};
int main() {
ifstream input;
ifstream input2;
double scores [9][6];
char firstName[10];
char lastName[10];
int count = 0;
struct studInfo students[9];
input.open("cis_testGrades.txt");
while (!input.eof()){
for(int a = 0; a < 9; a++){
cout << "Student " << a+1 << ": ";
for(int b = 0; b < 6; b++){
input >> scores[a][b];
cout << scores[a][b] << " ";
}
cout << " " << endl;
}
}
input.close();
/*cout << calcAvg(scores, 9) << endl;
cout << calcHigh(scores, 9) << endl;
cout << calcLow(scores, 9) << endl;*/
input2.open("cis_students.txt");
while (!input2.eof()){
input2 >> firstName;
//firstName >> students[count].fname;
strcpy(students[count].fname, firstName);
input2 >> lastName;
//lastName >> students[count].lname;
strcpy(students[count].lname, lastName);
students[count].low = calcLow(scores, count);
students[count].high = calcHigh(scores, count);
students[count].average = calcAvg(scores, count);
count++;
}
input2.close();
for(int a = 0; a < 9; a++)
cout << students[a].fname << " " << students[a].lname << " " << students[a].low << " " << students[a].high << " " << students[a].average << endl;
return 0;
}
double calcAvg(double grades[9][6], int student){
double average;
double sum;
for(int a = 0; a < 6; a++)
sum += grades[student][a];
average = sum/6;
return average;
}
double calcHigh (double grades[][6], int student){
double high = 0;
for(int a = 0; a < 6; a++) {
if (grades[student-1][a] >= high)
high = grades[student-1][a];
}
return high;
}
double calcLow (double grades[][6], int student){
double low = 100;
for(int a = 0; a < 6; a++) {
if (grades[student-1][a] <= low)
low = grades[student-1][a];
}
return low;
}
cis_TestGrades.txt:
99 86 88 89 85 78 73 74 72 61 62 63 57 58 93 97 81 81 85 79 75 72 73 64 66 69 68 59 54 49 95 92 98 89
87 83 71 70 76 65 60 61 84 82 81 80 77 73 74 78 70 71 72 79
cis_students.txt:
Robert Smallwood
Mary Stevens
Sally Moore
John Perkins
Connor Cousins
William Laws
Renee Rivers
Thomas Carver
Donna Smith
Output:
Student 1: 99 86 88 89 85 78
Student 2: 73 74 72 61 62 63
Student 3: 57 58 93 97 81 81
Student 4: 85 79 75 72 73 64
Student 5: 66 69 68 59 54 49
Student 6: 95 92 98 89 87 83
Student 7: 71 70 76 65 60 61
Student 8: 84 82 81 80 77 73
Student 9: 74 78 70 71 72 79
Robert Smallwood 6.32404e-322 5.96342e+228 9.93903e+227
Mary Stevens 78 99 84
Sally Moore 61 74 90.1667
John Perkins 57 97 90.8333
Connor Cousins 64 85 75
William Laws 49 69 102.167
Renee Rivers 83 98 83.5
Thomas Carver 60 76 92.1667
Donna Smith 73 84 88
In every function you are starting from array[-1], and in C/C++ you won't get an exception it will just take what is in memory before the array.
Change [student-1] to [student] and initialise sum to 0.
Advice for future: don't use 'magic numbers' in loops, declare them as a variable and then you can just change it in one place, less likely error prompt behaviour.
Compiled with VS 2015:
#include <iostream>
#include <fstream>
#include <cctype>
#include <cstring>
#include <iomanip>
#include <string>
using namespace std;
double calcAvg(double[][6], int);
double calcLow(double[][6], int);
double calcHigh(double[][6], int);
struct studInfo
{
string fname;
string lname;
double low;
double high;
double average;
} ;
int main()
{
ifstream input;
ifstream input2;
double scores[9][6];
string firstName;
string lastName;
int count = 0;
struct studInfo students[9];
input.open("cis_testGrades.txt");
while (!input.eof())
{
for (int a = 0; a < 9; a++)
{
cout << "Student " << a + 1 << ": ";
for (int b = 0; b < 6; b++)
{
input >> scores[a][b];
cout << scores[a][b] << " ";
}
cout << " " << endl;
}
}
input.close();
/*cout << calcAvg(scores, 9) << endl;
cout << calcHigh(scores, 9) << endl;
cout << calcLow(scores, 9) << endl;*/
input2.open("cis_students.txt");
while (!input2.eof())
{
input2 >> firstName;
students[count].fname = firstName;
//strcpy(students[count].fname, firstName);
input2 >> lastName;
students[count].lname = lastName;
//strcpy(students[count].lname, lastName);
students[count].low = calcLow(scores, count);
students[count].high = calcHigh(scores, count);
students[count].average = calcAvg(scores, count);
count++;
}
input2.close();
for (int a = 0; a < 9; a++)
cout << students[a].fname << " " << students[a].lname << " " << students[a].low << " " << students[a].high << " " << students[a].average << endl;
return 0;
}
double calcAvg(double grades[][6], int student)
{
double average;
double sum = 0;
for (int a = 0; a < 6; a++)
sum += grades[student][a];
average = sum / 6;
return average;
}
double calcHigh(double grades[][6], int student)
{
double high = 0;
for (int a = 0; a < 6; a++)
{
if (grades[student][a] >= high)
high = grades[student][a];
}
return high;
}
double calcLow(double grades[][6], int student)
{
double low = 100;
for (int a = 0; a < 6; a++)
{
if (grades[student][a] <= low)
low = grades[student][a];
}
return low;
}
In
double calcAvg(double grades[9][6], int student)
sum is defined as
double sum;
but is not initialized before
sum += grades[student][a];
so the value of sum at the beginning of the operation is unknown. Could be zero. Could be a billion.
Solution: Initialize sum.
double sum = 0;
In addition in double calcHigh (double grades[][6], int student)
if (grades[student-1][a] >= high)
student-1 is almost certainly not the student whose grades you want to compute. Where this fails particularly bad is student 0 who will be computed on grades[-1] which does not exist and invokes undefined behaviour.
Solution
if (grades[student-1][a] >= high)
calcLow has the same problem.

not reading file line by line

So i need to read n numbers from a file and print on screen only those that are prime. The code to determine if a number is prime is working but after it checks a number it doesn't want to check the other n numbers.
#include <iostream>
#include <fstream>
#include <conio.h>
using namespace std;
int main()
{
int n = 0;
unsigned int x = 0;
cout << "n= ";
cin >> n;
ifstream f("numbers.txt");
for (int i = 1; i <= n; i++)
{
int p = 1;
f >> x;
if (x % 2 == 0)
{
if (x == 2)
cout << x << endl;
}
else
{
for (int i = 3; i <= x / 2; i++)
{
if (x%i == 0)
p = 0;
}
if (p == 1)
cout << x << endl;
}
cout << "i= " << i << "x= " << x<<endl;
}
f.close();
_getch();
return 0;
}
the file is
53
34
65
234
756
342
988
997
1
2
97
234
87
234
867
37
234
and this is a test of the output to a file since i can't post images
53
i= 1x= 53
i= 2x= 34
i= 3x= 65
i= 4x= 234
i= 5x= 756
i= 6x= 342
i= 7x= 988
You should read the file by this way :
std::ifstream f("your_file_name.txt");
unsigned long int x;
while(f >> x) // will be 0 when the value can't be read (= at the end of the file)
if(is_prime(x))
std::cout << x << std::endl;
Note that it's not needed to close the file at the end of the scope. The destructor of f will do this job.

Resources