Student Binary Files

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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include<iostream>
#include<fstream>
#include<cstdio>
using namespace std;

class Student
{
    int admno;
    char name[50];
public:
    void setData()
    {
        cout << "\nEnter admission no. ";
        cin >> admno;
        cout << "Enter name of student ";
        cin.getline(name,50);
    }

    void showData()
    {
        cout << "\nAdmission no. : " << admno;
        cout << "\nStudent Name : " << name;
    }
	 
    int retAdmno()
    {
        return admno;
    }
};

/*
* function to write in a binary file.
*/

void write_record()
{
    ofstream outFile;
    outFile.open("student.dat", ios::binary | ios::app);

    Student obj;
    obj.setData();
    
    outFile.write((char*)&obj, sizeof(obj));
    
    outFile.close();
}

/*
* function to display records of file
*/


void display()
{
    ifstream inFile;
    inFile.open("student.dat", ios::binary);

    Student obj;
    
    while(inFile.read((char*)&obj, sizeof(obj)))
    {
        obj.showData();
    }        
    
    inFile.close();
}

/*
* function to search and display from binary file
*/

void search(int n)
{
    ifstream inFile;
    inFile.open("student.dat", ios::binary);
    
    Student obj;

    while(inFile.read((char*)&obj, sizeof(obj)))
    {
        if(obj.retAdmno() == n)
        {
            obj.showData();
        }
    }
    
    inFile.close();
}

/*
* function to delete a record
*/

void delete_record(int n)
{
    Student obj;
    ifstream inFile;
    inFile.open("student.dat", ios::binary);

    ofstream outFile;
    outFile.open("temp.dat", ios::out | ios::binary);
    
    while(inFile.read((char*)&obj, sizeof(obj)))
    {
        if(obj.retAdmno() != n)
        {
            outFile.write((char*)&obj, sizeof(obj));
        }
    }

    inFile.close();
    outFile.close();
    
    remove("student.dat");
    rename("temp.dat", "student.dat");
}

/*
* function to modify a record
*/

void modify_record(int n)
{
    fstream file;
    file.open("student.dat",ios::in | ios::out);

    Student obj;

    while(file.read((char*)&obj, sizeof(obj)))
    {
        if(obj.retAdmno() == n)
        {
            cout << "\nEnter the new details of student";
            obj.setData();
            
            int pos = -1 * sizeof(obj);
            file.seekp(pos, ios::cur);
			
            file.write((char*)&obj, sizeof(obj));
        }
    }
  
    file.close();
}

int main()
{
    //Store 4 records in file
    for(int i = 1; i <= 4; i++)
       write_record();
	   
    //Display all records
    cout << "\nList of records";
    display();
	
    //Search record
    cout << "\nSearch result";
    search(100);
	
    //Delete record 
    delete_record(100);
    cout << "\nRecord Deleted";
	
    //Modify record
    cout << "\nModify Record 101 ";
    modify_record(101);
	
    return 0;
    system("pause")
}


So I am having trouble getting this code running. I have tried adding (int) infront of the sizeobj, and it get's the program to run with no errors but It does not run properly.. It constantly just askes for admission no. and not name. Please help with an explanation! Thanks
Have you paid attention to your compiler warnings?
1
2
3
:136:26: warning: overflow in conversion from ‘long unsigned int’ to ‘int’ changes value from ‘18446744073709551560’ to ‘-56’ [-Woverflow]
             int pos = -1 * sizeof(obj);
                       ~~~^~~~~~~~~~~~~

Is there are reason you're using a char array for name, when it is in fact, it's a string?

cin.getline is eating the end-of-line. You really should be using std::getline(std::cin, name);
Last edited on
@kbw can you please tell me the rearranged code?
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172

#include<iostream>
#include<fstream>
#include<cstdio>
using namespace std;

class Student
{
	int admno;
	string name;
public:
	void setData()
	{
		cout << "\nEnter admission no. ";
		cin >> admno;
		cout << "\nEnter name of student ";
		cin >> name;
	}

	void showData()
	{
		cout << admno; "\n";
		cout << name; "\n";
	}

	int retAdmno()
	{
		return admno;
	}
};

/*
* function to write in a binary file.
*/

void write_record()
{
	ofstream outFile;
	outFile.open("student.dat", ios::binary | ios::app);

	Student obj;
	obj.setData();

	outFile.write((char*)&obj, (int)sizeof(obj));

	outFile.close();
}

/*
* function to display records of file
*/


void display()
{
	ifstream inFile;
	inFile.open("student.dat", ios::binary);

	Student obj;

	while (inFile.read((char*)&obj, (int)sizeof(obj)))
	{
		obj.showData();
	}

	inFile.close();
}

/*
* function to search and display from binary file
*/

void search(int n)
{
	ifstream inFile;
	inFile.open("student.dat", ios::binary);

	Student obj;

	while (inFile.read((char*)&obj, (int)sizeof(obj)))
	{
		if (obj.retAdmno() == n)
		{
			obj.showData();
		}
	}

	inFile.close();
}

/*
* function to delete a record
*/

void delete_record(int n)
{
	Student obj;
	ifstream inFile;
	inFile.open("student.dat", ios::binary);

	ofstream outFile;
	outFile.open("temp.dat", ios::out | ios::binary);

	while (inFile.read((char*)&obj, (int)sizeof(obj)))
	{
		if (obj.retAdmno() != n)
		{
			outFile.write((char*)&obj, (int)sizeof(obj));
		}
	}

	inFile.close();
	outFile.close();

	remove("student.dat");
	rename ("temp.dat", "student.dat");
}

/*
* function to modify a record
*/

void modify_record(int n)
{
	fstream file;
	file.open("student.dat", ios::in | ios::out);

	Student obj;

	while (file.read((char*)&obj, sizeof(obj)))
	{
		if (obj.retAdmno() == n)
		{
			cout << "\nEnter the new details of student";
			obj.setData();

			int pos = -1 * static_cast<int>(sizeof(obj));
			file.seekp(pos, ios::cur);

			file.write((char*)&obj, sizeof(obj));
		}
	}

	file.close();
}

int main()
{
	//Store 4 records in file
	for (int i = 1; i <= 4; i++)
		write_record();

	//Display all records
	cout << "\nList of records";
	display();

	//Search record
	cout << "\nSearch result";
	search(100);

	//Delete record 
	delete_record(100);
	cout << "\nRecord Deleted";

	//Modify record
	cout << "\nModify Record 101 ";
	modify_record(101);

	return 0;
	system("pause");
}


So it lets me enter the 4 students but it errors out after that? WHAT about this code is wrong???
aftger i enter the amount of people in the for loop in the main method... I get this


Exception thrown at 0x00F29B92 in BinaryFilesFinal.exe: 0xC0000005: Access violation writing location 0xDDDDDDDD.

You're not serialising your data properly.
1
2
3
4
5
6
class Student
{
public:
	int admno;
	string name;
};


Try this simple test.
1
2
3
4
5
6
7
int main ( ) {
   Student foo;
   foo.name = "fred";
   cout << sizeof(foo) << endl;
   foo.name = "this is my name, it's the longest in the world, good luck putting this on your puny forms";
   cout << sizeof(foo) << endl;
}


The content of the string is NOT part of your object, it's somewhere else in memory.

It's also somewhere else in memory (which no longer exists) when you read it back in from the file.

char name[100];
would work just fine, for this homework.
If you use an object in Student, say std::string instead of char array for name, you'll to rewrite the save/restore code.

I'll start again, Student needs save/restore methods. No external thing should have access to its implementation.

Let's also look at Initialization. It's constructed from an Admin Number/Name pair or from the stream. So let's redefine Student to be constructed that way.

One more thing, we can expect a name to be up to 50 chars. As you're storing fixed length records in the binary file, it's important to maintain the size of the written record.

And we'll need a save() method that writes to a stream.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Student {
    int admno_;
    std::string name_;

public:
    Student() : admno_(-1) {}
    Student(int admno, std::string name) : admno_(admno), name_(name) {}
    Student(std::istream& is) {
        is.read((char*)&admno_, sizeof(int));
        char buffer[50];
        is.read(buffer, sizeof(buffer));
        name_ = buffer;
    }
    void save(std::ostream& os) {
        os.write((char*)&admno, sizeof(int));
        char buffer[50] = {0}; // initialize to zero
        strncpy(buffer, name_.c_str(), sizeof(buffer) - 1); // leave space for the null
        os.write(buffer, sizeof(buffer));
    }
    // ...
};


Then your write_record will look like:
1
2
3
4
void write_record(const Student& student) {
    std::ofstream os("student.dat", std::ios::binary|std::ios::app);
    student.write(os);
}


Search will look like:
1
2
3
4
5
6
7
8
9
10
11
void search(int admno, bool& found, Student& result) {
    found = false;
    std::ifsteam is("student.dat", std::ios::binary);
    while (is && !found) {
        Student student(is);
        if (student.redAdmno() == admno) {
            found = true;
            result = student;
        }
    }
}


I haven't tried to compile any of this, but I hope the idea helps. The point of Object Oriented Programming is to get the Objects to do stuff that they know about.
Last edited on
Topic archived. No new replies allowed.