Click here to Skip to main content
14,695,615 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hey all, I've been learning to program for a few months now and I've been working on a program to manage student data. Here's the code:

#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <stdio.h>

using namespace std;

class Student
{
private:
    string name;
    string course;
    int section;
    int grade;

public:
    void calcgrade();
    void getData();
    void showData();

};

void Student::calcgrade() 
{
    if (grade >= 90)

        grade = 'A';

    else if (grade >= 80)

        grade = 'B';

    else if (grade >= 70)

        grade = 'C';

    else if (grade >= 60)

        grade = 'D';

    else

        grade = 'F';
}

void Student::getData() 
{
    cout << "Enter the name of the student: ";
    cin.ignore();
    getline(cin, name);

    cout << "Enter the course: ";
    cin >> course;

    cout << "Enter the section: ";
    cin >> section;

    cout << "Enter the grade received: ";
    cin >> grade;
    calcgrade();
}

void Student::showData()
{
    cout << ".......Student Information......" << endl;
    cout << "Student Name: " << name << endl;
    cout << "Course: " << course << endl;
    cout << "Section: " << section << endl;
    cout << "Grade: " << grade << endl;
    cout << endl;
}


void addData() 
{
    Student st; 
    ofstream fout; 
    fout.open("Student.data", ios::binary | ios::out | 
            ios::app); 
    st.getData(); 
    fout.write((char*)& st, sizeof(st)); 
    fout.close(); 
    cout << "Data Successfully Saved to File." << endl;
}

void displayData() 
{
    Student st;
    ifstream file;  
    file.open("Student.data", ios::in | ios::binary);

    if (file.is_open()) 
    {
        while (file.read((char*)& st, sizeof(st)))
        {
            st.showData(); 
        }

        cout << "Finished Reading Data From File." << 
                    endl;
    }
    else 
    {
        cout << "Unable to open file" << endl;
    }
    file.close();

}

void searchData()
{
    Student st;
    ifstream file;
    file.open("Student.data", ios::in | ios::binary);
    string search; 
    cout << "Please enter the first name of a student to search for: ";
    cin >> search;
    bool isFound = 0; 
    while (file.read((char*)& st, sizeof(st))) 
    {
        string temp = " ";
        getline(file, temp);
        for (int i = 0; i < search.size(); i++)
        {
            if (temp[i] == search[i])
                isFound = 1;
            else
            {
                isFound = 0;
                break;
            }
        }

        if (isFound) 
        {
            cout << "The name " << search << " was found in the database." << endl;
            break;
        }
    }

    if (file.read((char*)& st, sizeof(st)) && (!isFound)) 
    {
        cout << "Name not found." << endl;
    }

    file.close();
}

void modifyData() 
{
    Student st;
    string stname;
    bool isFound = 0; 
    int pos;
    fstream file;

    file.open("Student.data", ios::in | ios::out | ios::binary);

    cout << "Enter the name of a student whose data you want to modify: ";
    cin >> stname;

    while (file.read((char*)& st, sizeof(st))) 
    {
        string temp = " ";
        getline(file, temp);
        for (int i = 0; i < stname.size(); i++)
        {
            if (temp[i] == stname[i])
                isFound = 1;
            else
            {
                isFound = 0;
                break;
            }
        }

        if (isFound)
        {
            pos = file.tellg(); 

            cout << "Current Data" << endl;
            st.showData();
            cout << "Modified Data" << endl;
            st.getData();
            file.seekg(pos - sizeof(st)); 
            file.write((char*)& st, sizeof(st));
        }

    }

    if (file.read((char*)& st, sizeof(st)) && (!isFound)) 
    {
        cout << "Name not found." << endl;
    }

    file.close();
}

void deleteData()
{
    Student st;
    string stname;
    bool isFound = 0;
    ifstream file;
    ofstream fout;

    file.open("Student.data", ios::in | ios::binary);
    fout.open("Temporary.data", ios::out | ios::app | ios::binary);

    cout << "Enter the name of a student whose data you want to delete: ";
    cin >> stname;

    while (file.read((char*)& st, sizeof(st))) 
    {
        string temp = " ";
        getline(file, temp);
        for (int i = 0; i < stname.size(); i++)
        {
            if (temp[i] == stname[i])
                isFound = 1;
            else
            {
                isFound = 0;
                break;
            }
        }

        if (isFound)
        {

            cout << "Bleh" << endl;
            fout.write((char*)& st, sizeof(st));
        }
    }
    if (file.read((char*)& st, sizeof(st)) && (!isFound))
    {
        cout << "Name not found." << endl;
    }

    fout.close();
    file.close();

    remove("Student.data");
    rename("Temporary.data", "Student.data");
}
void printData()
{
    ifstream file;
    file.open("Student.data", ios::in | ios::binary);
    if (file.is_open())
    {
        cout << file.rdbuf();
    }

    file.close();
}

int main()
{
    int num;


    do
    {
        cout << "...............STUDENT MANAGEMENT SYSTEM..............\n";
        cout <<  "======================================== ==============\n";
        cout << "0. Close Program. " << endl;
        cout << "1. Add Data. " << endl;
        cout << "2. List Data. " << endl;
        cout << "3. Modify Data. " << endl;
        cout << "4. Search For Data. " << endl;
        cout << "5. Print Data. " << endl;
        cout << "6. Delete Data. " << endl;

        cout << "Choose an option: ";
        cin >> num;

        if (num == 1)
        {
            addData();
        }
        else if (num == 2)
        {
            displayData();
        }
        else if (num == 3)
        {
            modifyData();
        }
        else if (num == 4)
        {
            searchData();
        }
        else if (num == 5)
        {
            printData();
        }
        else if (num == 6)
        {
            deleteData();
        }
    } while (num > 0);

    return 0;
}



Ideally, when the program runs, the user chooses an option, with different function calls depending on the number entered. The Add Data option works fine, but when choosing others, such as List Data or Search Data, I run into an error: Unhandled exception thrown: read access violation. _Pnext was 0x10A6A04.

Code in xmemory:

inline void _Container_base12::_Orphan_all() noexcept {
    #if _ITERATOR_DEBUG_LEVEL == 2
        if (_Myproxy != nullptr) { // proxy allocated, drain it
            _Lockit _Lock(_LOCK_DEBUG);

            for (_Iterator_base12** _Pnext = &_Myproxy->_Myfirstiter; *_Pnext != nullptr;
                *_Pnext = (*_Pnext)->_Mynextiter) {
                (*_Pnext)->_Myproxy = nullptr;
            }

            _Myproxy->_Myfirstiter = nullptr;
        }



The error occurs after != nullptr. Because there are no obvious errors in the code, I'd like a little help in picking out what I've done wrong.

Thanks.

What I have tried:

I've been looking at the code for hours, and have tried rearranging things in various ways. I'm completely lost.
Posted
Updated 9-May-20 2:03am
v2
Comments
Rick York 8-May-20 22:15pm
   
I don't have a specific answer but I think the first thing you should do is make sure your showData functions correctly and call it OFTEN! After every single operation you should display your list and make sure it is still valid. This is known as printf style debugging. A better option is to learn how to use your debugger.

Actually I think your whole approach is wrong. I think you should read all your data into memory and save it in a container of some sort. std::list and vector are good options. List is better for insertions and removals so that is the better option. Then manipulate your data in memory. When you are done with the data then write it all out to a file at one go. Doing things intermittently to the file like you are is asking for trouble in my opinion. As far as I am concerned that is really only a good option if the file is to big to fit into memory conveniently.

Quote:
while (file.read((char*)& st, sizeof(st)))
You cannot do that. Student instances are not POD (see, for instance Passive data structure - Wikipedia[^]), they contain reference to other objects (std::string). What you need is proper object serialization (see, for instance A practical guide to C++ serialization[^].
   
This code has many flaws:
1. The private members should be initialized; otherwise there values are undefined when you instantiate on object of type Student. STL class member variables like 'string', 'vector', etc., do not need to be initialize, because they initialize themselves. But variable like 'int', ''long', etc., should be initialized in the class constructor.
2. How are you supposed to get/set the internal private data? You have not provided public methods for getting or setting those values. You could set their initial values via the constructor. But you would also need public methods for reading them or changing them if required.
Example:
const string& name() { return name; } // or get_name()
void name(const string& aname) { name = aname; } // or set_name(...)

3. All the I/O should be external methods/functions. The Student class should not know or care were the data it stores is coming from or what it is being used for. There are exceptions to this rule, but that is a more advance subject.
4. You cannot read/write class objects to a file using 'file.read' and file.write' in the manner that you are using. The Student class is not a simple block of memory (or POD) and, therefore, cannot be treated like one. The way you are using them is going to corrupt memory, which is probably what is causing your exception.
5. Do not assume all integer values are of type 'int'. 'sizeof(type)' returns a 'size_t' value, which is implementation defined. It could be an unsigned 32 or 64 bit integer; again it depends on the implementation. This also applies to the file position type. A file position type is defined in the file stream class (Exp.: fstream::pos_type) and is normally of type 'streampos'.

Your compiler should have generated warnings about size type conversion and signed/unsigned comparisons. When you see such warnings, then you should investigate what is causing them. Depending on how your configuration is setup, the compiler may treat such warning as errors instead and refuse to create your program.

(2nd attempt at posting)
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900