Link to home
Start Free TrialLog in
Avatar of AliciaVee
AliciaVee

asked on

replace code and create functions (rush!)

Experts,

Okay, I am 'just' learning C++ and up until now have been doing great with my assignments (yes, this is a class).  Here is, only 3 weeks left for the course, and this chapter really threw me for a loop (no pun intended) and I'm confused on how to create functions for certain tasks.

I wrote a simple program that calculates GPA averages for university students.  It works -- all is good.  I now have to remove a lot of the code and replace with functions.  I've been reading and trying different things for the past 3 hours, and nothing is working.  I need some guidance here...

The new functions I have to create are:

Function OpenFiles:
opens the input and output files, sets the output of the floating point nubmers to two decimal places in a fixed decimal format with a decimal point and trailing zeros

Function initialize:
initializes variables - countFemale, countMale, fsumGPA, msumGPA

Function sumGrades
find the sums of femail and make students GPAs

Function averageGrade:
finds the average GPA for female and male students

Function printResults:
output the releveant results.

Note:  cannot use global variables.  need to use the appropriate parameters to PASS information in/out of the functions (so need a by ref functions)

I'm a mess cause I can get it to work.  Instead of sending you my 'mess', here is my original code, which I wrote and totally understand, but to get in my head to switch it all around is confusing (I could do one or two of these,....but not all of them at the same time...HELP!)


My code:

==========================================================================
#include <iostream.h>
#include <fstream.h> // required statement for file I/O
#include <iomanip.h> // required statement to use manipulators


int main()

{
int countFemale = 0; // variable for total of females
int countMale = 0; //variable for total of males
double msumGPA = 0.0; // variable for total male GPA
double fsumGPA = 0.0; //variable for total female GPA

char studentType; // variable stores whether male or female
double studentGPA =  0; // variable stores GPA to be used in calculations

ifstream infile;
ofstream outfile;

infile.open("a:GPA.txt"); // open input file

if(!infile) // if file is not found, then message displays and program shuts down
{
      cout<<"Cannot open input file"<<endl;
      cout<<"Program terminates!!"<<endl;
      return 1;
}

// file is found, and program continues

outfile.open("a:GPAdone.txt");
outfile.setf(ios::fixed,ios::floatfield);
outfile.setf(ios::showpoint);
outfile<<setprecision(2);

cout<<"Processing data...."<<endl;

infile>>studentType>>studentGPA;

while(infile)
{
      switch(studentType)// loops through and finds female or male and counts each separatly
      {
      case 'F':
      case 'f': fsumGPA = fsumGPA + studentGPA;
            countFemale++;
            break;

      case 'M':
      case 'm': msumGPA = msumGPA + studentGPA;
            countMale++;
            break;

      default: cout<<"Invalid Student Data"<<endl;
      } // end switch

      infile>>studentType>>studentGPA;

} // end while looping


//Output the results

outfile<<"The total number of female students is "<<countFemale<<endl;
outfile<<"The average GPA for female students is "<<fsumGPA/countFemale<<endl;
outfile<<endl;
outfile<<"The total number of male students is "<<countMale<<endl;
outfile<<"The average GPA for male students is "<<msumGPA/countMale<<endl;
outfile<<endl;
outfile<<"The total number of all students is "<<countFemale+countMale<<endl;
outfile<<"The average GPA for all students is "<<(fsumGPA + msumGPA)/(countFemale+countMale)<<endl;
outfile<<endl;

      return 0;

}
====================================================================
Avatar of bcladd
bcladd

Okay, let's focus on the first function you are supposed to write, OpenFiles. What we want to do is identify the parameters you are going to need, the return type of the function, and had how you are going to call it.

It is supposed to open the input and output files. Without global variables (it is GOOD to use no global variables), the files that are opened must be parameters (when thinking about parameters, think about communication. What information must be communicated between the caller and the callee. Here we must communicate the open, established input and output streams FROM OpenFiles back TO main...). Since they are OUTPUT from the function, they have to be reference parameters (do you understand the difference between pass by value (passing a COPY into the function) and pass by reference (passing a reference to the original item)? If not, ask). Using your program as a model, we don't need any other information as the name of the input and output files are fixed as are the various settings. So the only communication is from the called function back to main passing the opened files.

Wait, a mistake in the previous statement: We should also communicate the success or failure of opening the two streams. Easiest way to do that? Have the function return a boolean value, true if the files are opened, false otherwise. That way you can check the return code in main, if it is false you can exit (as you do now if either of the files is not opened properly).

Does the analysis make sense? Given this description, we can write the signature of the function:

bool OpenFiles(ifstream & infile_param, ofstream & outfile_param)
{
  // DO SOME WORK HERE
}

Then, in main, we can imagine how to call the function:

if (!OpenFiles(infile, outfile)) {
  // HANDLE FAILURE (return 1)
}

Now, what goes into the function? All the code to open the files. That is the infile.open() line, the check for success, the outfile.open() line and the check for success there. Only differences: You want to return false rather than 1 if there is a problem; the names of the variables was changed (I added _param to the end so you can tell the difference when reading them; not strictly necessary but it can give you a heads up on where the variable came from) and the function must return true if it reaches the end (both of the success if statements return short of this so it will return false or true depending solely on the success of opening the two files).

I have spelled this one out. The others are similar in that you want to figure out what is being communicated, how it is communicated (into, out of or into and out of the function), and then how it is being calculated (what part of main you will be replacing with a call to your function). I would suggest just replacing one item at a time since you can compare the output with the original.

HTH, -bcl
There is one thing bcladd did not talk about yet :-) which is required (you may get your program to work without is however).

You are already using one function: main() which already returns a status. You are not calling this function directly, it gets called by the operating system (actually by the program loader, or runtime linker). All you have to do now is pretty much like writing your main function - just a bit more complicated :-)

You don't have to tell the compiler about main(), because the linker "knows" that it has to be there. This can be shown by e.g. renaming the main() function to main_x(). If you compile your program again, you will end up with an error message.
When you create your own functions, the compiler doesn't know about them, so you have to "introduce" them to the compiler before you use them. You can actually just write them and use them without this "introduction" (or declaration), but this requires that you define them before they get used. The right way to handle this is however to declare the functions first. At the top of your program (right after the include statements), you would add these function declarations. If we take the function from bcl's example, the declaration would look like this:

bool OpenFiles(ifstream & infile_param, ofstream & outfile_param);

You see, it's exactly the same as the start of the function definition, just without the actual implementation. You need to end the declaration with a ';'

Avatar of AliciaVee

ASKER

bcladd,

Wow!  your explanation is quite thorough and just want I need to try and figure this out -- although, I thought I was doing what you mentioned, probably not in the right order.  its still confusing to me, but I'll do as you suggest and take one function at a time and see if I can get something to work.  The problem I have is that one function depends on another and am not sure how this is all going to work.  I tried doing it all at once, because I thought I had to reference the parameters, and I'm still not clear on the ref and val usage (this was all new in this chapter).  We haven't done functions at all yet...except for this unit, and trying to package them all in one program was hard for me to handle.

But, I'll re-read through your outline and see if I can get the concept.  stay tuned....

khk -- thanks for mentioning that....yes, this part was covered in our chapter and I will make sure I don't forget to incorporate that in.

AV
You can start with the output function, this should not depend on any other function. All you need is a mechanism to pass in your data.

Your main function should call all your functions in the right order, so you should be able to do one after the other.

If you have something to show, just post your code here.

khk,

thanks for your encouragement and road map.  Just starting on it....will be  a while I'm sure....

I'll be back.
:)

AV
bcladd,

Sorry, althougth I would have loved to 'figure it out' I just cant, which is why I posted this.  I read what you said, and thought maybe it might help me see the light, but here I am, another 2 hours...and am not any close.

I am confused because:

I don't know where to declare the variables;
I don't know how to use the initiatlize function that I am requred to do;
I am confused on when to use a by ref, or a value, or a void fuction.

Please...I NEED MORE HELP.  AT this point, can you GIVE me the solution?.  I can learn a lot better if I see how it works, and then can understand the concept going forward.

Here is what I came up with, trying to move things around, and trying to figure out how to call a function by ref, by val, or void...initialize...its a mess!

Suprisingling, I only get 5 compile errors.  I dare not run it cause my PC might blow up!

#include <iostream.h>
#include <fstream.h> // required statement for file I/O
#include <iomanip.h> // required statement to use manipulators


//Function Prototypes
double sumGrades(ifstream& inp, double& fsumGPA, msumGPA);
bool openFiles;
void initialize (double& fsumGPA, msumGPA, tsumGPA, tsumStudents, int& countMale, countFemale);
void sumGrades(double& fsumGPA, msumGPA)



//this function initializes variables such as
//countFemale, countMale, fsumGPA, msumGPA
void initialize (double& fsumGPA, msumGPA, tsumGPA, tsumStudents, int& countMale, countFemale);
{

int countFemale = 0; // variable for total of females
int countMale = 0; //variable for total of males
double msumGPA = 0.0; // variable for total male GPA
double fsumGPA = 0.0; //variable for total female GPA
double tsumGPA=0;//totals both female and male GPA
ifstream myInFile;
ofstream myOutFile;

}

//in the main section, I will get and print the GPA

int main()


if(!OpenFiles) // if file is not found, then message displays and program shuts down
{
      cout<<"Cannot open input file"<<endl;
      cout<<"Program terminates!!"<<endl;
      return False;
}


      return 0;

}


//this function opens the input/output file, sets the output
//of the floating-point numbers to 2 decimal placed in a fixed
//format with a decimal point and trailing zeros

bool openFiles (ifstream& myInFile, ofstream& myOutFile)
{
      myInFile.open("a:GPA.txt"); // open input file

outfile.open("a:studentGradesdone.txt");
outfile.setf(ios::fixed,ios::floatfield);
outfile.setf(ios::showpoint);
outfile<<setprecision(2);

cout<<"Processing data...."<<endl;

}


//this function finds the sum GPA for female and male students
//Steps: read the input, get the input, print the GPA
void sumGrades(double& fsumGPA, msumGPA)

char studentType; // variable stores whether male or female
double studentGPA =  0; // variable stores GPA to be used in calculations

infile>>studentType>>studentGPA;

while(infile)
{
      switch(studentType)// loops through and finds female or male and counts each separatly
      {
      case 'F':
      case 'f': fsumGPA = fsumGPA + studentGPA;
            countFemale++;
            break;

      case 'M':
      case 'm': msumGPA = msumGPA + studentGPA;
            countMale++;
            break;

      default: cout<<"Invalid Student Data"<<endl;
      } // end switch

      infile>>studentType>>studentGPA;

} // end while looping


//this function finds the average GPA for female and male students
void averageGrade(double& fsumGPA, msumGPA)

{


      tsumStudents = countFemale+countMale;
      tsumGPA = (fsumGPA + msumGPA)/(countFemale+countMale)
}


//this function outpus the relevant results
//Steps: calculate the GPA, print the GPA
void printResults(double& averageGrade)

{

outfile<<"The total number of female students is "<<countFemale<<endl;
outfile<<"The average GPA for female students is "<<fsumGPA/countFemale<<endl;
outfile<<endl;
outfile<<"The total number of male students is "<<countMale<<endl;
outfile<<"The average GPA for male students is "<<msumGPA/countMale<<endl;
outfile<<endl;
outfile<<"The total number of all students is "<<tsumStudents<<endl;
outfile<<"The average GPA for all students is "<<tsumGPA<<endl;
outfile<<endl;

}

(1) No, I can't give you the solution. It is against the EE policy and against my own conscience.

(2) I will try to help you by answering your questions and helping you hunt down your bugs. This will take me a couple of minutes (need to compile your code).

-bcl
ASKER CERTIFIED SOLUTION
Avatar of bcladd
bcladd

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
bcladd,

Wow...thanks -- really.  Okay, I was really stressing before, got a cup of java (like in coffee) and I feel I can spend more time to figure this out.  By the way -- I didn't know that EE cannot give help with homework assignments.  Makes sense I guess.

khk -- also much thanks to you too -- for your comments and explanations.

Back to my code....will be in touch soon.

:)
Okay...  I'm done.

I guess both of you helped -- or at least tried to help me understand.  I'm still very confused.  It doesn't make sense to me, am sure I'm missing something.

I have to use an initialize function, to initialize variables, but I don't set them, and then I declare them again in main.  I don't see the value of using a function to initialize variables then?

its still not working...

but for now I'm done.  I can't get it....I think it was a lot to try and learn in one chapter jumping from learning a simple function to voids, ref, val, and all this other stuff for one assignment.

I'll take whatever credit I can and just wait till the teach marks up my assignment.

thanks in any event.

aliciaVee
Show your code, we will certainly give you more input.

You need to understand the scope of variables. Your main function (hopefully) looks like this pseudo code:

int main()
{
    // variable declarations

    init(pass variables by reference);

    do_something_else(pass variables by reference or by value);

    return 0;
}

In this example you are first defining your (local) variables in your main routine. When you define them, the variables are _NOT_ initialized (that is as long as you are not using objects that have a constructor, but we leave this for some future homework :-). In order to initialize them, you pass them (by reference) into your init() function. Because they are passed by reference, the init() function can modify them. Once you return from the init() function, the local variables in your main() function are initialized. After that, you call some other functions that again can potentially modify your variables. You only pass those variables by reference that can be modified.
Here is my code....am getting all kinds of errrors.

The assignment is due tomorrow, so maybe I need to sleep on it and start fresh tomorrow
:(

I really was doing so well in this class up until now.  just not getting it.

more reading and re-readigng I guess.

thanks,
AV

========================================================================

#include <iostream.h>
#include <fstream.h> // required statement for file I/O
#include <iomanip.h> // required statement to use manipulators


//Function Prototypes
void sumGrades(ifstream& myInFile, double& fsumGPA, double& msumGPA);
void openFiles (ifstream& myInFile, ofstream& myOutFile);
void sumGrades(double& fsumGPA, double& msumGPA);
void averageGrade(double& fsumGPA, double& msumGPA);
void printResults(ofstream& myOutFile, double& averageGrade);



//in the main section, I will get and print the GPA

int main()
{
 
  int countFemale; // variable for total of females
  int countMale; //variable for total of males
  double msumGPA; // variable for total male GPA
  double fsumGPA; //variable for total female GPA
  double tsumGPA; //totals both female and male GPA
  ifstream myInFile;
  ofstream myOutFile;

if(!openFiles) // if file is not found, then message displays and program shuts down
{
      cout<<"Cannot open input file"<<endl;
      cout<<"Program terminates!!"<<endl;
      return 1;
}

return 0;

}


//this function initializes variables such as
//countFemale, countMale, fsumGPA, msumGPA
void initialize (double& fsumGPA, double & msumGPA, double & tsumGPA, double & tsumStudents,
                         int& countMale, int & countFemale)
{
    fsumGPA = 0.0;
      msumGPA = 0.0;
      tsumGPA=0;
      tsumStudents = 0;
      countFemale = 0;
      countMale = 0;
}


//this function opens the input/output file, sets the output
//of the floating-point numbers to 2 decimal placed in a fixed
//format with a decimal point and trailing zeros

void openFiles (ifstream& myInFile, ofstream& myOutFile)
{
      myInFile.open("a:GPA.txt"); // open input file

myOutFile.open("a:studentGradesdone.txt");
myOutFile.setf(ios::fixed,ios::floatfield);
myOutFile.setf(ios::showpoint);
myOutFile<<setprecision(2);

cout<<"Processing data...."<<endl;

}


//this function finds the sum GPA for female and male students
//Steps: read the input, get the input, print the GPA
void sumGrades(double& fsumGPA, double& msumGPA)

char studentType; // variable stores whether male or female
double studentGPA =  0; // variable stores GPA to be used in calculations

infile>>studentType>>studentGPA;

while(myInFile)
{
      switch(studentType)// loops through and finds female or male and counts each separatly
      {
      case 'F':
      case 'f': fsumGPA = fsumGPA + studentGPA;
            countFemale++;
            break;

      case 'M':
      case 'm': msumGPA = msumGPA + studentGPA;
            countMale++;
            break;

      default: cout<<"Invalid Student Data"<<endl;
      } // end switch

      myInFile>>studentType>>studentGPA;

} // end while looping


//this function finds the average GPA for female and male students
void averageGrade(double& fsumGPA, double& msumGPA)

{

      fsumGPA = fsumGPA/countFemale;
      msumGPA = msumGPA/countMale;
      tsumStudents = countFemale+countMale;
      tsumGPA = (fsumGPA + msumGPA)/(countFemale+countMale);
}


//this function outpus the relevant results
//Steps: calculate the GPA, print the GPA
void printResults(double& averageGrade)

{

outfile<<"The total number of female students is "<<countFemale<<endl;
outfile<<"The average GPA for female students is "<<fsumGPA<<endl;
outfile<<endl;
outfile<<"The total number of male students is "<<countMale<<endl;
outfile<<"The average GPA for male students is "<<msumGPA<<endl;
outfile<<endl;
outfile<<"The total number of all students is "<<tsumStudents<<endl;
outfile<<"The average GPA for all students is "<<tsumGPA<<endl;
outfile<<endl;

}

You are still not calling openFiles with the correct parameters.
The function sumGrades is declared twice, your implementation does not take the ifstream parameter (as it should, because you are using it). The fuction also is missing the top level braces. Also, you are using the wrong input stream variable when you read studentType and studentGPA.

you are using openFiles() in an if statement, but the function does not return any value. YOu need to change that.

There are more problems, but I don't have time right now to look further into this.