Hi all. I am finishing up a project previously posted. I am to create a student 'database' that consist of one student and X number of classes the student has taken. My problem now is that i cannot run a test on the linked list correctly. I am to check to see if a student has taken a certain class, to do this, i do the following in my 'main' program:

Student s1;
....//previous code tests etc
....//insert class, remove class, etc
CourseInfo c3, c4;
string id3;

cout << "Enter the course id to be checked: ";
cin >> id3;
c3.setCourseID(id3);

c4 = s1.checkCourseTaken(s1.getZID(), c3);

cout << endl << "Test 6, check if course was taken:"  << endl;

if(c4.getCourseID() == "")
  cout << endl << "***  COURSE NOT TAKEN  ***" << endl << endl;

else
  cout << endl << "Student took " << c4.getCourseID() << " in the " 
       << c4.getSemesterTaken() << " of " << c4.getYearTaken() 
       << " and earned a grade of " << c4.getGrade() << "." << endl 
       << endl;

Now ... i would post the functions i use, but you would probably need the other parts of code aswell so you can cross reference data members/methods etc. Sooo, i will post ALL my code files along with my 'data' file. Please review the following:

Student:
checkCourseTaken()
SinglyLinkedList:
checkCourseTaken() // calls recursive function
isInList() // has to be recursive

These are the functions used. My idea is that i have to change them a little. First off, i think the Student function needs to return a CourseInfo object (this been the case, i would need a copy constructor for my student class? So that it copies data from one object to another fully?! Also, i would like it if you could review the other 2 functions in SinglyLinkedList for correctness... i am sure they may not make sense, or even correctly function... but i will leave that up for your expert eyes to tell me.

Thanks all in advance,

Recommended Answers

All 12 Replies

Well, I was able to get it to work out, but if you want to mess with those functions, I'm not sure if this will help. You were passing back an empty CourseInfo variable from the SinglyLinkedList function isInList.

You need to set searchCourse = current->info; in the match if statement of isInList, however the const will prevent it. So, you'll need to remove the const from isInList and checkCourseTaken in that same class and it should work out fine.

I have done something similar to what you mentioned and i get something similar to this for my output for this part:

if(c4.getCourseID() == "")
  cout << endl << "***  COURSE NOT TAKEN  ***" << endl << endl;

else
  cout << endl << "Student took " << c4.getCourseID() << " in the " 
       << c4.getSemesterTaken() << " of " << c4.getYearTaken() 
       << " and earned a grade of " << c4.getGrade() << "." << endl 
       << endl;

I get the following:

student took cs111 in the ___ of ___ and earned a grade of ___.

This because i am simply passing back the same courseinfo object that i sent etc.. so is there a way to search through the list, find the course taken, then set the values from the searched and found course object, and set those values to the courseobject i will return to the driver.cpp program. So something like:

courseInfo.setCourseID(current->getCourseID());
courseInfo.setYearTaken(current->getYearTaken());
...
...

Would this work...then i would do:

return courseObject to the main...

Then in main the print will print the correct information.

Is this possible?

The code posted above in my original code works ONLY if you try to 'checkCourseTaken' the first course in the list... try it yourself,....

Check the course you add at the start of the program, then see what you get as a result. Then redo it, and choose the last item in the list printed to check if the student has taken it, you will get a segmentation fault... (or just nothing printed in the sentence).

let me know how it goes for you. ... and if possible a solution to this problem!

Thanks!

Your searching is not actually returning the found object (actually, I don't think it's finding anything, it's hitting on the first node - that's another problem)

To get info back, try these changes:

CourseInfo Student::checkCourseTaken(string ZID, CourseInfo c1)
{
	CourseInfo c2;
	 c2 = courseList.checkCourseTaken(c1)->info;
	return c2;
}


// public non-recursive method
template <class T>
nodeSLL<T> * SinglyLinkedList<T>::checkCourseTaken(const CourseInfo& searchCourse)
{
	head = isInList(searchCourse, head);
	return head;
}
//and change the prototype to match new return value

You need to work on the isInList to actually find the target. What I've given above will be returning a full course record, so you'll see year and grade displayed, although incorrect.

Alright, let me show you what I changed and perhaps that would help. Anything marked in read is something I had to change to get it to run on my computer. I'm running this on Dev-C++ (which shouldn't matter) so you know.

In driver:

#include "Person.cpp"       // was "Person.h"
#include "CourseInfo.cpp"   // was "CourseInfo.h"
#include "Student.cpp"      // was "Student.h"
....
#include <fstream>          // extra <fstream>, removed cause not needed

In SinglyLinkedList.h

class SinglyLinkedList
{
	public:
                ......
		void checkCourseTaken(CourseInfo& searchCourse);
                        // removed const

	private:
                .....
		nodeSLL<T> * isInList(CourseInfo& delCourse, nodeSLL<T>* current);  
                       // removed two consts
};
....
....
....
template <class T>
void SinglyLinkedList<T>::checkCourseTaken(CourseInfo& searchCourse)
                       // removed const
{
	head = isInList(searchCourse, head);
}

template <class T>
nodeSLL<T> * SinglyLinkedList<T>::isInList(CourseInfo& searchCourse, nodeSLL<T>* current)
                       // removed two consts
{
	
  // If at end of list
  if (current == NULL)
      return NULL;
  // Else if matching object found
  else if (searchCourse == current->info)
      {
      nodeSLL<T>* nextNode = current->next;
      searchCourse = current->info;    // added to store values
      return nextNode;
      }
  // Else make recursive call
  else
      {
      current->next = isInList(searchCourse, current->next);
      return current;
      }
}

I ran a few examples but here's three to show it works for the two you supplied and if checking for a new course.

cs111 = http://i21.photobucket.com/albums/b272/DemonGal711/Program%20Pic/DB/two.png
cs222 = http://i21.photobucket.com/albums/b272/DemonGal711/Program%20Pic/DB/one.png
user inputted cs333 = http://i21.photobucket.com/albums/b272/DemonGal711/Program%20Pic/DB/three.png


This is just me, cause I'm obsessed with making programs nearly perfect, but you might want to consider adding a loop to the add, delete, and check test that you have, or asking how many classes they'd like to add/delete/check and then run it that way. I doubt you need it, I'm just someone who would add that so that my users can do everything.

That you for your reply to my questions in great detail. I have the program running exactly how you have it (for the most part)... i did copy / paste your corrections etc. BUT the problem is that the code for the isInList is still very wrong. If you search for teh first course in the list you are given after deleting a class, it looks like the correct information is given back, for example:

cs340 fall 2009 a
cs222 spring 2009 F

you ask to check if cs340 was taken, it will print,

cs340 was taken in the fall of 2009 with a grade of a.

But if you type in cs222, you will STILL get the above printed out, like:

cs340 was taken in the fall of 2009 with a grade of a.

My assumption is that i am returning the same value that was passed into the function, or just the very first node in the list. In the isInList function, i would need to return the actual node when/if found?!

Any ideas? I will try rework this now. And will post with any updates, Thank you once again.

One question before I delve into finding what's wrong with it now, are you storing the information for one student of more then one? I mean, your file only has one student, but are you saving the info for more then one student and checking for these different students?

I just want to make sure before I go write something and realize I'm going overboard.

At the present time, we are only using one student. The file i uploaded is the file i will be working with for the forseeable future. Down the road, i am sure more students will come into play, as for this project, just ONE students class data is to be stored into the linked list.

I hope this helps you clarify things!

Alright, just wanted to make sure. I'm notorious for making my programs harder for myself then I should, so I didn't want to be adding on that when it wasn't required.

Alright, I'm not entirely sure where your problem came from, cause I got something similar but not like that. If I searched for cs340 and then cs222, the first line would read fine but the second line would read cs222 and then the rest of the info from cs340.

Anyway, I believe the reason it is doing that is because you are changing the head of the list every time you search, thus losing the rest of the list and resulting it to spit out the data that is stored in c3 already. How I got rid of that was by making isInList void and removing all the returns. This is what I did to change the code:

template <class T>
void SinglyLinkedList<T>::checkCourseTaken(CourseInfo& searchCourse)
{
	isInList(searchCourse, head);
}

template <class T>
void SinglyLinkedList<T>::isInList(CourseInfo& searchCourse, nodeSLL<T>* current)
{  // If at end of list
  if (current == NULL)  ;
  // Else if matching object found
  else if (searchCourse == current->info)
           { searchCourse = current->info; }
  // Else make recursive call
  else 
      { isInList(searchCourse, current->next); }
}

If you change that, it should be fine.


Now, this is another side note, but you are using a lot of different variables in your driver that really aren't necessary. If it's something you have to do, then I can't really complain, but it seems like an awful lot. You have some 4 CourseInfo variables and 8 strings. I was able to bring it down to 2 CourseInfo variables and 1 string. It really doesn't affect much, but I've gotten yelled at enough for variable usage that I've learned how to make things work with less values.

Anyway, it should be good now, if you have any more issues, feel free to ask.

Thank you for your help with this. My only question/concern involves 2 things. First off, what did you do with the function that is in my Student.cpp file (it is called checkCourseTaken) and returns a CourseInfo object. I curerntly have:

CourseInfo Student::checkCourseTaken(string ZID, CourseInfo c1)
{
	c1 = courseList.checkCourseTaken(c1);
	return c1;
}

But now that you had changed the 2 functions in SinglyLinkedList.h , the function no longer returns anything!

Secondly, the function isInList() within SinglyLinkedList.h, is that considered to be recursion. I only as this because i am 'supposted' to write this function recursively. By the looks of it would be considered so, but i am no expert.

As for those 3 functions; the Student.h (checkCourseTaken), SinglyLinkedList (checkCourseTaken & isInList), the main purpose of those is to check if a course has been taken from a student. If the student has taken the course, you print the course data, if not, have a message that says student did not take the course. However way this is completed, it has to be recursive! If i get help and it is in a non-recursive manner, i would not mind, as i have the brains (i think!) to turn it into a recursive method!

Once again, i thank you for your continued help with this project, it is greatly appreciated!

The first part is easy, my function is a void, thus not returning anything. The c1 within the function call has the values stored within it (see my code in the above post, the CourseInfo& searchCourse). So just get rid of "c1 =" and you should be fine. Make sure you leave the return c1; though, otherwise you'll have another issue.

One easy way to check it is to take that section, add a simple cout << "HERE\n"; or whatever you want it to put on the screen right before the recursive call, make it run a case that's not in the list, and see if you see that written on the screen a few times (should be twice if there are two cases in the list). If so, then it's recursive, if not, then it isn't. That's how I test if my recursive things are correct.

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.