1

我的程序快完成了,但是输出没有得到正确的数字。

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!

这就是它打印的内容。所有的 2-15 都应该有名字和统计数据,但由于某种原因,它都是 0。

这是我的代码

宝贝名字.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 */

宝贝名字.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++;
}

主要的

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

文本文件看起来像这样,但有 250000+ 行

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

如何让 arrayFillCount 在 >> 运算符中上升?

4

1 回答 1

1

myFile >> *names;您调用std::istream& operator >> (std::istream&, const BabyNames&)时,它将执行以下代码:

[...] // 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

这将仅正确读取文件的第一行并仅填充对象people内部的第一行BabyNames(第一次arrayLocation= 0)。

您应该执行myFile >> *names;要填充的行数*names


我需要让 arrayFillCount 与我的 >> 运算符一起使用。我该怎么做呢?

您应该arrayFillCount++;在填写ac.people[ arrayLocation ]数据后立即添加。

于 2013-03-23T05:43:22.977 回答