Thread: Seeking Help on my 1st C++ class program!

  1. #1
    Registered User
    Join Date
    Apr 2003
    Posts
    17

    Seeking Help on my 1st C++ class program!

    Hi,
    First of all, thank you for opening this post. This is my first C++ program with classes, and I've ran into some trouble.

    I am writing program using a class that stores first name, last name, and age for each person. Then, using that info, it calculates average of ages of several people and deviation from avg. for each person.

    My problem is my member function "compute_avg()" does not return proper average even though when I output value of average within it, it gives correct average. Because avg. is returned incorrectly, deviation from avg for each person is incorrect as well.

    I am posting the code and sample output here for convenience, but you can also download it from attachment. Thank you very much for your help in advance. I need this ASAP!

    Code:
    #include <iostream>
    
    using std::cout;
    using std::cin;
    using std::getline;
    using std::endl;
    
    #include <iomanip>
    
    using std::ios;
    using std::setw;
    using std::setprecision;
    
    #include <cstring>
    
    
    class Personal {
       
    public:
       
       // constructor
       Personal(const char *fname="Joe", const char *lname="Smith", const int years_old=0);
       
       // set functions
       void input_personal(); // input data of 1 person
       double compute_avg(); // find average of ages
       double dev_from_avg(); // compute deviation from average
       
       // get function
       void print_data(); // prints data of each in formatted output incl. average of ages 
       
       // destructor
       ~Personal();
       
    private:
       
       char first_name[30]; // store first name of max. 30 characters
       char last_name[30];  //  store last name of max. 30 characters
       int age; // store age
       double avg; // store average
       double dev_diff; // store person's deviation from the average
    
    };
    
    
    // constructor
    Personal::Personal(const char *fname, const char *lname, const int years_old) 
    
    { 
      
       // copy fname into first_name and be sure it fits
      int length = strlen(fname); // what is name?
      length = (length < 30 ? length : 29);
      strncpy (first_name, fname, length);
      first_name[length] = '\0';
     
       // copy lname into last_name and be sure it fits
      length = strlen(lname); // what is name?
      length = (length < 30 ? length : 29);
      strncpy (last_name, lname, length);
      last_name[length] = '\0';
     
      // error check value put into age
      age = (years_old < 150 ? years_old : 0); // default age at 0
      avg = 0; // set avg to 0 for each new object
      dev_diff = 0; // set deviation difference from avg to 0
    
    
    } // end Personal constructor
    
    
    // input Personal info.
    void Personal::input_personal() 
    {
      
       for (int r=0; r < 30; r++) {
        
          first_name[r] = '\0';
          last_name[r] = '\0';
       
       }
       
       cout << "Enter first name: ";
       cin >> setw(30) >> first_name; // input first name
          
       cout << "Enter last name: ";
       cin >> setw(30) >> last_name; // input last name
       
       cout << "Enter age: "; 
       cin >> age;
       while (age < 0 || age > 150) {
         cout << "Age must be between 0 to 150. Re-enter: ";
         cin >> age;
       } 
       
    } // end function input_personal
    
    
    double Personal::compute_avg() 
    {
       static int total = 0;
       static int count = 0;
       
       total += age;
       count++;
       
       avg = static_cast <double> (total) / count; 
       
       return avg;
    } // end function compute_avg
    
    
    double Personal::dev_from_avg() {
    
      dev_diff = age - avg;
    
      return dev_diff;
    } // end function dev_from_avg
    
    void Personal::print_data() {
           
       cout << last_name << ", " << first_name << " " << age << " " 
            << ios::showpos << dev_diff << endl; 
     
    }
    
    // destructor
    
    Personal::~Personal() {
    
    }
    
    
    int main()
    {
       const int NUM = 2; // define for how many people to output personal info.
                          
       Personal person[NUM];
       double average;
       
       for (int k=0; k < NUM; k++) {
          person[k].input_personal(); // input info. for each person
      
       }
       
       for (int b=0; b < NUM; b++) {
          average = person[b].compute_avg(); // finds average for each new person
      
       } 
       
       // output average only after the last person     
       cout << "\nThe average of ages is: " << ios::dec << setprecision(1)
            << average << endl;
         
       for (int c=0; c < NUM; c++) {
          person[c].dev_from_avg(); // finds deviation from avg for each person
       }
     
       for (int r=0; r < NUM; r++) {
       
          person[r].print_data();
       
       }
       cout << endl;
       
       return 0;
    }
    Sample Output:
    -------------------
    Enter first name: Justin
    Enter last name: Smith
    Enter age: 20
    Enter first name: Joe
    Enter last name: Smith
    Enter age: 22

    The average of ages is: 22e+01
    Smith, Justin 20 20480
    Smith, Joe 22 20481
    -----------------------------------------

    Once again, I appreciate your time and effort in helping me find the error. Thank you.

    Justin

  2. #2
    Registered User The Dog's Avatar
    Join Date
    May 2002
    Location
    Cape Town
    Posts
    788
    Ok, from what I see I think that this is what you want to do:

    Create many Personal objects and find the average age.

    What you should then do is write a method outside of the class, ( outside main() ), which calculates the averages. An array of personal objects would then be passed to the function. If there are more functions that would deal with many objects, then you could wrap them in a class called PersonalManager for instance.

  3. #3
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    If you do what The Dog said, you can make the compute_avg() function a friend function, and then you won't have to create a helper function to give you access to the private data members.

    Or, you could create static data members of the class that keep track of the total age and the number of objects, and then you can use a single object to access that data to calculate the average.
    Last edited by 7stud; 05-18-2003 at 03:01 PM.

  4. #4
    What don't you use
    Code:
    using namespace std;
    instead? But doing it your way would be better for learning since you will learn what namespace things belong to.

  5. #5
    Registered User
    Join Date
    Apr 2003
    Posts
    17

    Fixed my problem

    Well, thank you guys for your suggestions. I fixed my problem by getting rid of member function compute_avg(). Instead, I created a get_age() member function. So, I keep a running total of the age in main() in a loop. Then, I find the average in main() by dividing by number of objects.

    7stud said:

    Or, you could create static data members of the class that keep track of the total age and the number of objects, and then you can use a single object to access that data to calculate the average.
    My questions are:

    1) How do I get access to that single object in main() when I have an array of <i>Personal</i> objects?
    2) If I want to calculate the average of ages of Personal objects of only a certain range, how would I do that without doing it in main()?


    Thank you in advance for your answers.

    -Justin
    P.S. my new correctly functioning code is below:

    Code:
    #include <iostream>
    
    using std::cout;
    using std::cin;
    using std::getline;
    using std::endl;
    
    #include <iomanip>
    
    using std::setw;
    using std::setprecision;
    
    #include <cstring>
    
    
    class Personal {
       
    public:
       
       // default constructor
       Personal(const char *fname="Joe", const char *lname="Smith", const int years_old=20);
       
       // set functions
       void input_personal(); // input data of 1 person including first name, last name, and age
       void print_data(float); // must send average as argument to function to find deviation of 
                                // each person's age from the average, and then output in neat format
       
       // get functions
       inline int get_age() const; // gets age of each person
        
       // destructor
       ~Personal();
       
    private:
       
       char first_name[30]; // store first name of max. 30 characters
       char last_name[30];  //  store last name of max. 30 characters
       int age; // store age
    
    };
    
    
    // constructor
    Personal::Personal(const char *fname, const char *lname, const int years_old) 
    
    { 
      
       // copy fname into first_name and be sure it fits
      int length = strlen(fname); 
      length = (length < 30 ? length : 29);
      strncpy (first_name, fname, length);
      first_name[length] = '\0';
     
       // copy lname into last_name and be sure it fits
      length = strlen(lname);
      length = (length < 30 ? length : 29);
      strncpy (last_name, lname, length);
      last_name[length] = '\0';
     
      // error check value put into age
      age = (years_old < 150 ? years_old : 20); // default age at 0
      
    } // end Personal constructor
    
    
    // input Personal info.
    void Personal::input_personal() 
    {
       // How come I don't need to enter a null at the end? Does setw restriction put one in 30th character?
       cout << "Enter first name: ";
       cin >> setw(30) >> first_name; // input first name
       int length = strlen(first_name);
       first_name[length]='\0';
          
       cout << "Enter last name: ";
       cin >> setw(30) >> last_name; // input last name
       length = strlen(first_name);
       first_name[length]='\0';
       
       cout << "Enter age: "; 
       cin >> age;
       while (age < 0 || age > 150) {
         cout << "Age must be between 0 to 150. Re-enter: ";
         cin >> age;
       } 
       
    } // end function input_personal
    
    inline int Personal::get_age() const {
       return age;
    }
    
    void Personal::print_data(float avg) {
       
       float avg_diff = age - avg;
       
       cout << last_name << ", " << first_name << " " << age << " " 
            << avg_diff << endl;
    }
    
    //destructor
    Personal::~Personal() {
    
    }
    
    
    int main()
    {
       const int NUM = 10; // define for how many people to output personal info.
                          
       Personal person[NUM];
       unsigned int total_age=0;
       float average, dev_from_avg;
       
       for (int k=0; k < NUM; k++) {
          person[k].input_personal(); // input info. for each person
      
       }
      
       for (int b=0; b < NUM; b++) {
          total_age += person[b].get_age(); // finds running total of the ages
       } 
       
       average = total_age / NUM;
       
       cout << "\nThe average of the ages is " << setprecision(10) << average << endl;
              
       for (int r=0; r < NUM; r++) {
          person[r].print_data(average); // must pass average so it can calculate deviation from avg
                                         // and output it along with other info. in print_data()
       }
       cout << endl;
       
       return 0;
    }

  6. #6
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    1) How do I get access to that single object in main() when I have an array of <i>Personal</i> objects?

    If a class has a static data member, any and all objects of the class have access to it. An array of objects is made up of individual objects, isn't it?


    2) If I want to calculate the average of ages of Personal objects of only a certain range, how would I do that without doing it in main()?

    Create a function called range_average() that takes as parameters the array of objects, the starting index position and the ending index position of the range you want.

  7. #7
    ¡Amo fútbol!
    Join Date
    Dec 2001
    Posts
    2,138
    Originally posted by Munkey01
    What don't you use
    Code:
    using namespace std;
    instead? But doing it your way would be better for learning since you will learn what namespace things belong to.
    Umm... No

    Obviously, this person knows that all of the things belong to the std namespace by stating using std::whatever. Using namespace std should only be used when writing quick apps or code for demonstration. By using it, one imports all of the std namespace. Therefore, it increases the odds that the names that you use may conflict with names in the header file.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. problem in pass a variable to a class
    By nima_pw in forum C# Programming
    Replies: 3
    Last Post: 06-09-2009, 07:30 AM
  2. deriving classes
    By l2u in forum C++ Programming
    Replies: 12
    Last Post: 01-15-2007, 05:01 PM
  3. BOOKKEEPING PROGRAM, need help!
    By yabud in forum C Programming
    Replies: 3
    Last Post: 11-16-2006, 11:17 PM
  4. Need help to build network class
    By weeb0 in forum C++ Programming
    Replies: 0
    Last Post: 02-01-2006, 11:33 AM
  5. structure vs class
    By sana in forum C++ Programming
    Replies: 13
    Last Post: 12-02-2002, 07:18 AM