2013-03-21 4 views
2

Итак, вот что мне еще нужно делать. У меня серьезные проблемы с синтаксисом. Я не знаю, почему я получаю сообщение об ошибке, когда пытаюсь объявить динамически выделенный массив. Было бы здорово, если бы я мог помочь в этом.Динамические массивы, деструктор, требуется глубокая копировальная помощь

BabyNames класс:

  1. должны иметь в качестве членов данных:
    • динамически выделяется массив объектов данных
    • член данных INT, который представляет емкость массива
    • ИНТ данных чтобы отслеживать, сколько мест массива имеют объекты данных в них.
  2. Помимо одного или нескольких «обычных» конструкторов, также реализуйте i. конструктор копирования, который выполняет «глубокую» копию, - используйте это, чтобы сделать копии. ii. перегруженный оператор присваивания iii. виртуальный деструктор для освобождения любой памяти, выделенной любым из конструкторов.
  3. Перегрузка вставки (<<) и извлечение (>>) операторов.

Вот заголовок

 /* 
* File: BabyNames.h 
* Author: jack 
* 
* Created on March 18, 2013, 3:35 PM 
*/ 

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

/** 
* 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(); 
    BabyNames(const char fn[], const int numLines); 
    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 
    friend std::ostream& operator<<(std::ostream& os, const BabyNames& bn); 
    //friend std::PeopleStats& operator =(const PeopleStats& rhs); 

private: 
    static const int MAX_DATA_SIZE = 25000; 
    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 */ 

Вот функции

/** 
* PeopleSort.cpp 
* Description: 
* This class stores the information in data structure and includes methods that 
* sort the data by name and by popularity. 
* Created: 
* Feb 27, 2013 
* Modified: 
* March 1st 2013 
*/ 

#include <iostream> 
#include <string> 
#include <fstream> 
using namespace std; 
using std::ifstream; 
#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 PeoplStats[MAX_DATA_SIZE]; //edit I put this in but I still get errors 
    //set current capacity 
    capacity = numLines; 
    //Open File 
    ifstream myfile; 
    myfile.open(fn); 
    //read in data 
    int current = 0; 
    while (current < capacity) { 
     myfile >> people[current].year; 
     myfile >> people[current].name; 
     myfile >> people[current].percent; 
     string sex; 
     myfile >> sex; 
     people[current].sex = parseSex(sex); 
     current++; 
    } 

} 

BabyNames::~BabyNames(){ 
    cout << "Deconstructor" << endl; 
    delete[]people; //Edit: I added this 
} 

/* 
* 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; 
    } 
} 

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

Вот главная

/*Title: CS 237 Assignment#1 

* Created: 
* Feb 27, 2013 
* Modified: 
* March 1st 2013 
********************************/ 

#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", 5000); 
    cout << names; 
    cout << "Sorted by popularity" << endl; 
    names.sortByPopularity(); 
    cout << names; 
// cout << "Sorted by name" << endl; 
// names.sortByName(); 
// cout << names; 
    cout << "... done!" << endl; 
    return 0; 


//This is a suggested Main by my professor 
/* cout << "People 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: " << number_of_names; 
    BabyNames* names = new BabyNames(number_of_names); 

    // 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; 

} 

Кроме того, файл, который я читаю очень много линий, которые выглядят следующим образом:

1880 John 0.081541 boy 
1880 William 0.080511 boy 
1880 James 0.050057 boy 
1880 Charles 0.045167 boy 
+1

Каков ваш вопрос? – Nick

+0

Как бы я добавил некоторые из вещей, которые я перечислял вверху? – Freiermuth

+1

Несколько советов: 1) Вы не определили свой деструктор в своем заголовочном файле. 2) не помещайте 'use namespace' в свой файл заголовка, поместите его в свой файл' .cpp'. 3) Если вы уже указываете 'using namespace std;', то 'using std :: ifstream'' бессмысленно. 4) Почему бы не использовать «список» или «вектор»? – Nima

ответ

1

Не думаю, что я вижу, где вы на самом деле выделяете память в своем конструкторе.

BabyNames::BabyNames(const char fn[], const int numLines) { 
    people = new PeopleStats[numLines]; 
    // check for null 
    ..... 
} 

Кроме того, освободить память в вашем деструкторе:

BabyNames::~BabyNames() { 
    delete [] people; 
} 
+0

Спасибо, это действительно помогает, хотя я все еще получаю ошибки, когда у меня есть люди = новые PeopleStats [numLines]; в конструкторе. Несколько маркеров в этой строке - тип «PeoplStats» не может быть разрешен - ожидаемый тип-спецификатор до «PeoplStats» - ожидается «;» перед «PeoplStats» - не может преобразовать «int *» в «PeopleStats *» при назначении – Freiermuth

+0

У вас есть Опечатка: «PeoplStats» (отсутствует «e»). –

0

Я предполагаю, что у вас возникли проблемы с помощью следующей строки в заголовке:

PeopleStats* people = new PeopleStats[MAX_DATA_SIZE]; 

Вы не можете динамически выделять память в заголовке. Вот почему он не будет компилироваться. Вам придется динамически распределять память в файле cpp. Вам просто нужно объявить указатель в заголовке (как вы уже сделали). Затем в конструкторе для класса выделите память, прежде чем пытаться получить к ней доступ.

Заголовок:

class BabyNames { 
public: 
    BabyNames(const char fn[], const int numLines); 
    ~BabyNames(); 

private: 
    PeopleStats* people; 
}; 

CPP файл:

BabyNames::BabyNames(const char fn[], const int numLines) { 
    // dynamicall allocate array 
    people = new PeopleStats[numLines]; 

    // fill in people array here 
} 

~BabyNames::BabyNames { 
    // don't forget to free array or you will have a memory leak 
    delete [] people; 
} 
+0

Спасибо, это действительно помогает, хотя я все еще получаю ошибки, когда у меня есть люди = новые PeopleStats [numLines]; в конструкторе. Множественные маркеры на этой линии - типа «PeoplStats» не может быть решен - ожидаемый тип спецификатор до того «PeoplStats» - ожидается «;» перед «PeoplStats» - не может преобразовать «Int *» до 'PeopleStats * в задании – Freiermuth

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