Freiermuth
Freiermuth

Reputation: 121

Operator not working correctly help needed

My program is almost done, but the output just doesn't get the right numbers.

Baby names: 
 1. Reading file: "src/people.txt" ... Number of lines in text file: 258000 number of lines in file is: 15 file has been read!
 2. Sorted by popularity:
  BabyNames object 
    1:  John 1880 0.081541 0
    2:   0 0 0
    3:   0 0 0
    4:   0 0 0
    5:   0 0 0
    6:   0 0 0
    7:   0 0 0
    8:   0 0 0
    9:   0 0 0
    10:   0 0 0
    11:   0 0 0
    12:   0 0 0
    13:   0 0 0
    14:   0 0 0
    15:   0 0 0
 3. Sorted by name:
  BabyNames object 
    1:  John 1880 0.081541 0
    2:   0 0 0
    3:   0 0 0
    4:   0 0 0
    5:   0 0 0
    6:   0 0 0
    7:   0 0 0
    8:   0 0 0
    9:   0 0 0
    10:   0 0 0
    11:   0 0 0
    12:   0 0 0
    13:   0 0 0
    14:   0 0 0
    15:   0 0 0
 4. Sorted by year:
  BabyNames object 
    1:  John 1880 0.081541 0
    2:   0 0 0
    3:   0 0 0
    4:   0 0 0
    5:   0 0 0
    6:   0 0 0
    7:   0 0 0
    8:   0 0 0
    9:   0 0 0
    10:   0 0 0
    11:   0 0 0
    12:   0 0 0
    13:   0 0 0
    14:   0 0 0
    15:   0 0 0
 5. Original names:
  BabyNames object 
    1:  John 1880 0.081541 0
    2:   0 0 0
    3:   0 0 0
    4:   0 0 0
    5:   0 0 0
    6:   0 0 0
    7:   0 0 0
    8:   0 0 0
    9:   0 0 0
    10:   0 0 0
    11:   0 0 0
    12:   0 0 0
    13:   0 0 0
    14:   0 0 0
    15:   0 0 0
Destructor to deallocate memory... Done!
Destructor to deallocate memory... Done!
Destructor to deallocate memory... Done!
Destructor to deallocate memory... Done!
... all done!

This is what it print. All of the 2-15 should have names and stats in them, but for some reason it is all 0.

Here is my code

BabyNames.h

#ifndef BABYNAMES_H_
#define BABYNAMES_H_
#include <string>
#include <fstream>
using namespace std;


/**
 * gender: an enum to hold types boy and girl
 */
enum gender {boy, girl};

/**
 * PeopleStats: a data struct to hold year, name, double, and the enum type
 * gender
 */
struct PeopleStats {
    short year;
    string name;
    double percent;
    gender sex;
};

/**
 * Names: A class that reads data from a file into a PeopleStats Array
 * and is capable of sorting them by name and by popularity percentage
 */
class BabyNames {

public:

    BabyNames(const BabyNames& bn);
    BabyNames( const int numLines);
    ~BabyNames();
    const gender parseSex(string s);
    void swap(int i);
    const int getCapacity();//getter for dataSize
    const PeopleStats& get(int i) const; //getter for objects of the data array
    void sortByName();      //Sorts the names alphabetically
    void sortByPopularity();//Sorts the names by popularity
    void sortByYear();
    void addArrayFillCount();
    friend std::ostream& operator << (std::ostream& os, const PeopleStats& d);
    friend std::ostream& operator << (std::ostream& os, const BabyNames& bn);
    //friend std::istream& operator >> (std::istream& in, const PeopleStats& ac);
    friend std::istream& operator >> (std::istream& in, const BabyNames& ac);
private:

    PeopleStats* people;
    int capacity;
    int arrayFillCount; // to keep track of how many array locations have data objects in them
    static const int OUT_OF_BOUNDS = -1;

};//end of class


#endif  /* BABYNAMES_H */

BabyNames.cpp

#include <iostream>
#include <string>
#include <fstream>
using namespace std;
#include "BabyNames.h"




/**
 * BabyNames: A class that reads data from a file into a PeopleStats Array
 * and is capable of sorting them by name and by popularity percentage
 */


BabyNames::BabyNames(const int numberOfLines) {
    people = new PeopleStats[numberOfLines];
    capacity = numberOfLines;
    arrayFillCount = 0;

    for (int i=0 ; i<capacity; i++){
        people[i].year = 0;
        people[i].name = "";
        people[i].percent = 0;
        people[i].sex = boy;
    }
}

//Copy Constructor
BabyNames::BabyNames(const BabyNames& bn){
    capacity = bn.capacity;
        arrayFillCount = bn.arrayFillCount;
        people = new PeopleStats[ bn.capacity ];
    for (int i=0; i< bn.capacity ;i++)
        people[i] = bn.people[i];
}

BabyNames::~BabyNames(){
    cout << "Destructor to deallocate memory... Done!" << endl;
    delete[]people;
}

/*
 * sortByName - Sorts the entire array of people by name using the bubble
 * sort algorithm. Array is sorted according to name, within the structure
 * Algorithm becomes extremely slow if capacity > 3000
 */
void BabyNames::sortByName(){
    //sorted is set to true if no changes were made
    bool sorted = false;
    //change tells the loop if we made a swap or not
    bool change = false;
    while (!sorted) {
        for (int i = 0; i < capacity - 1; i++) {
            int compare = people[i].name.compare(people[i + 1].name);
            if (compare == 1) {
                swap(i);
                change = true;
            }
        }
        //if the array was not changed,
        //changed sorted to true and exit loop
        if (change == false)
            sorted = true;
        //otherwise reset change and repeat the loop
        else
            change = false;
    }
}

/**
 * sortByPopularity - sorts the entire array using the bubble sort algorithm
 * Method is almost exactly the same as sortByName, except the compare
 * variable is a double consisting of the difference of the two popularity
 * percentages.
 * Algorithm becomes extremely slow if capacity > 3000
 */
void BabyNames::sortByPopularity(){
    bool sorted = false;
    bool change = false;
    while (!sorted) {
        for (int i = 0; i < capacity - 1; i++) {
            double compare = people[i].percent - people[i + 1].percent;
            if (compare < 0) {
                swap(i);
                change = true;
                break;
            }
        }
        if (change == false)
            sorted = true;
        change = false;
    }
}

void BabyNames::sortByYear(){
    bool sorted = false;
    bool change = false;
    while (!sorted) {
        for (int i = 0; i < capacity - 1; i++) {
            double compare = people[i].year - people[i + 1].year;
            if (compare < 0) {
                swap(i);
                change = true;
                break;
            }
        }
        if (change == false)
            sorted = true;
        change = false;
    }
}
/**
 * swap - swaps the positions of people[i] and people[i + 1]
 * @param i - index of the people array that will get swapped with i + 1
 */
void BabyNames::swap(int i) {
    PeopleStats temp = people[i + 1];
    people[i + 1] = people[i];
    people[i] = temp;
}

/**
 * getCapacity: returns the number of data entries stored.
 * @return size of the data
 */
const int BabyNames::getCapacity(){
    return capacity;
}

/**
 * get: returns one PeopleStat Object
 * @param i
 * @require: i < capacity
 * @return PeopleStat object
 */
const PeopleStats& BabyNames::get(int i) const {
    if (i>=0 && i < capacity)
        return people[i];
    throw OUT_OF_BOUNDS;
}
/**
 * << - overloads the outstream operator for PeopleStats object
 * @param os
 * @param d
 * @return os : output stream
 */
std::ostream & operator << (std::ostream& os, const PeopleStats& d){
    os << d.name << " " << d.year << " " << d.percent << " " << d.sex;
    return os;
}

/**
 * <<: overloads the outstream operator for the BabyNames object
 * @param os
 * @param bn
 * @return
 */
std::ostream& operator << (std::ostream& os, const BabyNames& bn) {
    os << "  BabyNames object " << std::endl;
    for (int i=0; i < bn.capacity; i++ )
        os << "    " << (i+1) <<":  " << bn.get( i ) << std::endl;
    return os;
}//end of operator

/*std::istream& operator >> (std::istream& in, const PeopleStats& ac){
    in>>ac.year>>ac.name>>ac.percent>>ac.sex;
    //struct doesnt need a loop in the operator
    return in;
}*/

std::istream& operator >> (std::istream& in, const BabyNames& ac){

    short tempYear;
    string tempName;
    double tempPercent;
    string  tempSex;
    int arrayLocation = ac.arrayFillCount;
    in >> tempYear;
    in >> tempName;
    in >> tempPercent;
    in >> tempSex;
    //gender tempGender = parseSex(tempSex);
    ac.people[ arrayLocation ].year = tempYear;
    ac.people[ arrayLocation ].name = tempName;
    ac.people[ arrayLocation ].percent = tempPercent;

    if( tempSex.compare( "boy" ) == 0 )
        ac.people[ arrayLocation ].sex = boy;
    else if ( tempSex.compare( "girl" ) == 0 )
        ac.people[ arrayLocation ].sex = girl;
    else
        throw "invalid Gender";
    //addArrayFillCount();

    return in;
}
//Baby names extraction operator does need a loop

void BabyNames::addArrayFillCount(){
    arrayFillCount++;
}

Main

#include <iostream>
#include "BabyNames.h"



/**
 * main: The client function that controls the server, BabyNames
 * For reasons currently unknown, the program will take forever
 * to run after the  * 3000-5000 line mark.
 * @return 0 if successful
 */

int checkLines(string fn){
    int numberOfLines = 0;
    string temp;
    ifstream myfile( fn.c_str(), ios::in );
    while( getline( myfile, temp ) )
        numberOfLines++;
    std::cout << "Number of lines in text file: " << numberOfLines;
    return 15;
}//make a stand alone function

int main(void) {



    cout << "Baby names: " << endl;

    const char filename[] = "src/people.txt";
    cout << " 1. Reading file: \"" << filename << "\" ... ";
    int numberOfNames = checkLines(filename);
    cout << " number of lines in file is: " << numberOfNames;
    BabyNames* names = new BabyNames( numberOfNames );

    // read the contents of a file into names and print them
    ifstream myFile( filename, ios::in );
    //myfile.open(fn);
    myFile >> *names;
    cout << " file has been read!" << endl;

    // Sort and print
    cout << " 2. Sorted by popularity:" << endl;
    BabyNames* namesByPop = new BabyNames( *names );
    namesByPop->sortByPopularity();
    cout << *namesByPop;

    // Sort and print
    cout << " 3. Sorted by name:" << endl;
    BabyNames* namesByName = new BabyNames( *names );
    namesByName->sortByName();
    cout << *namesByName;

    // Sort and print
    cout << " 4. Sorted by year:" << endl;
    BabyNames* namesByYear = new BabyNames( *names );
    namesByYear->sortByYear();
    cout << *namesByYear;

    cout << " 5. Original names:" << endl;
    cout << *names;

    delete names;
    delete namesByYear;
    delete namesByName;
    delete namesByPop;



    cout << "... all done!" << endl;
}

The text file looks like this but there are 250000+ lines

1880 Henry 0.020641 boy
1880 Robert 0.020404 boy
1880 Edward 0.019965 boy
1880 Harry 0.018175 boy
1880 Walter 0.014822 boy
1880 Arthur 0.013504 boy
1880 Fred 0.013251 boy
1880 Albert 0.012609 boy

How do I get arrayFillCount to go up in the >> operator?

Upvotes: 1

Views: 134

Answers (1)

Shoe
Shoe

Reputation: 76300

On myFile >> *names; you are calling std::istream& operator >> (std::istream&, const BabyNames&) which will execute the following code:

[...] // var declarations

in >> tempYear;
in >> tempName;
in >> tempPercent;
in >> tempSex;

ac.people[ arrayLocation ].year = tempYear;
ac.people[ arrayLocation ].name = tempName;
ac.people[ arrayLocation ].percent = tempPercent;

[...] // other checks and return

which will correctly read only the first line of the file and populate only the first of people inside the BabyNames object (the first time arrayLocation = 0).

You should execute myFile >> *names; for the number of lines you want to populate *names with.


I need to get arrayFillCount to go up with my >> operator. How do I do this?

You should just add arrayFillCount++; right after you fill ac.people[ arrayLocation ] data.

Upvotes: 1

Related Questions