Why is the data not getting properly written/read in this file? - c++

The following code just accepts some data from the user in an object and writes it in a binary file. The first object gets written fine but after that it gets messed up.
Below is the output on reading the file after writing the first object onto it.
ROLL NO. NAME MARKS
234 Sansa 67
All fine and just as I expect. But when I append another object in the file, then this happens.
ROLL NO. NAME MARKS
234 SansSnow 78
564 Jon Snow 78
The roll numbers remain intact however names of the previous objects gets mixed up with the last object's and their marks get overwritten by the marks of the last object.
Why is it happening?
CODE:
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
fstream file;
class Student
{
protected:
int rollno;
char name[30];
float marks;
public:
void getData()
{
cout<<"ENTER THE DATA..."<<endl<<endl;
cout<<"Roll Number : ";
cin>>rollno;
fflush(stdin);
cout<<"Name : ";
cin.getline(name,30);
cout<<"Marks : ";
cin>>marks;
}
void displayData()
{
cout<<"\n"<<rollno;
cout<<setw(17)<<name;
cout<<setw(13)<<marks;
}
void writeData()
{
file.open("StudentData.dat", ios::app|ios::binary);
file.write((char*)this, sizeof(this));
file.close();
}
void readData()
{
file.open("StudentData.dat",ios::in|ios::binary);
while(file.read((char*)this, sizeof(this)))
{
displayData();
}
file.close();
}
};
Student S1;
int main()
{
cout<<"\nMAIN MENU"<<endl<<endl;
cout<<"1. Enter data and write to file\n";
cout<<"2. Read data from file and display\n";
cout<<"3. Exit\n\n";
cout<<"Enter your choice : ";
int choice;
cin>>choice;
switch(choice)
{
case 1:{
S1.getData();
S1.writeData();
cout<<endl<<endl;
cout<<"Data written to file successfully!"<<endl;
main();
break;
}
case 2:{
cout<<"ROLL NO."<<setw(10)<<"NAME"<<setw(15)<<"MARKS";
S1.readData();
cout<<endl;
main();
break;
}
case 3:{
exitop:
char confirmExit;
cout<<"\nAre you sure you want to exit? (Y/N) : ";
cin>>confirmExit;
if(confirmExit=='y' or confirmExit=='Y')
exit(0);
else if(confirmExit=='n' or confirmExit=='N')
{
cout<<"Exit Aborted.\n\n";
getchar();
main();
}
else{
cout<<"Invalid Input!";
goto exitop;
}
}
default:{
cout<<"Invalid Input!";
break;
}
}
return 0;
}

You’re only reading and writing 8 bytes. this is a pointer so sizeof(this) is 8 (on a 64 bit machine). What you actually want to do is get the size of the object instead so use sizeof(*this) or sizeof(Student).

Related

C++ File handling Program

Here I have tried to write a program write, update, display, delete, and print record. Display a menu of option and select an option to execute it.
Problem is that, "Neither default switch statement is executed nor 3 to 6 option executed."
Can someone point out the error/mistakes?
#include <iostream>
#include <fstream>
#include <windows.h>
#include <iomanip>
using namespace std;
void gotoxy(short x, short y) {
COORD pos = {x, y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
struct data{
char mark;
char name[15],city[15];
};
class person{
public:
void addrec(void);
void update(void);
void disp_all(void);
void display(void);
void delrec(void);
void pack(void);
};
int main(){
person obj;
int ch;
while(1){
system("cls");
gotoxy(28,5);
cout<<"Person Records";
gotoxy(25,6);
cout<<"===================="; //20
gotoxy(25,7);
cout<<"1: Add Records ";
gotoxy(25,8);
cout<<"2: Update Records ";
gotoxy(25,9);
cout<<"3: Display All Records ";
gotoxy(25,10);
cout<<"4: Display Single Records ";
gotoxy(25,11);
cout<<"5: Mark Record for Deletion ";
gotoxy(25,12);
cout<<"6: Delete Records Permanently";
gotoxy(25,13);
cout<<"7: Exit ";
gotoxy(25,15);
cout<<"Enter Your choice [1-7] ";
cin>>ch;
switch(ch){
case 1: obj.addrec(); break;
case 2: obj.update(); break;
case 3: obj.disp_all(); break;
case 4: obj.display(); break;
case 5: obj.delrec(); break;
case 6: obj.pack(); break;
case 7: exit(1); break;
default:
cout<<"invalid choice ";
}
}
}
void person::addrec(void){
data rec;
char op;
ofstream add("employee.dat",ios::binary);
do{
system("cls");
cout<<"Enter Name of person: ";
cin>>rec.name;
cout<<"Enter City of person: ";
cin>>rec.city;
rec.mark=' ';
add.write((char*)&rec,sizeof(rec));
cout<<"More Records [Y/N]";
cin>>op;
}
while(op=='y'||op=='Y');
add.close();
}
void person::update(){
data rec;
char nm[15];
long int rn=0, t=0;
fstream update_Rec("employee.dat", ios::binary|ios::in|ios::out);
if(!update_Rec){
cerr<<"File opening error "<<endl;
exit(1);
}
cout<<"Enter Name of person ";
cin>>nm;
while(update_Rec.read((char*)&rec,sizeof(rec))){
if(strcmp(nm,rec.name)==0){
cout<<rec.mark<<rec.name<<"\t"<<rec.city<<endl;
rn=(rn)&sizeof(rec);
update_Rec.seekp(rn);
cout<<"Enter New name of person";
cin>>rec.name;
cout<<"Enter new city of Person";
cin>>rec.city;
update_Rec.write((char*)&rec,sizeof(rec));
update_Rec.close();
t=1;
}
rn++;
}
if(t==0)
cout<<"Record not found"<<endl;
}
void person::disp_all(void){
data rec;
char op;
ifstream disp_all_Rec("employee.dat",ios::binary);
if(!disp_all_Rec){
cerr<<"File opening error";
exit(1);
}
while(!disp_all_Rec.eof()){
disp_all_Rec.read((char*)&rec,sizeof(rec));
cout<<setw(15)<<bodyrec.mark<<rec.name<<setw(15)<<rec.city<<endl;
}
disp_all_Rec.close();
}
void person::display(void){
data rec;
char nm[15];
long int rn=0, t=0;
ifstream display_Rec("employee.dat",ios::binary);
if(!display_Rec){
cerr<<"File opening error";
exit(1);
}
cout<<"Enter name of person: ";
cin>>nm;
while(display_Rec.read((char*)&rec,sizeof(rec))){
if(strcmp(nm,rec.name)==0){
rn=(rn-1)*sizeof(rec);
display_Rec.seekg(rn);
cout<<rec.mark<<"\t"<<rec.name<<"\t"<<rec.city<<endl;
display_Rec.close();
t=1;
}
rn++;
}
if(t==0)
cout<<"Record not found"<<endl;
}
void person::delrec(){
data rec;
char nm[15];
long int rn=0,t=0;
fstream del("employee.dat",ios::in|ios::out);
if(!del){
cerr<<"File opening error"<<endl;
exit(1);
}
cout<<"Enter Name of person";
cin>>nm;
while(del.read((char*)&rec,sizeof(rec))){
if(strcmp(nm,rec.name)==0){
cout<<"Record is : "<<rec.mark<<"\t"<<rec.name<<"\t"<<rec.city<<endl;
if(rec.mark='*'){
cout<<"Record already Marked \n";
t=1;
}
else
{
rn=(rn)*sizeof(rec);
del.seekp(rn);
rec.mark='*';
del.write((char*)&rec,sizeof(rec));
cout<<"\n\n Record is marked for deletion \n";
del.close();
t=1;
}
rn++;
}
if(t==0)
cout<<"Record not found";
}
}
void person::pack(void){
data rec;
char nm[15];
long int rn=0;
ifstream pack_Rec("employee.dat",ios::binary);
ofstream pack_Rec_open("temp.dat",ios::binary);
if(!pack_Rec){
cerr<<"File opening error";
exit(1);
}
while(pack_Rec.read((char*)&rec,sizeof(rec))){
if(rec.mark!='*')
pack_Rec_open.write((char*)&rec,sizeof(rec));
rn++;
}
pack_Rec_open.close();
pack_Rec.close();
remove("employee.dat");
rename("temp.dat","employee.dat");
cout<<"Records are copies";
}
add records and update records are working properly but other functions are not properly?

C++ Program On Elementary Database Operations i.e. Record Management

When i execute the program and select option number 2 it reads the data from the file successfully but when i select the option number 2 for the second time , third time and so on... nothing comes up and it returns back to the menu.
I have tried so many times, same error comes every time. PLEASE HELP. Thanks to all in advance. love all.
#include <fstream>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <iomanip>
#include <iostream>
using namespace std;
//class for database functions
class group
{
private:
struct person {
char flag;
char empcode[5];
char name[10];
int age;
float sal;
}p;
public:
fstream file,t_file;
ifstream fin;
ofstream fout;
group();
void addrec();
void listrec();
void modirec();
void delrec();
void recovrec();
};
//main function
int main()
{
char choice;
group g;
do
{
system("cls");
cout<<"1.Add Records"<<endl;
cout<<"2.List Records"<<endl;
cout<<"3.Modify Records"<<endl;
cout<<"4.Delete A Record"<<endl;
cout<<"5.Recover Deleted Records"<<endl;
cout<<"6.Exit"<<endl;
cout<<"Your choice ?: ";
cin>>choice;
system("cls");
switch(choice)
{
case '1':
g.addrec();
break;
case '2':
g.listrec();
break;
case '3':
g.modirec();
break;
case '4':
g.delrec();
break;
case '5':
g.recovrec();
break;
case '6':
exit(0);
}
} while(choice!=6);
return 0;
}
//default constructor
group::group()
{
file.open("EMP.DAT",ios::in|ios::out|ios::binary);
p.flag=' ';
if(!file)
cerr<<"Unable to open file";
}
//Add records at the end
void group::addrec()
{
char ch;
cout<<"Do You Want To Erase Previous Records ?: ";
cin>>ch;
if(ch=='y'||ch=='Y')
remove("EMP.DAT");
fout.open("EMP.DAT",ios::binary);
fout.seekp(0L,ios::end);
system("cls");
do
{
cout<<"Enter Emp_Code, Name, age, Salary"<<endl;
cin>>p.empcode>>p.name>>p.age>>p.sal;
fout.write((char*)&p,sizeof(p));
cout<<"Add another record ?: ";
cin>>ch;
} while(ch=='y'||ch=='Y');
fout.close();
}
//list all the records
void group::listrec()
{
int j=0;
//position get pointer at beginning
//fin.open("EMP.DAT",ios::binary);
file.seekg(0L,ios::beg);
while(file.read((char*)&p,sizeof(p)))
{
if(p.flag!='*')
{
cout<<"\nRecord N. "<<++j;
cout<<"\nEmp Code: "<<p.empcode;
cout<<"\nName: "<<p.name;
cout<<"\nAge: "<<p.age;
cout<<"\nSalary: "<<p.sal<<endl;
}
}
cin.ignore();
getchar();
}
//modifies a given record from file
void group::modirec()
{
char code[5];
int count=0;
long int pos;
cout<<"Enter Emp Code";
cin>>code;
file.open("EMP.DAT",ios::in|ios::out|ios::binary);
file.seekg(0,ios::beg);
//search an employee
while(file.read((char*)&p,sizeof(p)))
{
//if record is found
if(strcmp(p.empcode,code)==0&&p.flag==' ')
{
//recieve new data
cout<<"Enter new Data: "<<endl;
cout<<"Enter Emp_Code, Name, age, Salary"<<endl;
cin>>p.empcode>>p.name>>p.age>>p.sal;
//position put pointer to overwrite record
pos=count*sizeof(p);
file.seekp(pos,ios::beg);
file.write((char*)&p,sizeof(p));
file.close();
cout<<endl<<"Press Any Key...";
getchar();
return;
}
count++;
}
file.close();
cout<<endl<<"No Employee In File With Code: "<<code;
cout<<endl<<"Press Any Key...";
getchar();
}
//marks a record for deletion
void group::delrec()
{
char code[5];
long int pos;
int count =0;
cout<<"Enter Emp Code";
cin>>code;
file.open("EMP.DAT",ios::in|ios::out|ios::binary);
//position pointer at beginning
file.seekg(0L,ios::beg);
//search an employee
while(file.read((char*)&p,sizeof(p)))
{
//if record is found
if(strcmp(p.empcode,code)==0&&p.flag==' ')
{
p.flag='*';
//position put pointer
pos=count*sizeof(p);
file.seekp(pos,ios::beg);
file.write((char*)&p,sizeof(p));
file.close();
return ;
}
count++;
}
cout<<endl<<"No Employee In File With Code: "<<code;
file.close();
cout<<endl<<"Press Any Key...";
getchar();
}
//unmarkmarks a record
void group::recovrec()
{
char code[5];
long int pos;
int count =0;
cout<<"Enter Emp Code";
cin>>code;
file.open("EMP.DAT",ios::in|ios::out|ios::binary);
//position pointer at beginning
file.seekg(0L,ios::beg);
//search an employee
while(file.read((char*)&p,sizeof(p)))
{
//if record is found
if(strcmp(p.empcode,code)==0&&p.flag=='*')
{
p.flag=' ';
//position put pointer
pos=count*sizeof(p);
file.seekp(pos,ios::beg);
file.write((char*)&p,sizeof(p));
file.close();
return ;
}
count++;
}
file.close();
cout<<endl<<"No Employee In File With Code: "<<code;
cout<<endl<<"Press Any Key...";
getchar();
}

Getting the same output twice when reading a file

I am having a problem with the following program,
#include<iostream>
#include<fstream>
#include<windows.h>
using namespace std;
class student
{
int rollno;
char name[50];
int cls;
int marks;
char grade;
public:
void getdata()
{
cout<<"Enter Roll No.: ";
cin>>rollno;
cout<<"Enter Name: ";
cin>>name;
cout<<"Enter Class: ";
cin>>cls;
cout<<"Enter Marks: ";
cin>>marks;
if(marks>=75)
{
grade='A';
}
if(marks>=60 && marks<75)
{
grade='B';
}
if(marks>=45 && marks<60)
{
grade='C';
}
if(marks>=35 && marks<45)
{
grade='D';
}
if(marks<35)
{
grade='F';
}
}
void display()
{
cout<<"\nRoll No.: "<<rollno;
cout<<"\nName: "<<name;
cout<<"\nClass: "<<cls;
cout<<"\nMarks: "<<marks;
cout<<"\nGrade: "<<grade<<endl;
}
int rno()
{
return rollno;
}
} s1, s2, s3;
void append()
{
fstream fo ("STUDENT.DAT",ios::binary | ios::app | ios::out);
if(!fo)
{
cout<<"CANNOT OPEN FILE!!!!!";
}
else
{
s1.getdata();
fo.write((char*)&s1, sizeof(s1));
}
fo.close();
}
void sdisplay()
{
fstream fi ("STUDENT.DAT",ios::binary | ios::in);
if(!fi)
{
cout<<"\nNO RECORDS !!!!";
}
else
{
while(!fi.eof())
{
fi.read((char*)&s2, sizeof(s2));
if(s2.rno()!='\0')
{
s2.display();
}
}
}
fi.close();
}
void rdisplay()
{
int n, found;
fstream fi ("STUDENT.DAT", ios::in | ios::binary);
if(!fi)
{
cout<<"\nNO RECORDS !!!!";
}
else
{
cout<<"\nEnter Roll No. to be displayed: ";
cin>>n;
while(!fi.eof())
{
fi.read((char*)&s3, sizeof(s3));
if(s3.rno()==n)
{
s3.display();
found=1;
}
}
if(found!=1)
{
cout<<"\nCannot find roll no!!";
}
}
fi.close();
}
int main()
{
char ch='y';
int choice, n;
while(ch=='y' || ch=='Y')
{
cout<<"\n1. Append Data to File";
cout<<"\n2. Display Entire File";
cout<<"\n3. Search & Display record based on Roll No.";
cout<<"\n4. Exit";
cout<<"\n\n Enter your choice (1-4): ";
cin>>choice;
switch(choice)
{
case 1:
append();
break;
case 2:
sdisplay();
break;
case 3:
rdisplay();
break;
case 4:
exit(0);
break;
default:
cout<<"\nWrong Choice !!!!!";
break;
}
cout<<"\n\nDo you want to continue? (Y/N)";
cin>>ch;
}
}
So, After appending the data, When I go to Display the data (option 2 & 3) it outputs the same entry twice.
Append Data to File
Display Entire File
Search & Display record based on Roll No.
Exit
Enter your choice (1-4): 2
NO RECORDS !!!!
Do you want to continue? (Y/N)y
Append Data to File
Display Entire File
Search & Display record based on Roll No.
Exit
Enter your choice (1-4): 1 Enter Roll No.: 23 Enter Name: James Enter
Class: 12 Enter Marks: 85
Do you want to continue? (Y/N)y
Append Data to File
Display Entire File
Search & Display record based on Roll No.
Exit
Enter your choice (1-4): 2
Roll No.: 23 Name: James Class: 12 Marks: 85 Grade: A
Roll No.: 23 Name: James Class: 12 Marks: 85 Grade: A
Do you want to continue? (Y/N)n
Process returned 0 (0x0) execution time : 25.013 s Press any key to
continue.
Can someone help me?
Thanks
eof() won't get set until you read past the end, which won't happen until your 2nd read. That read will do nothing, so it won't overwrite s2, it'll just fail - so you'll end up printing that row again.
The solution is don't loop over eof(). Just loop over read():
while(fi.read((char*)&s2, sizeof(s2)))
{
s2.display();
}

data written in file only in alternate steps

code
#include<iostream>
#include<fstream>
#include<conio.h>
#include<string>
using namespace std;
class student
{
int admno;
char name[20];
// char address[20];
//string name;
public:
void getdata()
{
cout<<"\n\nEnter The Name of The Student ";
//gets(name);
//cin.ignore();
cin>>name;
cout<<"\nEnter The admission no. ";
cin>>admno;
// getch();
}
void showdata()
{
cout<<"\nAdmission no. : "<<admno;
cout<<"\nStudent Name : "<<name<<endl;
//puts(name);
}
void display()
{
//student obj;
ifstream fp1;
fp1.open("student.dat",ios::binary);
while(fp1.read((char*)this,sizeof(*this)))
{
this->showdata();
fp1.read((char*)this,sizeof(*this));
}
fp1.close();
}
void add()
{
ofstream fp2;
fp2.open("student.dat",ios::binary|ios::app);
this->getdata();
fp2.write((char*)this,sizeof(*this));
fp2.close();
}
};
int main()
{
student obj;
//system("cls");
cout<<"\n1. Add new student";
cout<<"\n2. View all student";
cout<<"\n3. Search student";
cout<<"\n4. modify student";
cout<<"\n5. delete student";
cout<<"\n6. Exit";
cout<<"\n\nEnter your choice";
int ch;
cin>>ch;
switch(ch)
{
case 1:
obj.add();
break;
case 2:
obj.display();
//b.viewbook();
break;
default:
cout<<"Enter Valid choice";
}
return 0;
}
problem:
when I enter the data in file, the data is written to the file only in the alternate steps.
at the first run and enter the data it is OK and in second run to add the student, the data isnot written in the file and again in the next step it writes properly and it continues to give proper output in alternate addition.
You should put your switch inside a loop:
bool exitLoop = false;
while(!exitLoop) {
int ch;
cin>>ch;
switch(ch) {
case '1':
obj.add();
break;
case '2':
obj.display();
//b.viewbook();
break;
case '6':
exitLoop = true;
break;
default:
cout<<"Enter Valid choice";
}
}
Also note how to handle character inputs: 1 != '1'

How do I compare a string variable to an array of strings created from a file

Hello Ive been working on a program where I have a file with 3 columns containing both the inauguration year and departure year of a president, along with the name of the president. Im trying to have the user input a president and have the program return the start and stop year. I began by opening the file (which opens correctly) and making 3 arrays, 2 integer arrays and one string array. The program runs but when I press 2 regardless of what name I enter the bool stays false. The file can be found here: http://pastebin.com/8h3BJxGD
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
char junk, x;
int start[100],stop[100],year,i,count=0;
string names[100],president;
ifstream file;
file.open("presidents.txt");
if(file.fail())
cout<<"failed to open file"<<endl;
for(i=0;file>>start[i];i++)
{
file>>stop[i];
file.get(junk);
getline(file,names[i]);
cout<<start[i]<<stop[i]<<names[i]<<endl;
count++;
}
do
{
cout<<"What would you like to know?"<<endl;
cout<<"Press 1 for who was President in what year"<<endl;
cout<<"Press 2 for the years served by a President"<<endl;
cout<<"Press 3 to stop"<<endl;
cin>>x;
if(x=='1')
{
bool valid=false;
cout<<"Enter a year: "<<endl;
cin>>year;
for(i=0;i<count;i++)
{
if(start[i]<=year&&stop[i]>=year)
{
cout<<names[i]<<endl;
cout<<endl;
valid=true;
}
}
if(valid==false)
{
cout<<"Invalid year"<<endl;
cout<<endl;
}
}
if(x=='2')
{
bool valid=false;
cout<<"Enter a President: "<<endl;
cin>>president;
getline(cin,president);
for(i=0;i<count;i++)
{
if(president==names[i])
{
cout<<start[i]<<"-"<<stop[i]<<endl;
cout<<endl;
valid=true;
}
}
if(valid==false)
{
cout<<"Please be more percise"<<endl;
cout<<endl;
}
}
}
while (x!='3');
cin>>junk;
return 0;
}
Here, problem is not with the comparison, but with input string into president variable, try printing president variables value, you will understand the problem.
You need to add following line after reading x.
cin.ignore(); //add this line after cin>>x;
This will remove \n from the input buffer and will not cause any issue while reading president string. You need to take care of such issues while combining use of formatted input (i.e. >>) with unformatted input (i.e. get(), getline() etc).
Below is the modified code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
char junk, x;
int start[100],stop[100],year,i,count=0;
string names[100],president;
ifstream file;
file.open("president.txt");
if(file.fail())
cout<<"failed to open file"<<endl;
for(i=0;file>>start[i];i++)
{
file>>stop[i];
file.get(junk);
getline(file,names[i]);
cout<<start[i]<<stop[i]<<names[i]<<endl;
count++;
}
do
{
cout<<"What would you like to know?"<<endl;
cout<<"Press 1 for who was President in what year"<<endl;
cout<<"Press 2 for the years served by a President"<<endl;
cout<<"Press 3 to stop"<<endl;
cin>>x;
cin.ignore();
if(x=='1')
{
bool valid=false;
cout<<"Enter a year: "<<endl;
cin>>year;
for(i=0;i<count;i++)
{
if(start[i]<=year&&stop[i]>=year)
{
cout<<names[i]<<endl;
cout<<endl;
valid=true;
}
}
if(valid==false)
{
cout<<"Invalid year"<<endl;
cout<<endl;
}
}
if(x=='2')
{
bool valid=false;
cout<<"Enter a President: ";
getline(cin,president);
for(i=0;i<count;i++)
{
if(president==names[i])
{
cout<<start[i]<<"-"<<stop[i]<<endl;
cout<<endl;
valid=true;
}
}
if(valid==false)
{
cout<<"Please be more percise"<<endl;
cout<<endl;
}
}
}
while (x!='3');
cin>>junk;
return 0;
}
Following is the output:
What would you like to know?
Press 1 for who was President in what year
Press 2 for the years served by a President
Press 3 to stop
2
Enter a President: Theodore Roosevelt
1901-1909
if(president==)
if president == what???
Also,
getline(cin,president); //why this line?
if you have already read the file and put into data structure, then just search through the data structure for the name of the president that the user enters...if you find it, keep track of the index as you have done and print out the start[] and stop[] at the same index...