Need help with how to delete a record

This is my first time using this forum so I am a bit unsure of what exactly to include for my code. My assignment for class was to create a Student ADT. I have three files. First one is Student.h which defines a Student record and has the prototypes of the functions that can be used with Student. I have Student.cc which is where the functions are actually declared. And my final file is testStudent.cc where the "main" function is that is creating a Student and callign all of the functions to make sure they work properly. I have all of the functions working properly, except for my destroyStudentRecord function. It is supposed to deallocate the record, but I am unsure of how to actually do this. The current implementation appears to only deallocate the firstName field, as when you display the record after deallocationg it, everything still shows up except the first name. I have tried deallocating each field of the record before deallocating the record itself and that gave me the biggest list of errors I have ever seen. I realize the implementation of some things in here might be a bit odd, but this is exactly how we are required to do things for this assignment and nothing about the implementation can really be changed unless something is actually just plain wrong(which is of course a possibility as I am quite new to this!). As I said though, everything else is working exactly as it should be, so my only issue at all is with actually deleting the record once I have created one. Everything I have been able to find online looks nothing like this code and looks nothing like anything I have ever seen before either, so I am unsure of what exactly to do. I have also asked numerous friends and others in the class and have spent probably 30+ hours trying different things to get it to work and the current version is the closest I can get it and the ONLY implementation where I didn't get a TON of errors. This is a first year c++ class and any help on how to properly delete a record would be greatly appreciated. It isn't letting me upload my code, so I will try to copy what is necessary here.

Student.h:
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
#include <iostream>
#include <cstdlib>
using  namespace std;

#ifndef _STUDENT_H_
#define _STUDENT_H_

struct Student
{
   char firstName[30];
   char lastName[30];
   char studentNumber[10];
   int assignGrades[10];
   int examGrade;
};


//Algorithm createStudentRecord()
//pre: nothing
//post: allocate memory for a new student
//return: reference to a memory location for a new student

Student* createStudentRecord();


//Algorithm destroyStudentRecord(Student* s)
//pre: s - Student
//post: deallocate Student
//return: nothing

void destroyStudentRecord(Student* s);


//Algorithm displayStudentRecord(Student s)
//pre: s - student
//post: student is printed to the console
//return: nothing

void displayStudentRecord(Student s);


//Algorithm readStudentRecordFromConsole()
//pre: nothing
//post: nothing
//return: reference to new student with info typed in from the console

Student* readStudentRecordFromConsole();


//Algorithm changeAssignmentGradeForStudent(Student* s, int a, int g)
//pre: s - student
//     a - assignment number
//     g - amount to change the grade by
//post: grade stored in assignGrades[a] is changed by g
//return: nothing

void changeAssignmentGradeForStudent(Student* s, int a, int g);


//Algorithm changeExamGradeForStudent(Student* s, int e)
//pre: s - student
//     e - amount to change exam grade by
//post:  grade stored in examGrade is changed by e
//return: nothing

void changeExamGradeForStudent(Student* s, int e);

#endif 


Student.cc:
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
#include <iostream>
#include <cstdlib>
#include "Student.h"

using  namespace std;


//Algorithm createStudentRecord()
//pre: nothing
//post: allocate memory for a new student
//return: reference to a memory location for a new student

Student* createStudentRecord()
{
   Student* studentPtr = new Student;
   return studentPtr;
}


//Algorithm destroyStudentRecord(Student s)
//pre: s - Student
//post: deallocate Student
//return: nothing

void destroyStudentRecord(Student* s)
{
   delete s;
}


//Algorithm displayStudentRecord(Student s)
//pre: s - student
//post: student is printed to the console
//return: nothing

void displayStudentRecord(Student s)
{
   cout << s.lastName << ", " << s.firstName << ", " <<  s.studentNumber << endl;
   for(int i = 0; i < 9; i++)
   {
      cout << s.assignGrades[i] << ", ";
   }
   cout << s.assignGrades[9] << ". Exam: " << s.examGrade << endl;
}


//Algorithm readStudentRecordFromConsole()
//pre: nothing
//post: nothing
//return: reference to new student with info typed in from the console

Student* readStudentRecordFromConsole()
{
   Student* inputStudent;
   inputStudent = createStudentRecord();
   cin >> inputStudent->firstName;
   cin >> inputStudent->lastName;
   cin >> inputStudent->studentNumber;
   for(int i = 0; i < 10; i++)
   {
      cin >> inputStudent->assignGrades[i];
   }
   cin >> inputStudent->examGrade;
   return inputStudent;
}


//Algorithm changeAssignmentGradeForStudent(Student s, int a, int g)
//pre: s - student
//     a - assignment number
//     g - amount to change the grade by
//post: grade stored in assignGrades[a] is changed by g
//return: nothing

void changeAssignmentGradeForStudent(Student* s, int a, int g)
{
   s->assignGrades[a] += g;
}


//Algorithm changeExamGradeForStudent(Student s, int e)
//pre: s - student
//     e - amount to change exam grade by
//post:  grade stored in examGrade is changed by e
//return: nothing

void changeExamGradeForStudent(Student* s, int e)
{
   s->examGrade += e;
}


testStudent.cc:
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
#include <iostream>
#include <cstdlib>
#include <cstring>
#include "Student.h"

using  namespace std;

int main(){

Student* testStudent;
testStudent = createStudentRecord();

strcpy(testStudent->firstName, "Ashley");
strcpy(testStudent->lastName, "Armstrong");
strcpy(testStudent->studentNumber, "12345678");

for(int i = 0; i < 10; i++)
{
   testStudent->assignGrades[i] = i*10;
}

testStudent->examGrade = 95;

displayStudentRecord(*testStudent);

changeAssignmentGradeForStudent(testStudent, 2, 5);
displayStudentRecord(*testStudent);

changeExamGradeForStudent(testStudent, 5);
displayStudentRecord(*testStudent);

destroyStudentRecord(testStudent);
displayStudentRecord(*testStudent);

testStudent = readStudentRecordFromConsole();
displayStudentRecord(*testStudent);

destroyStudentRecord(testStudent);
displayStudentRecord(*testStudent);

}


Sorry if this isn't the correct way to do this, but I wasn't sure how else to do it!
Last edited on
When you deallocate something you merely mark memory area of that object free for reuse, it will not zero out memory or something. Then you are passing your student record by value to display function i.e. accessing deleted memory. This leads to undefined behavior: your program can work as expected, work incorrectly (your case), crash or make your heart stop. Seriously, there is nothing in Standard which disallows that.

So your deallocation routine appears to be working correctly (just don't call it on records stored in arrays or STL containers) and you just did something that is disallowed by language Standard and suffered from it.
Last edited on
My assignment for class was to create a Student ADT.
An abstract data type is a black box, with the data completely hidden.

A really good example of an ADT implementation in C is FILE*. You don't really care what's in a FILE, you only care that you use it with fopen, fclose, fread, fwrite, fseek, ftell, ...

A not so good example of an ADT implemented in C is string. The implementation is exposed (char*), but that asside, you can use it with strdup, strcat, strcpy, strstr, strchr, ...

There are some problems with your implementation:
1. The implementation is exposed.
2. You can use C++ language features to enforce ADT principles.

So, in C++, I'd expect your ADT to look like:
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
#include <string>
#include <istream>
#include <ostream>

class Student
{
friend std::ostream& operator<<(std::ostream&, const Student&);
friend std::istream& operator>>(std::istream&,  Student&);

public:
   const std::string& getFirstName() const;
   const std::string& getLastName() const;
   const std::string& getStudentNumber() const;
   int getAssignGrades() const;
   int getExamGrade() const;

   void setFfirstName(const std::string&);
   void setLastName(const std::string&);
   void setStudentNumber(const std::string&);
   void assignGrade(int idx);
   void assignGrade(int idx, int value);
   void setExamGrade(int);

    // optionally
    static Student* create();
    static void destroy(Student*);

private:
   std::string firstName;
   std::string lastName;
   std::string studentNumber;
   std::vector<int> assignGrades;
   int examGrade;
};

std::ostream& operator<<(std::ostream&, const Student&);
std::istream& operator>>(std::istream&,  Student&);


I've replaced C strings with the standard string, and the int array with a standard int container.

The client code would then look like:
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
#include <iostream>
#include <cstdlib>
#include <cstring>
#include "Student.h"

int main()
{
    Student* testStudent = Student::create();
    testStudent->setFirstName("Ashley");
    testStudent->setLastName("Armstrong");
    testStudent->setStudentNumber("12345678");

    for (int i = 0; i < 10; i++)
    {
        testStudent->assignGrade(i * 10);
    }

    testStudent->setExamGrade(95);
    std::cout << (*testStudent) << std::endl;

    testStudent->assignGrade(2, 5);
    std::cout << (*testStudent) << std::endl;

    // ... and so on

    Student::destroy(testStudent);
    testStudent = std::nullptr;
}


As for the implementation of new/delete
1
2
3
4
5
6
7
8
9
Student* Student::create()
{
    return new Student();
}

Student::destory(Student* obj)
{
    delete obj;
}


Of course those wrappers, create/destroy are optional. But even if you needed to keep them, these days you'd use a smart pointer that does the delete for you:
1
2
3
4
5
6
7
8
#include "Student.h"
#include <memory>

int main()
{
    std::unique_ptr<Student> testStudent = testStudent(Student::create(), Student::destroy);
    // ... don't call destroy when you're done, the smart pointer does it for you.
}
Last edited on
Topic archived. No new replies allowed.