hey All.

I am currently working on a project to create a basic student registration system using classes and other sorts of stuff later on...

as of now, i am to create three classes as follows:

Person, Student, and courseInfo.

I have to create a simple driver program that allows the user to enter some basic information regarding a student. Such as first/last name, SSN, DOB, and more. After entering this data i need to be able to enter data such as course for this person, such as classID, semester, year, grade. So its pretty simple. I would like to create a menu system once i have the skeleton working...(something like:)
1. enter new student.
2. edit existing student.
3. edit course data for student (search via ID).
etc

As for now, my basic skeleton code looks like this:

//THIS SHOULD CONTAIN THE CLASS DEFINITION
#include "main.h"

#include <iostream>
#include <vector>
#include <string>

using namespace std;

class Person {
	public:
      Person(){};
      virtual ~Person(){};
      void infoPrint(string); //NEEDS FUNCTION DEFINITION
      void setFirstName(string x){firstName = x;}
      string getFirstName() const {return firstName;}
      void setLastName(string x) {lastName = x;}
      string getLastName() const {return lastName;}
      void setSSN(string x) {SSN = x;}
      string setSSN() const {return SSN;}
      void setDOB(string x) {DOB = x;}
      string getDOB() const {return DOB;}
      void setGender(string x) {gender = x;}
      string getGender() const {return gender;}
    private:
      string firstName;
      string lastName;
      string SSN;
      string DOB;
      string gender;
};

class Student : public Person {
	public:
      Student(){ZID = ""; };
      virtual ~Student(){ZID = "";};
    private:
      string ZID;
      typedef vector<string> courseInfoVec;
};

class CourseInfo {
	public:
      CourseInfo();
      virtual ~CourseInfo();
    private:
      string courseID;
      string yearTaken;
      string semesterTaken;
      string grade;
};

My little driver program contains:

#include "main.cpp"

int main()
{
	Student NIU_Student;
	string x;
	cout << "Please enter the first name: ";
	cin >> x;
	NIU_Student.setFirstName(x);
	cout << "Please enter the last name: ";
	cin >> x;
	NIU_Student.setLastName(x);
	cout << "Please enter students social security number: ";
	cin >> x;
	NIU_Student.setSSN(x);
	cout << "Please enter student DoB: ";
	cin >> x;
	NIU_Student.setDOB(x);
	cout << "Please enter the student's gender: ";
	cin >> x; 
	NIU_Student.setGender(x);
    return 0;
}

But i currently get this error message:

[Linker error] undefined reference to `Student::Student()'
[Linker error] undefined reference to `Student::~Student()'
[Linker error] undefined reference to `Student::~Student()'
ld returned 1 exit status

My assumption is that is because i have not defined the constructor or the destructor correctly. But... i am unsure what i should have in each of those, as the strings i define don't need to be created before hand, the only thing i can think of is the space needed for the data... so i would have do something like:

vector<string> studentX = new vector<string>(firstName,lastName,...,....,.....);

is this somewhat correct in my logic? Please explain if otherwise?

thank you all

Recommended Answers

All 21 Replies

are you 'including' the class declarations in main.cpp ???

Yes, my 'drivers program', the one with the cout/cin statements #includes my main.cpp file which contains the three class declarations...

Is that the answer you needed? If i understood you correctly it should be!

Thanks

first of all the naming convention is very inappropriate. Main.cpp should not be the file containing the class info rather it should be the file which contains 'int main'. The class definitions and declarations should be placed in separate files with proper names like 'class.h' and 'class.cpp' with include guards placed in the .h file. Then you should include the .h file of whichever class you need in the main.cpp.

Going forward when your project becomes bigger, it will be much easier to maintain it if you follow these rules.

That is completely understood, and i was going to do just that tomorrow, i was planning on doing each class declaration in its own .h file with the actual methods etc placed in a corresonding .cpp file. Such as Person.cpp and Person.h etc... with my main.cpp or in my case, drive.cpp with my int main...

This was something i had quickly put together and tried to get working in bulk, then was going to seperate after i got the initial part working - as i sometimes have problems with including the incorrect files, or including multiple times, this would have solved that initially, but yes, i will repost updated and seperated files tomorrow... i hope that helps, in the mean time, is this error because of the above problem or due to something else entirely?

Thanks for your input so far, i hope you can continue to help me.

i feel when you do that this error should go, basically I couldn't go beyond because i could never make out which of your files is main.cpp and what is main.h and the includes were equally confusing, so that should be the first step. For dealing with multiple includes use the include header guards.

I have updated my program and switched code into different .h and .cpp files.

I will upload the individual files... i have an error when trying to compile the project, i get the following:

1 C:\Users\Tony\Documents\Spring 2009\CSCI 340\Project1\Student.cpp In file included from Student.cpp
18 C:\Users\Tony\Documents\Spring 2009\CSCI 340\Project1\Student.h expected class-name before '{' token
C:\Users\Tony\Documents\Spring 2009\CSCI 340\Project1\Makefile.win [Build Error] [Student.o] Error 1

If someone could do me the huge favor or attempting to run/compile this program, i would be greatly appreciative.

Any questions/comments/concerns, please post and ill get back to you asap. In the meantime, i will continue to work on the project and update you all with a any progress in dealing with errors etc.

Thanks again!

PS - If you are downloading the code, there should be 7 files.
1 driver,
3 header files with 3 corresponding .cpp files.

It all worked for me, after adding #include "person.h" to the student.h file.

Using Visual C++ 2008

Same result here.

You need #include "person.h" in student.h because Student derives from Person.

Awesome, i have now got it working. I assumed that was what i had to do, using dev c++ can be fusy and it just didn't save the change correctly when i had tried it..but it works now!

My next question is this:

Lets say i have student FRED. He wants to add 2 classes to his list of courses.

THis line of code within my student.h:

typedef vector<string> courseInfo;

Creates a vector of strings correct? Now, if i wanted to add a course with this info:

MATH101 FALL 2008 A
(Decription of course, semester, year, grade)

How could this be inserted into the vector (or if need be, an array)... with each data unit in the same 'slot' of the vector.

So i could access the data later by something like:

CourseInfo[1].descript, etc etc.

And is there a way to tie the courseInfo vector/array to the courseInfo class - so i can use those variables etc.

Thank you for the help once more.

You don't want a vector of strings, you need a vector of CourseInfo's, like

class Student : public Person {
	public:
      Student();
      virtual ~Student();
    private:
      string ZID;
      vector<CourseInfo> courses;
};

Since you have the courses as private, you'll need student methods for accessing and modifying the course data.

Also need a #include "courseInfo.h" in the student.h file

Thank you once again for your help - that makes sense now.

I have tried numberous ways in which to add new course informtion for my student, FRED. Here is what i have tried.

courses[1].courseID = entry;
NIU_Student.courses[1].courseID = entry;
etc
etc

And i just cant seem to access the data in the way i think i should or want to be able to.

Having this new vector of courseInfo is useful, because that sets up something that could look like:
courses[1].courseID is MATH301
courses[1].yearTaken is 2008
courses[1].semesterTaken Fall
courses[1].grade is A
courses[2].courseID is MATH999
courses[2].yearTaken is 2010
courses[2].semesterTaken Summer
courses[2].grade is F

Am i correct in thinking this is what should be feasible using a vector or my courseInfo?

Is i am correct, how would i then create an object to insert into the vector at position 1.... say i have my student fred who input class information...how can i have this new course information CONNECTED with fred... ? Can i?

Sorry for all the questions, but i understand what i need to have, and i know parts of the puzzle, putting them together is the hardest part!

Thansk again

new driver.cpp file... you can see what i am trying to do in more detail from this... all other files are the same (minus small edit with header file)

//THIS IS THE 'driver' PROGRAM
#include "Person.h"
#include "Student.h"
#include "courseInfo.h"
#include "340.h"

int main()
{
   int choice = 0;
   while (choice != 999)
   {
         cout << "Student Registration Database" << endl;
         cout << "Please choose from the options below (type 999 to quit)\n" << endl;
         cout << "1. Enter new student information" << endl;
         cout << "2. Enter new class information for student" << endl;
         cout << "3. Edit student information" << endl;
         cout << "4. Edit class information for student\n" << endl;
         cout << "Please enter your choice: (the press enter, 999 to quit)";
         cin >> choice;
   switch(choice)
   {
   case 1:
        {
        Student NIU_Student;
	     string x;
	     cout << "Please enter the first name: ";
	     cin >> x;
	     NIU_Student.setFirstName(x);
	     /*cout << "Please enter the last name: ";
	     cin >> x;
	     NIU_Student.setLastName(x);
	     cout << "Please enter students social security number: ";
	     cin >> x;
	     NIU_Student.setSSN(x);
	     cout << "Please enter student DoB: ";
	     cin >> x;
	     NIU_Student.setDOB(x);
	     cout << "Please enter the student's gender: ";
	     cin >> x; 
	      NIU_Student.setGender(x);
         */
         cout << NIU_Student.getFirstName() << endl;
         break;
         }
    case 2:
         {
         string entry;
         CourseInfo classes;
         cout << "Choice entered was 2" << endl;
         cout << "Please enter course name: ";
         cin >> entry;
         classes.courseID = entry;
         break;
         }
    case 3:
         {
         cout << "Choice entered was 3" << endl;
         break;
         }
    case 4:
         {
         cout << "Choice entered was 4" << endl;
         break;
         }
    case 999:
         {
         cout << "Quitting..." << endl;
         break;
         }
    default:
         {
         cout << "Incorrect option selected, please try again: " << endl;
         cin >> choice;
         }
    } // end of switch statement
    } // end of while
    system("PAUSE");
    return 0;
}

Short answer:
In student class, in your application, create an instance of courseinfo, fill it in, then pass that to a method in student that will push it onto the vector.

To access the course info elements directly, as you show above, you'd have to put the courseInfo vector in the public section of studentInfo. You probably shouldn't do that, just create access methods in the studentInfo class.

Short answer:
...then pass that to a method in student that will push it onto the vector.

To do this i would have something like:
*In driver.cpp*

insertToVec(classes);

*in Student.cpp*

void insertTovec(obj)
{
    courses.insert(obj);
}

Would that make me able to do something like:

cout << courses[1].grade;

Or am i completely off base?

I recently found out that later in th eproject i will be changing my course list data from arrays (or in my case, vector) to a linked list.

Now i am going to switch from my use of vector to an array based system... so instead i did this:

CourseInfo courses[10];

That is in my Student.h file... now, in my driver.cpp file, when i get data for a course, such as courseID, how can i access this data segment?

...case 2:
         {
         string entry;
        [B] CourseInfo classes;[/B]
         cout << "Please enter course name: ";
         cin >> entry;
          classes[0].setCourseID(entry);;
         cout << "Please enter year taken: ";
         cin >> entry;
         classes[0].setYearTaken(entry);
//...year taken, grade etc etc after this       
         break;
         }

Because i would like access to the first object in the array, so array[0]... and with that i should be able to access the data members, year, grade, classID, semester etc... so i can change them all...right? Wrong?

Why did you declare 'CourseInfo classes' inside this case?

If this case is inside a method of Student it can see classes directly.
If this case is not in a method of Student you need to decide how you are going to get the data there.

Presuming that CourseInfo has the mutators you're calling, and if you removed all of the [0] references on classes (because the one you declared in the case is not an array) the input should work to fill the local 'classes'. But then you need to have that update one of the elements in the Student's classes array.

I have modified my student.h file so that i am using an array of objects of the class CourseInfo... so now i should be able to use subscripts like i attempted before.

Here is my code:

class Student : public Person {
	public:
      Student();
      virtual ~Student();      

    private:
      string ZID;
      CourseInfo courses[10]; 
    
};

See how im declaring an array of objects (i am doing that right? ha?!). So within my driver.cpp program i try this:

cout << "Please enter course name: ";
         cin >> courses[0].courseID;

Would this be correct or am i completely wrong with this aswell?! I have an old worksheet that i had used an array of employee objects, so that i could access things such as employee[0].name, employee[0].SNN, employee[0].salary, etc... so i was hoping i could do the same with this course info section!

Please keep up the good comments! THanks a ton for all the help!

courses is a member of student.

To what student is cin referring when you want to update courses[0]?

(and courses is PRIVATE data, driver will not be able to update it)

If i move the CourseInfo courses[10]; into the public section my class definition that will temporarily get rid of any data ccess issues...

The definition there is creating a array of objects of the CourseInfo class... which looks like:

class CourseInfo {
	public:
      CourseInfo();
      virtual ~CourseInfo();
      void setCourseID(const string &x);
      string getCourseID() const;
      void setYearTaken(const string &x);
      string getYearTaken() const;
      void setSemesterTaken(const string &x);
      string getSemesterTaken() const;
      void setGrade(const string &x);
      string getGrade() const;

    private:
      string courseID;
      string yearTaken;
      string semesterTaken;
      string grade;
};

But after putting that up - i just noticed i would still have an issue with accessing the data within course info, as that is all private, althought i do have accessor methods...

Do you see what i am trying to do here now? Make a little more sense? Or am i just trying to do something that is weird, stupid and not possible?

Latest update on my program - i will upload the files and hope someone can see what is going on with it. I thought i had it working and had the right idea, but for some reason the program crashes when trying to try option 5 (print the data).

i hope someone has some ideas with this, as i am now compeltely baffled as to why it wont work, or at least some data - it used to until i changed the thing to NIU_Student.courses[0].get*****() etc.

Thank you in advance for your time and effort in helping me!

In my first test, it blew up trying to output grades when I had not entered any. (Maybe you should have a count for the number of grades that have been entered.)

Looking at the code for the grades:

while (count <= 10)
         {
         cout << endl << NIU_Student.courses[count].getCourseID() << " " 
              << NIU_Student.courses[count].getYearTaken() << " " 
              << NIU_Student.courses[count].getSemesterTaken() << " " 
              << NIU_Student.courses[count].getGrade() << endl;
         count++;
         }

You will index count from 0 to 10, and the 10 value is outside the range of the array.

I'm not sure why this isn't a for loop, but changing your while condition to while (count < 10) should make it feel better.

Classic error - you really should be past this by now! ;)

int count = 0;
         while (count <= 10)
         {
         cout << endl << NIU_Student.courses[count].getCourseID() << " " 
              << NIU_Student.courses[count].getYearTaken() << " " 
              << NIU_Student.courses[count].getSemesterTaken() << " " 
              << NIU_Student.courses[count].getGrade() << endl;
         count++;
         }

How many times does this loop iterate? How many array elements is it trying to access, compared to the number that really exist?

Array size is 10. Count from 0 up to and including 10 - how many fingers do you need?

Better expression of what you're doing there is a for loop, as in

for( count = 0; count < 10; count++ ) //note the strictly less than 10 test
 // do the work, exactly 10 times

But why print out 10 courses, when the student may not have that many. You keep count of the number of courses entered, that should be stored as part of the studentInfo data, and used to limit how many courses from that 10 element array you actually display. Saves a lot of blank lines.

(Murtan - great minds think alike!)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.