Solved

replace code and create functions (rush!)

Posted on 2004-04-11
14
409 Views
Last Modified: 2010-04-01
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;

}
====================================================================
0
Comment
Question by:AliciaVee
  • 6
  • 5
  • 3
14 Comments
 
LVL 11

Expert Comment

by:bcladd
Comment Utility
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
0
 
LVL 44

Expert Comment

by:Karl Heinz Kremer
Comment Utility
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 ';'

0
 

Author Comment

by:AliciaVee
Comment Utility
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
0
 
LVL 44

Expert Comment

by:Karl Heinz Kremer
Comment Utility
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.

0
 

Author Comment

by:AliciaVee
Comment Utility
khk,

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

I'll be back.
:)

AV
0
 

Author Comment

by:AliciaVee
Comment Utility
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;

}

0
 
LVL 11

Expert Comment

by:bcladd
Comment Utility
(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
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 11

Accepted Solution

by:
bcladd earned 250 total points
Comment Utility
The following address your compiler errors. Number after colon is the approximate line number.

gpa.cpp:8
double sumGrades(ifstream& inp, double& fsumGPA, msumGPA);
typename expected: Notice that there is no type for msumGPA. Assume it is double&

gpa.cpp:9
bool openFiles;
not actually a compiler error: If the function has parameters, include them in (); if there are no parameters, include the () so C++ knows it is a function.

gpa.cpp:10
void initialize (double& fsumGPA, msumGPA, tsumGPA, tsumStudents, int& countMale, countFemale);
typename expected: countFemale has no type

gpa.cpp:11
void sumGrades(double& fsumGPA, msumGPA)
typename expected:
Would you believe it took me to this point to realize the core problem? Declaring parameters for functions looks just like declaring variables but it isn't. You have to specify a type for each and every parameter. So the list consists of a type and a name for the parameter then a comma, a type and a name for the parameter. Should fix many errors.

Where to declare variables. This is a really good question. The answer is simple to state but sometimes hard to understand: Declare variables inside of the highest function where they are used. By height I mean in terms of calling. So if a variable is going to be used in main, initialize, and sumGrades, then it should be declared in main (main is called  by the OS and is called first. The other two are called directly from main so they are "lower"). You should pass the variable into the other functions as a parameter.

Here is the hard part, right? It looks like a parameter is a variable declaration and, for most purposes, it is. But, when passing things around as parameters, especially  reference parameters, we need one declaration of the actual variable and then we pass it in (and/or out) of other functions as a parameter so they can either use or set the value. So, for example, your initialize function has some logical problems. You should declare NO variables in initialize as all the variables will be passed in from main and have their values set in initialize. As in:

void initialize (double& fsumGPA, double & msumGPA,
                 double & tsumGPA, double & tsumStudents,
                 int& countMale, int & countFemale)
{
  countFemale = 0;
  countMale = 0;
  msumGPA = 0.0;
  fsumGPA = 0.0;
  tsumGPA=0;
} // initialize
/* I took the above from your code, cleaned up the indentation, removed a ; from after the ) in the parameter list (when defining the function you can't use the ; and when writing a prototype you MUST use the ;) and removed the type name in front of the variables inside the function. That way the PARAMETERS are set to the initial values. Since the streams are not passed in, there are not mentioned here. Now, in main() you must declare the variables and pass them as parameters to initialize*/
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
  double tsumGPA=0;//totals both female and male GPA
  ifstream myInFile;
  ofstream myOutFile;

  initialize(fsumGPA, msumGPA, tsumGPA, tsumStudents, countMale, countFemale);
  /* Notice that the order of the variables must match the order in the function's parameter list. This is important. The types must match in order but there is no requirement that the names match. */
  // ... and so on
} // main


Hope this helps,
-bcl
0
 
LVL 44

Assisted Solution

by:Karl Heinz Kremer
Karl Heinz Kremer earned 250 total points
Comment Utility
There are a few more errors:

Your main function looks like this (blank lines removed):

//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;
}

Your main function is missing the open brace:

int main()
{
    if (!OpenFiles)
    {
        ...
    }
    return 0;
}

Also, when you call OpenFiles, you are only checking a variable, and not calling a function, also C++ is case sensitive, so you need to name the function exactly like you defined it:

    if (!openFiles())
    {
        ...
    }

BTW: I share bcl's view of how to help with homework. You _HAVE_ to make these mistakes. This is the only way to learn. You are learning two things here: The C++ syntax (which is e.g. how to define a function and how to call it), but also "programming", which is way more than just the syntax of a language. It's the "feeling" for a language and how to solve programs in code. You can only learn this by making these mistakes and making them again in your next assignment, and again and again, until you finally "get" it. You need lots of practice, way more than you may realize right now.
0
 

Author Comment

by:AliciaVee
Comment Utility
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.

:)
0
 

Author Comment

by:AliciaVee
Comment Utility
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
0
 
LVL 44

Expert Comment

by:Karl Heinz Kremer
Comment Utility
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.
0
 

Author Comment

by:AliciaVee
Comment Utility
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;

}

0
 
LVL 44

Expert Comment

by:Karl Heinz Kremer
Comment Utility
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.
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Suggested Solutions

This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now