first fstream program
I am trying to write a program that gets data from this text file:
Then, based on this data, the program is supposed to calculate the average gpa of each gender (f=female, m=male) and output the results in a new file.
It must also contain these five functions:
openFiles: this function opens the input and output files and sets the output of floating-point numbers to two decimal places in a fixed decimal format with a decimal point and trailing zeros.
initialize: this function initializes variables.
sumGrades: This function finds the sum of the female and male students GPAs.
average grade: This function finds the average GPA for male and female students.
printResults: this function outputs the relevent results.
I think I've done pretty good coding up the functions and all but since this is my first program using fstream im not sure how i need to implement them in my main function.
Here is what i have so far:
header:
#ifndef header_h
#define header_h
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
#include <cstdlib>
using namespace std;
void extern initialize(int&, int&, float&, floa开发者_Python百科t&);
void extern openFiles(ifstream, ofstream);
void extern sumGrades(ifstream, ofstream, char, float, int&, int&, float&, float&);
void averageGrade (float&, float&, float, int, float, int);
void extern printResults (float, float, ofstream);
#endif
main:
#include "header.h"
int main()
{
char gender;
float gpa, sumFemaleGPA, sumMaleGPA;
ifstream inData;
ofstream outData;
int countFemale, countMale;
inData.open("./Ch7_Ex4Data.txt");
outData.open("./Ch7_Ex4Dataout.txt");
do
inData >> gender >> gpa;
while(!inData.eof());
inData.close();
outData.close();
system("PAUSE");
return EXIT_SUCCESS;
}
openFiles:
#include "header.h"
void openFiles(ifstream inData, ofstream outData)
{
inData.open("./Ch7_Ex4Data.txt");
outData.open("./Ch7_Ex4Dataout.txt");
outData << fixed << showpoint << setprecision(2);
inData.close();
outData.close();
}
sumGrades:
#include "header.h"
void sumGrades(ifstream inData, ofstream outData, char gender, float gpa, int& countFemale, int& countMale, float& sumFemaleGPA,
float& sumMaleGPA)
{
char m, f;
do
{
inData >> gender >> gpa;
if(gender == m)
{
sumMaleGPA += gpa;
countMale++;
}
else if (gender == f)
{
sumFemaleGPA += gpa;
countFemale++;
}
}
while(!inData.eof());
}
averageGrade:
#include "header.h"
void averageGrade (float& maleGrade, float& femaleGrade, float sumMaleGPA, int countMale, float sumFemaleGPA, int countFemale)
{
maleGrade = sumMaleGPA / static_cast<float>(countMale);
femaleGrade = sumFemaleGPA / static_cast<float>(countFemale);
}
printResults:
#include "header.h"
void
{
outData << "average male GPA: " << maleGrade << endl;
outData << "average female GPA: " << femaleGrade << endl;
}
You're making good progress.
You don't need the static_cast
s in averageGrade
.
printResults
is missing most of its function signature.
In sumGrades
, gpa
and gender
should be local variables, not parameters. You also want to compare to the character literals 'm'
and 'f'
, not variables named m
and f
with random contents.
Streams should ALWAYS be passed by reference, they can't be copied.
When reading from a stream, you should test the stream itself in your while loop, not eof()
.
Did you have a question?
You must pass the file streams by non-const references:
void extern openFiles(ifstream&, ofstream&);
sumGrades
and printResults
don't care that these streams are files, so you can pass just streams, still these must be references:
void extern sumGrades(istream&, ostream&, char, float, int&, int&, float&, float&);
void extern printResults (float, float, ostream&);
averageGrade
is missing extern
.
void extern averageGrade (float&, float&, float, int, float, int);
openFiles
does nothing useful. It opens files and closes them... You shouldn't close them:
void openFiles(ifstream& inData, ofstream& outData) {
inData.open("./Ch7_Ex4Data.txt");
outData.open("./Ch7_Ex4Dataout.txt");
outData << fixed << showpoint << setprecision(2);
// leave them open
}
The point is that you should call these function to open the files from main
:
// in main():
ifstream inData;
ofstream outData;
openFiles(inData, outData);
// call other functions to do the task.
// pass inData and outData as above, where stream arguments are expected.
// ...
Don;t do this:
do
{
inData >> gender >> gpa;
STUFF
} while(!inData.eof());
If it fails to read gender or gpa it still does stuff.
Wchich means that that the last line of your file was processed twice.
A better way to write this is:
while( inData >> gender >> gpa )
{
STUFF
}
Now STUFF is only done if gender and gpa are correctly read from the file.
This if statement is not required.
if(gender == m)
{
sumMaleGPA += gpa;
countMale++;
}
else if (gender == f)
{
sumFemaleGPA += gpa;
countFemale++;
}
You can use a map (or other container to hold these values). That way your code is more readable (and when we get a new third species easier to expand).
std::map<char, std::pair<double, int> > data;
std::pair<int,int>& value = data[gender];
value.first += gpa; // First contains the total gpa for a gender
value.second++; // Second contains the count of a gender.
Looks like this:
void readData(std::istream& in, std::map<char, std::pair<double,int> >& data)
{
char gender;
double gpa;
while(inData >> gender >> gpa)
{
data[gender].first += gpa;
data[gender].second ++;
}
}
//
// Notice that we pass streams by reference.
// Also notice that it is a generic stream not a file stream.
// This function does not need to know the output is going to a file
// so you can now re-use it to print to another type of stream std::cout
void writeData(std::ostream& out, std::map<char, std::pair<double,int> >& data)
{
for(std::map<char, std::pair<double,int> >::const_iterator loop = data.begin();
loop != data.end();
++loop
)
{
char gender = loop->first;
std::pair<double,int> value = loop->second;
out << gender << ": " << value.first / value.second << "\n";
}
}
int main()
{
std::map<char, std::pair<double,int> > data;
std::ifstream inData("./Ch7_Ex4Data.txt");
readData(inData, data);
std::ofstream outData("./Ch7_Ex4Dataout.txt");
writeData(outData, data);
// Don;t bother to close the files.
// This happens automatically when the file goes out of scope.
//
// Genereally you use close() manually when you want to catch a problem that
// is happening when you close the file. Since even if you did find a problem
// there is nothing you can do with the problem don;t do it.
//
// Also note: potentially close() can throw an exception.
// If you let the file close automatically with the destructor (it calls close
// catches the exception and throws it away).
}
printResults must not have copied correctly. I suspect it must have the signature
void printResults(float maleGrade, float femaleGrad);
When you are reading your file you need to see if the gender is m or f then branch and add the next GPA to the gender GPA.
something like
if(gender == "m"){
maleGPA += gpa;
maleCount++;
}
else{
femaleGPA += gpa;
femaleCount++;
}
// Call the next functions you copy pasted from your homework assignment
精彩评论