2011-04-26 46 views
0

我正在編寫一個使用OOP存儲學生記錄的程序。目前,我只有兩門課程,一門課程稱爲'課程',一門課程(如果您計算抽象基礎課程的話,還有兩門課程)適用於從「記錄」基礎中獲得的名爲「物理學」的學位課程類型類。存儲從基類類指針向量數組中映射到抽象基類的對象

我在程序中使用了兩張地圖。一個存儲每個單獨記錄的單個課程,並按課程代碼對其進行排序,另一個存儲所有記錄並按ID號對它們進行排序。

我打算在具有用戶輸入的所有學生的信息,包括代碼,在載體中存儲該(命名中的代碼「PREC」),則推壓向量元素到用於存儲所有記錄地圖。代碼遠沒有完成,我只是試圖運行它,看看我是否在正確的軌道上。

的代碼編譯沒有任何錯誤,但是當我嘗試運行它,它用錯誤信息出現:「調試斷言失敗:表達載體標超出範圍」。我覺得這可能是與我使用單獨的矢量元素打電話給我的功能在地圖商店課程的方式,但我不能完全得到它,任何幫助將不勝感激!

這裏是我的文件:

頭文件:

#ifndef MY_CLASS_H // Pre-processor directives to prevent multiple definition 
#define MY_CLASS_h 

#include <iostream> 
#include <string> 
#include <utility> 
#include <map> 
#include <fstream> 




using std::string; 
using std::ostream; 
using std::map; 
using std::cout; 
using std::endl; 
using std::cin; 

namespace student_record // Defines the namespace student_record in which the classes are defined 
{ 
    class Course { /* Create class Course for individual courses, is this better than incorporating 
        all the data separately into the Record class below? Class contains course name, mark achieved and mark weight and course ID */ 
    protected: 
     string course_name; 
     double course_mark; 
     int course_Id; 

    public: 
     Course() {course_name= "Null"; // Default constructor for null course 
        course_mark=0; 
        } 

     Course(string course_namein, double course_markin, int course_Idin) {course_name=course_namein; // Parametrized constructor to create course with set name, mark, weight and course ID 
                            course_mark=course_markin; 

                            course_Id=course_Idin;} 

     ~Course() {course_name.erase(0,course_name.size());} // Destructor to delete the course name 

     // Access functions to get name, mark and weight // 

     double getmark() const {return course_mark;} 
     string getname() const {return course_name;} 
     int getid() const {return course_Id;} 

     friend ostream & operator << (ostream &os, const Course &c);  // Friend function to overload the insertion operator for courses 
    }; 

    class Record 
    { // Create class Record as abstract base class for all inherited degree classes 

    protected: 
     string student_name; 
     int studentid; 
     int years; 

    public: 
     Record() {student_name="Casper"; 
        studentid=0; 
        years=0;}  // Default constructor for class Record, produces empty record 

     Record(string name, int number, int time) {student_name=name; 
                studentid=number; 
                years=time;} // Parametrized constructor for class Record 

     ~Record() {student_name.erase(0, student_name.size());} // Destructor to delete the student name 



     virtual int getid()const=0; 
     virtual int getyears()const=0; 
     virtual void show_record()const=0; 
     virtual void print_record(string *filename)const=0; 
     virtual void degree_class()const=0; 
     virtual void insert_class()=0; 


     /* Virtual functions defined to be used in the derived classes (subjects ie, Physics, stamp collecting, etc...) 
     Thus the base class Record is abstract*/ 
    }; 


    class Physics: public Record 
    { 
    private: 
     string degree_name; 
     typedef map <int, Course> course_map; 
     course_map modules; 


     void searchdatabase (course_map &courses, int coursecode)const; // Uses iterator to search map for corresponding course to inputted key (remember to move to function definitions) 

     string get_name (const int i, course_map &temp) const{ return temp[i].getname();} 
     double get_mark(const int i, course_map &temp)const{ return temp[i].getmark();} // Functions to return the mark, weight and name of a given course corresponding to inputed course code 
     int getid()const{return studentid;} 
     int getyears()const{return years;} 
     void show_record()const; 

     void print_record(string *filename) const; 
     void degree_class()const; 
     void insert_class(); 
     // Function to insert record into map 


    public: 
     Physics():Record(){degree_name= "Physics ";} 
     Physics(string name,int Id, int time):Record(name, Id, time){degree_name= "Physics";} 
     ~Physics() {degree_name.erase(0, degree_name.size());} 


    }; 
} 


#endif 

函數的定義:

#include <iostream> 
#include <string> 
#include <utility> 
#include <map> 
#include <fstream> 
#include <vector> 
#include "Database_header.h" 

using namespace std; 
using namespace student_record; 

ostream & student_record::operator<< (ostream &os, const Course &c) 
{ 
    os<< "Course code" << c.course_Id << " \n Course name: " <<c.course_name << " \n Mark " << c.course_mark <<endl; 
    return os; 
} 

// Function to insert classes // 
void Physics::insert_class() 
{ 

    int courseid; 
    string coursename; 
    double mark; 
    cout << " Enter course code " << endl; 
    cin >> courseid; 
    cout << " \n Enter course name " << endl; 
    cin >> coursename; 
    cout << " \n Enter mark achieved " << endl; 
    cin >> mark; 

    Course temp (coursename, mark, courseid); 

    modules.insert(pair<int, Course>(courseid, temp)); 

} 

void Physics::searchdatabase(course_map &courses, int coursecode) const // Function to search for specific course mark based on course code, need to modify this!!!! 
                     //takes in a map as its argument, although i suppose can use student.modules? 

     { 
      course_map::iterator coursesIter; 
      coursesIter=courses.find(coursecode); 
      if(coursesIter != courses.end()) 
      { 
       cout << " Course Code " << 
       coursecode << " corresponds to " << 
       coursesIter ->second << endl; 
      } 
      else { cout << " Sorry, course not found " << endl; } 
     } 

void Physics::print_record(string *filename) const // Function for printing record to the file 
{ 
    ofstream myoutputfile; 
    myoutputfile.open(*filename,ios::app); 
    if(!myoutputfile.good()) 
     { 
     // Print error message and exit 
     cerr<<"Error: file could not be opened"<<endl; 
     } 

    if(myoutputfile.good()) 
    { 
    myoutputfile << "Student name: " << student_name << endl 
       << "\n Student ID: " << studentid << endl 
       << "\n Year: " << years << endl; 
        course_map::iterator modulesiter; // Iterator to print out courses using overloaded << function (I think?) 
    for(modulesiter==modules.begin();modulesiter!=modules.end();modulesiter++) 
     { 
      myoutputfile<<modulesiter->second << endl; 
     } 
    } 


} 

void Physics::show_record() const // Function for showing specific student record on screen (with iterator for map of courses) 
{ 
    cout << "Student name: " << student_name; 
    cout << "\n Student ID: " << studentid; 
    cout << "\n Years on course: " << years; 
    cout << "\n Courses and grades: "; 
    course_map::iterator modulesiter; // Iterator to print out courses using overloaded << function (I think?) 
    for(modulesiter==modules.begin();modulesiter!=modules.end();modulesiter++) 
     { 
      cout<<modulesiter->second << endl; 
     } 

} 

void Physics::degree_class()const 
{ 
    double temp; 
    vector<double> dynarr; // Create a vector array to store the grades extracted from the course map for each student 
    course_map::iterator modulesiter; 
    for(modulesiter==modules.begin();modulesiter!=modules.end();modulesiter++) // Iterate through map and push values into each vector 
     { 
      Course ghost; 
      ghost=modulesiter->second; 
      dynarr.push_back(ghost.getmark()); 
     } 
    double sum(0); 
    for(int i(0);i<=dynarr.size();i++) 
    { 
     sum+=dynarr[i]; 
    } 

    temp=sum/dynarr.size(); 

    if(temp>=40 && temp <=49.9) 
    { 
     cout << "The student has achieved a 3rd class degree with an average of: \n " 
      << temp; 
    } 

    else if(temp>=50 && temp <=59.9) 
    { 
     cout << "The student has achieved a 2:2 degree with an average of: \n " 
      << temp; 
    } 

    else if(temp>=60 && temp <=69.9) 
    { 
     cout << "The student has achieved a 2:1 degree with an average of: \n " 
      << temp; 
    } 

    else if(temp>=70) 
    { 
     cout << "The student has achieved a 1st class degree with an average of: \n " 
      << temp; 
    } 

    else { cout << "The student has failed the degree " << endl;} 


} 

和主CPP文件:

#include <iostream> 
#include <utility> 
#include <map> 
#include <iomanip> 
#include <vector> 
#include "Database_header.h" 
#include <fstream> 

using namespace std; 
using namespace student_record; 

void main() 
{ 
    // Create map to store students with ID keys // 

    string full_name; 
    int id; 
    int time; 
    string degree_name; 

    vector<Record*> prec; 
    // Vector of base class pointers to store all the different records first. No need to specify length as it is a vector! (Advantage over dynamic array?) 
    char student_test('y'); // Condition for adding students to the record // 
    int q(0); 
    while (student_test=='y' || student_test=='Y') 
    { 
     // Counter for while loop 


     cout<< " \n Please enter the student name " << endl; 
     getline(cin, full_name); 

     // Enter student name, check it is a string? // 

     cout<< "\n Please enter student ID " << endl; 
     cin >> id; 

     // Check if not integer or number, if not need error message // 

     cout << "\n Please enter the number of years on the course " << endl; 
     cin >> time; 

     // Check if not integer or number, if not need error message // 

     cout<< "\n Please enter degree type " << endl; 
     cin>>degree_name; 

     if(degree_name=="Physics" || degree_name=="physics") // create object of appropriate derived class (Physics, Chem, Maths, Bio) 
     { 
      prec.push_back(new Physics(full_name, id, time)); 
     } 

     char class_test('y'); // test condition for class insertion loop 

     while(class_test=='y') // Add courses+marks into course map 
     { 
      cout << " \n Add classes to student record " << endl; 
      prec[q]->insert_class(); 
      cout << " \n Add another class? Y/N" << endl; 
      cin>>class_test; 
     } 

     cout << "Enter another student? Y/N " << endl; 
     cin >> student_test; 

     if(student_test=='N' && student_test=='n') 
     { 
      cout << "\n Thank you for using the student database, Goodbye !" << endl; 
     } 

     q++; // increment counter, to keep track of of vectors of base class pointers, and also be able to output number of students 

    } 

    // Next insert all records into map // 
    typedef map<int, Record*> studentlist; 
    studentlist studentmap; 

    for(int i(0); i<=prec.size(); i++) 
    { 
     studentmap.insert(pair<int, Record*> (prec[i]->getid(), prec[i])); 
    } 

} 

非常感謝!

+1

你應該儘量給的,而不是3個,而大文件的最小工作示例。也許只是這樣做,你會看到你的錯誤。也請給它發生它發生。並感謝@swald的格式化。 – 2011-04-26 13:37:00

+0

您是否嘗試過使用調試器來執行程序?您是否嘗試添加有用的'cout'跟蹤語句來調查發生了什麼? – 2011-04-26 13:43:13

+0

這不可能是功課嗎? – gregg 2011-04-26 13:44:58

回答

3
for(int i(0); i<=prec.size(); i++) 
{ 
    studentmap.insert(pair<int, Record*> (prec[i]->getid(), prec[i])); 
} 

應該是我< prec.size(),而不是< =

+2

是否有「乾草堆裏的針」徽章? – Potatoswatter 2011-04-26 13:45:27

+0

@Patatoswatter,非常正確。順便說一下......我是第一個投票給他:) – iammilind 2011-04-26 13:47:18