2013-03-22 56 views
0

我對這個程序有一些疑問。我先解釋一下它的快速行動。它的名稱和統計數據讀取,看起來像這樣的文件:範圍,操作員,功能錯誤幫助需要

1880 John 0.081541 boy 
1880 William 0.080511 boy 
1880 James 0.050057 boy 
1880 Charles 0.045167 boy 
1904 Zola 0.000157 girl 
1904 Juana 0.000154 girl 
1904 Ramona 0.000154 girl 
1904 Carmella 0.00015 girl 

我讀它並存儲在一個動態數組,並能夠與方法來組織。我的問題是: 1)我的提取操作符有什麼問題?爲什麼不能看到人民陣列?我應該在那裏打開文件嗎? 2)爲什麼我的主要看不到checkLines函數?我不認爲它應該是一個成員函數,我認爲它應該是獨立的。 3)我的拷貝構造函數有什麼問題?有一條黃線,而不是一個紅一個錯誤是:

Multiple markers at this line 
    - Member 'capacity' was not initialized in this 
    constructor 
    - Member 'people' was not initialized in this 
    constructor 
    - Member 'fillCount' was not initialized in this 
    constructor 

下面是代碼

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: 
    int checklines(const char fn[]); 
    BabyNames(BabyNames& people); 
    BabyNames(const char fn[], const int numLines); 
    ~BabyNames(); 
    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(); 
    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, PeopleStats& ac); 
    friend std::istream& operator >> (std::istream& in, BabyNames& ac); 
    //int filled; //keeps track of how many array locations have data objects 

private: 
    static const int MAX_DATA_SIZE = 2000; 
    PeopleStats* people; 


    int capacity; 
    int fillCount; // 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 char fn[], const int numLines) { 
    people = new PeopleStats[numLines]; 
    capacity = numLines; //set current capacity 
    ifstream myfile;  //Open File 
    myfile.open(fn);  //read in data 
    int filled = 0; 
    while (filled < capacity) { 
     myfile >> people[filled].year; 
     myfile >> people[filled].name; 
     myfile >> people[filled].percent; 
     string sex; 
     myfile >> sex; 
     people[filled].sex = parseSex(sex); 
     filled++; 
    } 

} 

//Copy Constructor 
BabyNames::BabyNames(BabyNames& people){ 
    PeopleStats* copyPeople = new PeopleStats[]; 
    for (int i=0; i<500 ;i++) 
     copyPeople[i] = people[i]; 
} 

PeopleStats& operator =(const PeopleStats& people){ 
    PeopleStats x = new PeopleStats[2000]; 
    for (int i=0; i<2000 ;i++) 
     x[i] = people[i]; 
    return *this; 
}//make a member with one parameter 


std::istream& operator >> (std::istream& in, PeopleStats& ac){ 
string str; 
ifstream myfile;  //Open File 
    myfile.open(fn);  //read in data 
    int filled = 0; 
myfile >> people[filled].year; 
     myfile >> people[filled].name; 
     myfile >> people[filled].percent; 
     string sex; 
     myfile >> sex; 
     people[filled].sex = parseSex(sex); 
     filled++; 
     } 
    }//struct doesnt need a loop in the operator 
    return in; 
} 

std::istream& operator >> (std::istream& in, BabyNames& ac){ 
string str; 

    while (in >> str){ 
     string strInput; 
     getline(inf, strInput); 
     in >> strInput; 

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

int checkLines(const char fn[]){ 
    int number_of_lines = 0; 
    std::string line; 
    ifstream myfile("textexample.txt"); 
    while (std::getline(myfile, line)) 
     ++number_of_lines; 
    std::cout << "Number of lines in text file: " << number_of_lines; 
    return number_of_lines; 
}//make a stand alone function 



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; 
} 
/**  string strInput; 
     getline(inf, strInput); 
     in >> strInput; 
* parseSex: extracts the gender from the input and returns the appropriate enum 
* @param s 
* @return gender object 
*/ 
gender BabyNames::parseSex(string s) { 
    if (s == "boy") 
     return boy; 
    else if (s == "girl") 
     return girl; 
    else 
     throw "invalid Gender"; 
} 

/** 
* 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 < 2000; i++) 
     os << " " << (i+1) <<": " << bn.get(i) << std::endl; 
    return os; 
}//end of operator 

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 main(void) { 
/* cout << "People names: " << endl; 
    BabyNames names("src/people.txt", 2000); 
    cout << names; 

    cout << "Sorted by popularity" << endl; 
    names.sortByPopularity(); 
    cout << names; 
// cout << "Sorted by name" << endl; 
// names.sortByName(); 
// cout << names; 
     cout << "Sorted by year" << endl; 
     names.sortByYear(); 
     cout << names; 
    cout << "... done!" << endl; 
    return 0;*/ 

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

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

    // read the contents of a file into names and print them 
    ifstream file(filename, ios::in); 
    file >> *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; 
} 

回答

2

1)因爲您的提取操作符不是該類的成員。你需要ac.people。你應該defintely不要在你的提取操作符中打開一個文件,打開的文件(或其他)通過參數in傳入。 2)因爲你還沒有告訴過它(即你沒有將它定義在main可以看到的任何地方)。也許最簡單的方法是在BabyNames.h的底部附近添加int checkLines(const char fn[]);

3)你的拷貝構造函數一切都是錯誤的。一方面,它不會初始化你正在構建的對象,而只是創建一個名爲copyPeople的數組,然後被丟棄,你構建的對象完全沒有被觸摸。另一個問題是該參數應宣佈爲const。像這樣的東西會更好

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

您的賦值運算符也是錯誤的,因爲類似的原因。