2013-03-23 2 views
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.

Вот мой код

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

Главная

#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 идти вверх в >> оператора?

+0

Для начала вы не выполнили правильное правило правильно. Вам нужно предоставить оператор присваивания копий ('=') –

+0

@ Хорошая тема, хорошая подсказка – 4pie0

+0

Можете ли вы разместить файл '.txt'? – Shoe

ответ

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

+0

Получаю и ошибаюсь, когда добавляю FillCount(); после этого line. Функция 'addArrayFillCount' не может быть разрешена – Freiermuth

+0

@Shigga, см. Редактирование. – Shoe

+0

Я пробовал ac.arrayFillCount ++; arrayFillCount ++; addArrayFillCount(); Ничего из них не работает Приращение элемента 'BabyNames :: arrayFillCount' в объекте только для чтения – Freiermuth

Смежные вопросы