Help please with reading into a linked list

closed account (35S3T05o)
My program is supposed to prompt the user if they want a student object or employee then let them enter the data. The program continues to crash after prompted for the second object in this list. I cannot figure out why, i think it may have to do with the insert sorted function? Please help

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include "PersonList.h"

/** 
 * Main function. Prompts the user for information on Students and Employees. 
 *    Creates a sorted linked list of pointers to Person objects. Prints the list.
 */
int main () {
	LinkedList list;
   string msg = "Do you want to enter a Student, an Employee, or Neither? ";

   string choice = getStringLine (msg);

   // Continue until the user chooses not to enter any more People.
   while (toupper (choice[0]) != 'N') {
      Person *person = nullptr;
      if (toupper(choice[0]) == 'E') {
         person = readEmployee ();
	 } else if (toupper(choice[0]) == 'S'){
       person = readStudent ();
      }
	 else {
		 cout << msg;
		 choice = getStringLine (msg);
	 }
      list.insertSorted (person);
      choice = getStringLine (msg);
   }

   // Determine what information to print for each Person.
   choice = getStringLine ("Do you want to print all information? ");
   if (toupper(choice[0]) == 'Y') {
      list.printAll();
   } else {
      list.print();
   }

	return EXIT_SUCCESS;
}

/**
 * Reads input until a string line is correctly entered. Prompt the user using
 *    the provided message.
 */
string getStringLine (const string &msg) {
	string response;
	cout << msg;
	getline(cin,response);
	int size = response.size();
	if ( size <= 0){ getStringLine(msg);}
	else 
	{return response;}
   }

/**
 * Reads in a person's basic information: name, gender, and year of birth.
 */
void getPersonBasics (string &name, bool &isMale, int &year) {
   string token = "";
   string pronoun = "his";
   token = getStringLine ("Enter the person's gender: ");
   isMale = (toupper(token[0]) == 'M');
   if (!isMale) pronoun = "her";
   
   name = getStringLine ("Enter " + pronoun + " name: ");

   while (!isInteger (token)) {
      token = getStringLine ("Enter " + pronoun + " year of birth: ");
   }
   istringstream strstream (token);
   strstream >> year;
}

/**
 * Determines whether the string holds a valid integer. Checks if each 
 *    character is a digit.
 */
bool isInteger (const string &str) {
   if (str.size() < 1) return false;
   for (unsigned int i = 0; i < str.size(); ++i) {
      if (!isdigit(str[i])) return false;
   }
   return true;
}

/**
 * Determines whether the string holds a valid double. Checks if each 
 *    character is digit and there is no more than 1 decimal point.
 */
bool isDouble (const string &str) {
	int decimal = 0;
	for (unsigned int i = 0; i < str.size(); ++i){
		if ( str[i] == '.'){
			decimal++;}
		if( !isdigit(str[i]) && (str[i] != '.')){
			return false;}
	}
	if( (decimal != 1)) return false;
	return true;
}

/**
 * Reads input until a valid double is entered. Prompts the user with provided
 *    message.
 */
double getDouble (const string &msg) {
	cout << msg;
	string num;
	cin >> num;
	while( !isDouble(num)){
		cout << "Enter a valid number ";
		cin>> num;
	}
	double s = atof(num.c_str());
	return s; // stubbed method. Replace this return statement.
}

/**
 * Reads the information needed to create an Employee object, dynamically 
 *    allocates an Employee object with the provided information, and 
 *    returns it.
 */
Employee *readEmployee () {
   string name, token, title;
   string pronoun = "his";
   float salary;
   int year;
   bool isMale;
   getPersonBasics (name, isMale, year);
   if (!isMale) pronoun = "her";

   title = getStringLine ("Enter " + pronoun + " job title: ");
   salary = static_cast<float> (getDouble("Enter " + pronoun + " salary: "));
   return new Employee (name, isMale, year, title, salary);
}

/**
 * Reads the information needed to create a Student object, dynamically 
 *    allocates a Student object with the provided information, and returns it.
 */
Student *readStudent () {
	string name, token, major;
	string pronoun = "his";
	float gpa;
	int year;
	bool isMale;
	getPersonBasics (name,isMale, year);
	if (!isMale) pronoun = "her";

	major = getStringLine("Enter " + pronoun + " major: ");
	gpa = static_cast<float> (getDouble("Enter " + pronoun + " gpa: "));
	return new Student(name, isMale, year, major, gpa);
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include "LinkedList.h"

/**
 * Constructor for the Node class declared inside the LinkedList class.
 */
LinkedList::Node::Node (Person *p, Node *n) {
	person = p;
	next = n;
}

/**
 * Default constructor. Assigns a value to head.
 */
LinkedList::LinkedList () {
	head = nullptr;
	// Program will crash in the destructor if this is not written correctly.
}

/**
 * Destructor. Deallocates all Person object and Nodes.
 */
LinkedList::~LinkedList() {
   Node *curr, *next;
   curr = head;
	while (curr != nullptr) {
      next = curr->next;
      delete curr->person;
      delete curr;
      curr = next;
	}
   head = nullptr;
}

/**
 * Copy constructor. Throws an exception to prevent the user from creating
 *    copies of LinkedList objects.
 */
LinkedList::LinkedList (const LinkedList &) {
   throw std::exception ("ERROR: this class does not allow copying.");
}

/**
 * Assignment operator. Throws an exception to prevent the user from copying
 *    LinkedList objects.
 */
const LinkedList &LinkedList::operator= (const LinkedList &) {
   throw std::exception ("ERROR: this class does not allow copying.");
}

/**
 * Print method. Prints basic information for each Student and Employee in the
 *    list. Meaning just the name
 */
void LinkedList::print () const {
	for(Node *current = head; current != nullptr; current = current->next){
		cout << current->person->getName() << endl;
		//Person * p = current->person;
		//cout << current->person << endl;
	}
}

/**
 * PrintAll method. Prints all data in each Student and Employee in the list.
 */
void LinkedList::printAll () const {
	for(Node *current = head; current != nullptr; current = current->next){
		cout << current->person->toString() << endl;
		
	}
}

/**
 * Inserts the passed-in Person object pointer into the linked list in 
 *    ascending order by name.
 */
void LinkedList::insertSorted (Person *p) {
	Node *ptr,*prev;
	 if(isEmpty()){
		head = new Node(p,head);
	 }
	 else{
		 prev= head;
		 ptr = head->next;
		 
		 while(ptr != nullptr && ((ptr->person->getName()) < (p->getName()))){
			 prev = ptr;
			 ptr = ptr->next;
		 }
		 prev->next = new Node(p,ptr);

	 }
}
	 
/** 
 * Returns true if the list is empty.
 */
bool LinkedList::isEmpty () const {
	if(head == nullptr)return true; 
	else return false;// stubbed method. Replace this return statement.
}
One possible problem is that getStringLine doesn't always return a value, even though it promises to.

And, you're on the money. There is a problem with insertSorted. I would expect something like the following (warning: not tested.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void LinkedList::insertSorted(Person* p)
{
    if ( isEmpty() )
        head = new Node(p,nullptr) ;
    else
    {
        if ( p->getName() <  head->person->getName() )
            head = new Node(p, head) ;
        else
        {
            Node * prev = head ;
            Node * curr = head->next ;
            while ( curr && curr->person->getName() < p->getName() )
            {
                prev = curr ;
                curr = curr->next ;
            }

            prev->next = new Node(p, curr) ;
        }        
    }
}
It is extremely rude to delete your posts so that nobody else may benefit from the thread after someone else has fixed your problem for you.
Topic archived. No new replies allowed.