Why it repeats last record only?

I'm writing just a simple program that gets input from user and stores them in a file and displays the contents when required. Following is my program.

What is eating my head is, why it displays the last record two times? Tried everything, might be due to my limited knowledge, Please help me!

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
#include<iostream>
#include<string>
#include<fstream>

using namespace std;

struct employee{
	int eno;
	string name, address;
	float basic, allowence, deduction;
};
void showData(employee e);
void addRecord();
void displayRecord();
void deleteRecord();
void modifyRecord();

int main(){
	int m; //determine which menu is selected
	string dummy;
	do{
	cout<<" =============PAYROLL SYSTEM ==================="<<endl;
	cout<<endl;
	cout<<"Options:"<<endl<<endl;
	cout<<"1   ->  Add new record"<<endl;
	cout<<"2   ->  Display All Records"<<endl;
	cout<<"3   ->  Delete Record"<<endl;
	cout<<"4   ->  Modify Data"<<endl;
	cout<<"0   ->  Exit Program"<<endl;
	cout<<endl<<endl;
	cout<<"Enter your choice "; cin>>m;
	cout<<"Value of m "<<m<<endl;
	

	switch(m){
		case 1:	addRecord();		break;
		case 2:	displayRecord();	break;
		case 3:	deleteRecord();		break;
		case 4:	modifyRecord();		break;
		case 0:	return 0;			break;
	}
	}while(!m==0);

}
void addRecord(){
	fstream data;
	employee e;
	string dummy;
	int choice=0;

	data.open("data.dat",ios::out|ios::app);
	do{
		cout<<endl<<endl;
		cout<<"Input data for this record"<<endl;
		cout<<endl<<endl;
		cout<<"ENO: "; cin>>e.eno; 
		getline(cin,dummy); //just clear input buffer
		cout<<"Name: "; getline(cin,e.name);
		cout<<"Adress: "; getline(cin,e.address);
		cout<<"Basic Salary: "; cin>>e.basic;
		cout<<"Allowences: "; cin>>e.allowence;
		cout<<"Deducation: "; cin>>e.deduction; 
		cout<<endl<<endl;
		cout<<"1 -> Save  |  2 -> Cancel  "; cin>>choice;
		if (choice==1){
			data.write((char*) & e, sizeof(e));
			cout<<endl<<"Record Saved";
		}else{
			cout<<endl<<"Record Cancelled";
		}
		cout<<endl<<endl<<"Add another record?"<<endl;
		cout<<endl<<"<<1 -> Yes  | 2 -> No "; cin>>choice;
	}while(choice==1);
	data.close();
	
}
void displayRecord(){
	fstream data;
	employee e;
	data.open("data.dat",ios::in);
	//data.seekg(0,ios::beg);
	while(!data.eof()){
		data.read((char*) &e, sizeof(e));
		cout<<e.eno<<endl;
		showData(e);
	}
	data.close();	
	
}
void deleteRecord(){
	/*
	employee de;
	fstream data;
	fstream temp;
	data.open("data", ios::in);
	temp.opean("data",ios::out);

	while(!data.eof()){
		data.read((char*)
		*/
}
void modifyRecord(){
}
void showData(employee se){
	cout.clear();
	cout<<endl<<endl;
	cout<<"-----Record for ENO:- " << se.eno<<"-----";
	cout<<"\nName: " <<se.name;
	cout<<"\nAddress: "<<se.address;
	cout<<"\nBasic Salary: "<< se.basic;
	cout<<"\nAllowence: "<<se.allowence;
	cout<<"\nDeducation: "<<se.deduction;
	cout<<"\nNet Pay: "<< se.basic + se.allowence + se.deduction<<endl<<endl;
}
while(!data.eof())
Only kicks you out of the while loop after you've failed to read from the file, so the contents you display stay the same as from the previous entry.
OK, that's great. So, what would be the better alternative to that while(!data.eof()) ?
while(data.read((char*) &e, sizeof(e)))
Or you can calculate the numbers or registers and use a for.

Also you've got a little problem with your structure: string name, address;. The idea with binary files is constant size of registers, so you can get the one you want in constant time.

And I think the string only contents a pointer to where is the data stored, so if you do
data.write((char*) & some_string, sizeof(string));
you'll get the direction and not the words.
Last edited on
You can't just read and write your employee records in binary the way you do because they contain std::string objects which use pointers. You will write the pointer but not the string itself.

This thread has the same problem: http://www.cplusplus.com/forum/beginner/27223/
Thank you guys, it really helped a lot. After all genius are genius!

regarding string, I had a doubt. You are right to say. So, I need to use char arrays for text fields, isn't it?

Thanks Galik, the link enriched my insight.
Last edited on
Using char arrays should work. Writing in binary as you are doing should work as long as your class only contain 'plain old data' or built in types, not class objects or pointers: http://www.parashift.com/c++-faq-lite/intrinsic-types.html#faq-26.7

Topic archived. No new replies allowed.