Binary structure delete error - c++

This is the whole program. Right now,the delete function does not write to the temp file. I'll try to change str array to string and see if it helps.
The program is supposed to read write edit search and sort binary file with structures.
#include <cstdlib>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include<string>
#include<limits>
#include<iomanip>
#include<stdio.h>
#include <errno.h>
using namespace std;
const int SIZE=40;
char typedef str[SIZE];
char fname[]="c:/solident.dat";
char tname[]="c:/temp.dat";
struct Rec{int id;str lname,fname;};
//prototypes
void menu(string&);
void engine(string&,Rec&,fstream&,fstream&,int,char[],char[]);
void openFile(char[]);
void addRec(Rec&,char[]);
void delAll(char[]);
void listAll(Rec&,fstream &,char[]);
void appRec(Rec&,fstream &,char[]);
void delRec(Rec&,fstream &, fstream &,char[],char []);
void srcRec(Rec&,fstream& ,char[]);
void modRec(Rec &J,fstream &outfile, char fname[]);
void sort();
int main(int argc, char *argv[])
{
string choice;
Rec Student;
fstream infile;
fstream outfile;
do
{
menu(choice);
engine(choice,Student,infile,outfile,SIZE,fname,tname);
} while(choice[0]!='0');
system("PAUSE");
return EXIT_SUCCESS;
}
//function menu
void menu(string &choice)
{
cout<<"\n\n\n\t\t========================";
cout<<"\n\n\t\tMENU \n";
cout<<"\n\t\t========================\n\n";
cout<<"\t\t[1] Open/check file\n";
cout<<"\t\t[2] Add records\n";
cout<<"\t\t[3] Append records\n";
cout<<"\t\t[4] Search for a record\n";
cout<<"\t\t[5] Delete a record\n";
cout<<"\t\t[6] Delete all records\n";
cout<<"\t\t[7] Modify a record\n";
cout<<"\t\t[8] List all records\n";
cout<<"\t\t[9] Sort all records\n";
cout<<"\t\t[0] Exit\n";
cout<<"\n\t\t========================= \n";
cout<<"\t\tYour choice :";
getline(cin,choice);
while (choice[0] !='1' && choice[0] !='2' &&choice[0] !='3' &&choice[0] !='4' &&choice[0] !='5' &&choice[0] !='6' &&choice[0] !='7' &&choice[0] !='8' &&choice[0] !='9' &&choice[0] !='0' )
{
cout<<"\n\t\t"<<choice<<" is invalid!";
cout<<"\n\t\tEnter correct choice: ";
getline(cin,choice);
}
cout<<"\n\t\t========================= \n\n";
}
//function
void engine(string &choice,Rec &J,fstream &infile,fstream &outfile,int SIZE,char fname[],char tname[])
{
switch (choice[0]){
case '1':
{
cout<<"Executing number "<<choice<<":"<<"Open/check file\n"<<endl;
openFile(fname);
break;
}
case '2':
{
cout<<"Executing number "<<choice<<":"<<"Add records\n"<<endl;
addRec(J,fname);
break;
}
case '3':
{
cout<<"Executing number "<<choice<<":"<<"Append records\n"<<endl;
appRec(J,outfile,fname);
break;
}
case '4':
{
cout<<"Executing number "<<choice<<":"<<"Search for a record\n"<<endl;
srcRec(J,infile,fname);
break;
}
case '5':
{
cout<<"Executing number "<<choice<<":"<<"Delete a record\n"<<endl;
delRec(J,infile, outfile,fname,tname);
break;
}
case '6':
{
cout<<"Executing number "<<choice<<":"<<"Delete all records\n"<<endl;
delAll(fname);
break;
}
case '7':
{
cout<<"Executing number "<<choice<<":"<<"Modify a record\n"<<endl;
modRec(J,outfile,fname);
break;
}
case '8':
{
cout<<"Executing number "<<choice<<":"<<"List all records\n"<<endl;
listAll(J,infile,fname);
break;
}
case '9':
{
cout<<"Executing number "<<choice<<":"<<"Sort all records\n"<<endl;
sort();
break;
}
default:exit(0);
}
}
//function
void openFile(char fname[])
{
cout<<"\nOpening file"<<fname<<"..."<<endl;
//confirm if file exists and opens
fstream infile;
fstream outfile;
infile.open(fname,ios::in|ios::binary);
if (infile.is_open())
{
cout<<"File "<<fname<<" exists, and was opened succesfully.";
}
infile.close();
//if fail ask to create
if (infile.fail())
{
cout<<"File does not exist. Create? [Y]/[N]";
char ch;
cin>>ch;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
//if yes then create file
if(ch=='y'|| ch=='Y')
outfile.open(fname,ios::out| ios::binary);
//if not created display error
if (outfile.fail())
{
cout<<"Error: File not created";
}
//else confirm creation of file
cout<<"File "<<fname<<" has been created.\n\n";
outfile.close();
}
}
//function
void addRec(Rec&J,char fname[])
{
fstream outfile;
outfile.open(fname,ios::out|ios::binary|ios::app);
char another[10];
do
{
cout<<"Please enter ID number :";
cin>>J.id;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout<<"\nPlease enter first name: ";
cin.getline(J.fname,SIZE);
cout<<"\nPlease enter lastname: ";
cin.getline(J.lname,SIZE);
outfile.write((char*) &J, sizeof(J));
cout<<"Add another record:[Y]/[N] ";
cin.get(another[0]);
cin.ignore(numeric_limits<streamsize>::max(), '\n');
} while(another[0]=='y'||another[0]=='Y');
cout<<"exiting to main menu.."<<endl;
}
//function
void delAll(char fname[])
{
fstream outfile;
cout<<"\n------------------\n"<<endl;
cout<<"\nDelete all records"<<fname<<"..."<<endl;
cout<<"\nAre you sure you want to delete all records in "<<fname<<" [Y]/[Any key for exit]?"<<endl;
char ch;
cin>>ch;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(ch=='y'||ch=='Y')
{
outfile.open(fname,ios::out|ios::binary|ios::trunc);
outfile.close();
}
else {cout<<"\nExiting to main menu..."<<endl;}
}
//function
void listAll(Rec&J,fstream &infile,char fname[])
{
infile.clear();
infile.open(fname,ios::in|ios::binary);
infile.read((char*)&J,sizeof(J));
cout<<"|=======================================================|"<<endl;
cout<<"| # | ID | FIRST | LAST |"<<endl;
cout<<"|=======================================================|"<<endl;
int count=1;
while(!infile.eof())
{
cout<<"| "<<setw(6)<<left<<count<<left<<"| "<<setw(9)<<J.id<<"| ";
cout<<left<<setw(14)<<J.fname<<"| ";
cout<<left<<setw(19)<<J.lname<<"|"<<endl;
infile.read((char*)&J,sizeof(J));
count=count+1;
cout<<"|-------------------------------------------------------|"<<endl;
}
infile.close();
}
//function
void appRec(Rec &J,fstream &outfile, char fname[])
{
outfile.open(fname,ios::out|ios::binary|ios::app);
outfile.clear();
cout<<"Please enter ID number :";
cin>>J.id;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout<<"\nPlease enter first name: ";
cin.getline(J.fname,SIZE);
cout<<"\nPlease enter lastname: ";
cin.getline(J.lname,SIZE);
outfile.write((char*) &J, sizeof(J));
outfile.close();
}
//----------------------------------------------------
void delRec(Rec&s,fstream &infile, fstream &outfile,char fname[],char tname[])
{
int current, request=1;
infile.open("c:/solident.dat",ios::in|ios::out|ios::binary);
if (!infile.is_open())
cout << "infile not open\n";
outfile.open("c:/temp.dat",ios::out|ios::binary|ios::trunc);
if (!outfile.is_open())
cout << "outfile not open\n";
for (;;)
{
infile.read((char*)&s, sizeof s);
if (infile.eof())
break;
current = s.id;
if (current != request)
outfile.write((char*)&s, sizeof s);
}
infile.close();
outfile.close();
infile.open("c:/temp.dat)",ios::in|ios::binary);
outfile.open("c:/solident.dat)", ios::out|ios::binary|ios::trunc);
for (;;)
{
infile.read((char*)&s, sizeof (s));
if (infile.eof())
break;
outfile.write((char*)&s, sizeof (s));
}
infile.close();
outfile.close();
}
void srcRec(Rec&Job,fstream &infile,char fname[])
{
cout << "Allowing the user to open a specific record.\n";
infile.open(fname, ios::in | ios::binary) ;
if(infile.fail())
{
cout << "Could not access file.\n";
}
else
{
int position; //user's position
//gets user's position
cout << "Please the record you would like to read: ";
cin >> position;
//ignore luki
cin.ignore(numeric_limits<streamsize>::max(), '\n');
//find the specific record, read it, and display it
infile.seekp((position - 1)*sizeof(Job));
infile.read((char*) &Job, sizeof(Job));
cout<<"|===============================================|"<<endl;
cout<<"| ID | FIRST | LAST |"<<endl;
cout<<"|===============================================|"<<endl;
cout<<left<<"| "<<setw(9)<<Job.id<<"| ";
cout<<left<<setw(14)<<Job.fname<<"| ";
cout<<left<<setw(19)<<Job.lname<<"|"<<endl;
}
//clears and closes the file
infile.clear();
infile.close();
}
void modRec(Rec &J,fstream &outfile, char fname[])
{
int position, //user's position
cntr = 0; //marks the current record within the file
cout << "Modifying a record.\n";
//open the two files
outfile.open(fname, ios::out | ios::in | ios::binary);
//get the user's desired position
cout << "please enter the record you would like to modify: ";
cin >> position;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << endl;
if(outfile.fail())
{
cout << "File could not be read.\n";
}
else
{
//find the desired record
outfile.seekp((position - 1)*(sizeof(J)));
//get the user's modification
cout<<"Please enter ID number :";
cin>>J.id;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout<<"\nPlease enter first name: ";
cin.getline(J.fname,SIZE);
cout<<"\nPlease enter lastname: ";
cin.getline(J.lname,SIZE);
//write over the desired record
outfile.write((char*) &J, sizeof(J));
}
//closes the files
outfile.close();
}
void sort()
{
int StructureSize, Idx1, Idx2;
FILE * binaryFile;
binaryFile = fopen("c:/solident.dat","rb+");
Rec Index, IndexTemp;
StructureSize = sizeof(Index);
fseek(binaryFile, 0, SEEK_END);
int fileSize = ftell(binaryFile);
rewind(binaryFile);
for (Idx1 = 0; Idx1 < fileSize; Idx1 += StructureSize)
{
for (Idx2 = 0; Idx2 < fileSize - StructureSize; Idx2 += StructureSize)
{
fread(&Index, StructureSize, 1, binaryFile);
fread(&IndexTemp, StructureSize, 1, binaryFile);
if (Index.id > IndexTemp.id)
{
fseek(binaryFile, -(StructureSize * 2), SEEK_CUR);
fwrite(&IndexTemp, StructureSize, 1, binaryFile);
fwrite(&Index, StructureSize, 1, binaryFile);
fseek(binaryFile, -StructureSize, SEEK_CUR);
}
else
{
fseek(binaryFile, -StructureSize, SEEK_CUR);
}
}
rewind(binaryFile);
}
fclose(binaryFile);
}

I don't know, there seem to be a few issues with this code. Here's just one of them though
int request=1,current;
...
while (!infile.eof())
{
s.id=current;
if (current!=request)
At no point in this code do you give current a value, but you are still using the variable. This is an uninitialised variable which is one reason your code isn't working.
I wonder if you meant to write
current=s.id;
instead? That would make a little more sense.
Try reading the file with a loop like this
infile.open("c:/solident.dat",ios::in|ios::out|ios::binary);
if (!infile.is_open())
cout << "infile not open\n";
outfile.open("c:/temp.dat",ios::out|ios::binary|ios::trunc);
if (!outfile.is_open())
cout << "outfile not open\n";
for (;;)
{
infile.read((char*)&s, sizeof s);
if (infile.eof())
break;
current = s.id;
if (current != request)
outfile.write((char*)&s, sizeof s);
}
infile.close();
outfile.close();
I wouldn't use fail() if I were you. I think it's extremely unlikely you'll detect a genuine read or write failure with it. It's much more likely to be an end of file error, or a failure to open a file.

#john .Thanks!
The first part works, but trying
rename(tempname,destination) does not work:
(the dest file exists)
Although the file temp.dat now contains the records minus the one deleted , the output is not written to the solident.dat file(it remains unchanged)
//So I tried to read every rec from file and write every record to dest file:
infile.open("c:/temp.dat)",ios::in|ios::binary);
outfile.open("c:/solident.dat)", ios::out|ios::binary|ios::trunc);
infile.read((char*)&s, sizeof s);
for (;;)
{
if (infile.eof())
break;
infile.read((char *)&s, sizeof (s));
outfile.write((char*)&s, sizeof (s));
}
infile.close();
outfile.close();
My understanding was, that outfile and infile are pretty straightforward: fstream.open, close , clear and it should work (I thought). It seems though that I'm missing something essential, because the simple delete binary struct function in the program seems to be a hit and miss and I've been going around in circles for a few days: parts of it work, then I add a few lines of code and either a function fails or the whole program fails.I tend to blame it on the compiler or devc++ :) but I'm certain it has to be the code that is invalid!
Thanks for help!

Related

Why is my program printing the last record of a file twice?

I created a simple bank application program to ask a user whether they want to add a bank record to a file or show all the records available. Both these functions are facilitated by write_rec() and read_rec() respectively. But when the function read_rec() is applied, while it does print all the records available in the file(a single file is used to store all the records), for some reason it prints the last record in the file two times instead of just once. It's very frustrating to see everything works so well then this problem pops up out of nowhere. I tried to see where the issue is but for the life of me I just can't find it. Can you guys please help me with this one?
Here's the code:
#include<iostream>
#include<fstream>
#include<cstdlib>
using namespace std;
class account_query
{
char account_number[20];
char firstName[10];
char lastName[10];
float total_Balance;
public:
void set_data();
void show_data();
void write_rec();
void read_rec();
};
void account_query::set_data()
{
cout<<"\nEnter Account Number: ";
cin>>account_number;
cout<<"Enter First Name: ";
cin>>firstName;
cout<<"Enter Last Name: ";
cin>>lastName;
cout<<"Enter Balance: ";
cin>>total_Balance;
cout<<endl;
}
void account_query::show_data()
{
cout<<"Account Number: "<<account_number<<endl;
cout<<"First Name: "<<firstName<<endl;
cout<<"Last Name: "<<lastName<<endl;
cout<<"Current Balance: Rs. "<<total_Balance<<endl;
cout<<"-------------------------------"<<endl;
}
void account_query::write_rec()
{
ofstream outfile;
outfile.open("D:/rec.bin", ios::binary|ios::in|ios::out|ios::app);
set_data();
outfile.write(reinterpret_cast<char *>(this), sizeof(*this));
outfile.close();
}
void account_query::read_rec()
{
ifstream outfile;
outfile.open("D:/rec.bin", ios::binary);
if(!outfile.is_open())
{
cout << "Error! File not found!" << endl;
return;
}
cout << "\n****Data from file****" << endl;
while(outfile.good())
{
outfile.read(reinterpret_cast<char *>(this), sizeof(*this));
show_data();
}
outfile.close();
}
int main()
{
account_query A;
int choice;
cout << "***Account Information System***" << endl;
while(true)
{
cout << "Select one option below";
cout << "\n\t1-->Add record to file";
cout << "\n\t2-->Show record from file";
cout << "\n\t3-->Quit";
cout << "\nEnter you chice: ";
cin >> choice;
switch(choice)
{
case 1:
A.write_rec();
break;
case 2:
A.read_rec();
break;
case 3:
exit(0);
break;
default:
cout << "\nEnter correct choice";
exit(0);
}
}
system("pause");
return 0;
}
And this is the result I get when I try to print the record on the console:
Please help me 🥺
As already pointed out in the comments section, the problem is that the line
while(outfile.good())
will only check whether the stream extraction has already failed. It will not tell you whether the next stream extraction operation will fail or not. It is unable to provide this information.
Therefore, you must check the state of the stream after the attempted stream extraction operation, to see whether it succeeded or not. So you must check the stream state after this line:
outfile.read(reinterpret_cast<char *>(this), sizeof(*this));
It should be checked before you call show_data, because you don't want to call show_data if the stream extraction failed.
The simplest fix would be to change the lines
while(outfile.good())
{
outfile.read(reinterpret_cast<char *>(this), sizeof(*this));
show_data();
}
to the following:
while( outfile.read(reinterpret_cast<char *>(this), sizeof(*this) ) )
{
show_data();
}
This will work because istream::read will return a reference to the stream object outfile and writing
while ( outfile )
is equivalent to
while ( !outfile.fail() )
due to istream::operator bool being called.

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();
}

How Run-Time error from File Handling code can be detected and removed? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
Q :Why is not this code working properly?
I have implemented file handling in C++ language.
I have created a complete file of the car. Through this code, we can store new data, delete old one, search a particular data about the car.The problem is that this code compiles successfully but during runtime, its execution stops and display an error message. I request kindly help me in removing runtime error from this code.
CODE:
#include<iostream>
#include<string.h>
#include<conio.h>
#include<fstream>
using namespace std;
struct car
{
char name[20];
int model;
string color;
int car_id;
string size;
float weight;
int price;
};
void getdata(car&); //function declaration
void showdata(car&); //function declaration
void searchdata(); //function declaration
void deleterecord(); //function declaration
void modify(); //function declaration
void readdata(); //function declaration
void writedata(); //function declaration
int main()
{
char ch;
cout<<"\nEnter w to write record ";
cout<<"\nEnter r to read record";
cout<<"\nEnter m to modify record";
cout<<"\nEnter s to search record";
cout<<"\nEnter d to delete record";
cout<<"\n\nEnter your choice :";
cin>>ch;
switch(ch)
{
case 'w':
{
writedata();
break;
}
case 'r':
{
readdata();
break;
}
case 's':
{
searchdata();
break;
}
case 'd':
{
deleterecord();
break;
}
case 'm':
{
modify();
break;
}
default:
{
cout<<"\nWrong choice";
}
}
return 0;
}
void getdata(car &ccc)
{
cout<<"Please enter name of car :";
cin>>ccc.name;
cout<<"Please enter model number of car:";
cin>>ccc.model;
cout<<"Enter color of car:";
cin>>ccc.color;
cout<<"Enter id number of car:";
cin>>ccc.car_id;
cout<<"Enter size of car :";
cin>>ccc.size;
cout<<"Enter weight of a car :";
cin>>ccc.weight;
cout<<"Enter price of a car :";
cin>>ccc.price;
}
void showdata(car &ccc)
{
cout<<"\nName of car is :";
puts(ccc.name);
cout<<"\nModel number of car is :"<<ccc.model;
cout<<"\nColor of car is :"<<ccc.color;
cout<<"\nID number of car is :"<<ccc.car_id;
cout<<"\nSize of car is :"<<ccc.size;
cout<<"\nWeight of car is :"<<ccc.weight;
cout<<"\nPrice of car is :"<<ccc.price;
}
void writedata()
{
ofstream file;
char ch='y';
car ccc;
file.open("carinformation.dat",ios::binary | ios::out | ios::app);
while(ch=='y'|| ch=='Y')
{
getdata(ccc);
file.write((char*)&ccc,sizeof(ccc));
cout<<"\nDo you want to countine?";
cin>>ch;
}
file.close();
}
void readdata()
{
int count=0;
ifstream file;
car ccc;
file.open("carinformation.dat",ios::binary | ios::in);
if(!file)
{
cout<<"File not found";
exit(0);
}
else
{
file.read((char*)&ccc,sizeof(ccc));
while(!file.eof())
{
showdata(ccc);
file.read((char*)&ccc,sizeof(ccc));
count++;
}
cout<<"Number of records are :"<<count;
}
file.close();
}
void searchdata()
{
car ccc;
ifstream file;
char n_c[20];
cout<<"Enter name of car :";
cin>>n_c;
file.open("carinformation.dat",ios::binary | ios::in);
if(!file)
{
cout<<"File nnot found";
exit(0);
}
else
{
file.read((char*)&ccc, sizeof(ccc));
while(!file.eof())
{
if(strcmp(n_c,ccc.name)==0)
{
showdata(ccc);
}
file.read((char*)&ccc, sizeof(ccc));
}
}
file.close();
}
void modify()
{
car ccc;
fstream file;
char n_c[20];
file.open("carinformation.dat",ios::binary | ios::in | ios::out);
cout<<"\nEnter name of car that should be searched:";
cin>>n_c;
if(!file)
{
cout<<"File not found";
exit(0);
}
else
{
file.read((char*)&ccc,sizeof(ccc));
while(!file.eof())
{
if(strcmp(n_c,ccc.name)==0)
{
file.seekg(0, ios::cur);
cout<<"Enter new record :\n";
getdata(ccc);
int i=file.tellg();
int j=sizeof(ccc);
int k=i-j;
file.seekp(k);
file.write((char*)&ccc, sizeof(ccc));
}
}
}
file.read((char*)&ccc, sizeof(ccc));
file.close();
}
void deleterecord()
{
int count=0;
car ccc;
int c_id;
cout<<"Please enter car id :";
cin>>c_id;
ifstream file;
file.open("carinformation.dat" ,ios::binary| ios::in);
ofstream file2;
file2.open("New carinformation.dat", ios::binary| ios::out);
while(file.read((char*)&ccc,sizeof(ccc)))
{
if(ccc.car_id!=c_id)
{
file2.write((char*)&ccc ,sizeof(ccc));
count++;
}
}
cout<<"Number of records are :"<<count;
file2.close();
count=0;
file2.open("New carinformation.dat", ios::binary| ios::in);
file.read((char*)&ccc,sizeof(ccc));
while(!file.eof())
{
count++;
showdata(ccc);
file.read((char*)&ccc,sizeof(ccc));
}
cout<<"Number of records are :"<<count;
file.close();
file2.close();
remove("carinfomation.dat");
rename("New carinformation.dat", "carinformation.dat");
file.open("carinformation.dat", ios::binary | ios::in);
file.read((char*)&ccc, sizeof(ccc));
while(!file.eof())
{
count++;
showdata(ccc);
file.read((char*)&ccc, sizeof(ccc));
}
cout<<"Number of records are :"<<count;
}
Class car has std::string fields which hold pointers to heap-allocated memory. So saving it to file by writing raw bytes file.write((char*)&ccc,sizeof(ccc)); is not going to work. And, what is more important, reading them later file.read((char*)&ccc, sizeof(ccc)); will fill string objects with invalid pointer values. You need to store fields one by one and read them one by one carefully validating input data.
There is a difference between "string" and "string.h". Delete two characters, ".h" and see if your code works.
<string.h> contains functions like strcpy, strlen for C style null-terminated strings.
<string> contains std::string, std::wstring plus other classes.
You need to initialize your struct, heres an example for your readdata(), look at the changes and figure out how to fix the rest of the program:
void readdata()
{
int count=0;
ifstream file;
car *ccc = new car();
file.open("carinformation.dat",ios::binary | ios::in);
if(!file)
{
cout<<"File not found";
exit(0);
}
else
{
file.read((char*)ccc,sizeof(*ccc));
while(!file.eof())
{
showdata(*ccc);
file.read((char*)ccc,sizeof(*ccc));
count++;
}
cout<<"Number of records are :"<<count;
}
file.close();
}

Output file overwriting incorrectly

This is just to go with my last question, someone asked me to upload the file so I'll cut out all the useless functions and have the main code especially that having to do with the output, this is my 3rd question on stack overflow so I still don't know much about how it works, if you want to answer please check my last (2nd) question for details. Here is the code:
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
const int MAX_SIZE = 1000;
struct Student
{
string studentID;
string firstName;
char midInitial;
string lastName;
};
void menu()
{
cout<<" CLASS ROSTER APPLICATION"<<endl;
cout<<"========================================="<<endl;
cout<<"ADD a student record..................[A]"<<endl;
cout<<"DELETE a student......................[D]"<<endl;
cout<<"EDIT a student record.................[E]"<<endl;
cout<<"INQUIRY about a student...............[I]"<<endl;
cout<<"LIST all students.....................[L]"<<endl;
cout<<"QUIT the system.......................[Q]"<<endl;
}
int linearSearch(const Student roster[], int numStuds, string sID)
{
int i;
for (i=0; i<numStuds; i++)
{
if (roster[i].studentID == sID)
return i;
}
return -1;
}
void selSort(Student roster[], int numStuds)
{
int minIDPos;
Student tempStudRecord;
int i,j;
for (i=0; i<numStuds-1; i++)
{
minIDPos = i;
for (j=i+1; j<numStuds; j++)
{
if (roster[j].studentID < roster[minIDPos].studentID)
minIDPos = j;
}
tempStudRecord = roster[i];
roster[i] = roster[minIDPos];
roster[minIDPos] = tempStudRecord;
}
}
void listStudents(const Student roster[], int numStuds)
{
cout<<"C L A S S R O S T E R"<<endl;
cout<<"Student ID # First Name M.I. Last Name"<<endl;
cout<<"---------------------------------------------"<<endl;
int i2=0; //just a counter.
while (i2<numStuds)
{
cout<<left;
cout<<setw(14)<<roster[i2].studentID<<setw(13)<<roster[i2].firstName;
cout<<roster[i2].midInitial<<". "<<roster[i2].lastName;
cout<<endl;
i2++;
}
cout<<right;
cout<<"---------------------------------------------"<<endl;
cout<<"Enrollment: "<<i2<<endl;
}
int main()
{
Student roster[MAX_SIZE];
fstream inFile;
fstream outFile;
string filename, sID;
Student newStudent;
int numStuds = 0;
char choice;
int i;
cout<<"Enter the name of the data file> ";
cin>>filename;
/** 7. open the data file for input **/
inFile.open(filename.c_str(), ios::in);
if (inFile)
{
/** 8. write a while loop to read the data from the file
into the roster array; the numStuds (number of Students)
must be updated as the records are read from the file.
Also, close the file after its contents are read into the
roster array.
**/
while (!inFile.eof() && numStuds < MAX_SIZE)
{
inFile>>roster[numStuds].studentID>>roster[numStuds].firstName;
inFile>>roster[numStuds].midInitial>>roster[numStuds].lastName;
numStuds++;
}
inFile.close();
}
do
{
cout<<endl;
menu();
cout<<endl;
cout<<"Select an option-> ";
cin>>choice;
cout<<endl;
switch(toupper(choice))
{
case 'A': cout<<"Enter the student ID #> ";
cin>>newStudent.studentID;
cout<<"Enter the student's first name> ";
cin>>newStudent.firstName;
cout<<"Enter the student's middle initial> ";
cin>>newStudent.midInitial;
cout<<"Enter the student's last name> ";
cin>>newStudent.lastName;
addStudent(roster,numStuds,newStudent);
break;
case 'D': /** 9. write code here to remove a student from the roster **/
cout<<"Enter the student ID Number: ";
cin>>sID;
deleteStudent(roster, numStuds, sID);
break;
case 'E': /** 10. write code to edit the record for a student with a specified ID # **/
cout<<"Enter the student ID Number: ";
cin>>sID;
editStudent(roster, numStuds, sID);
break;
case 'I': /** 11. write code to perform an inquiry (obtain full name) on a student with
with a specified ID # **/
cout<<"Enter the student ID Number: ";
cin>>sID;
studentInquiry(roster, numStuds, sID);
break;
case 'L': /** 12. write code to sort and then generate class roster **/
selSort(roster, numStuds);
listStudents(roster, numStuds);
break;
case 'Q': break;
default: cout<<"Invalid menu choice...try again!"<<endl;
}
}while(toupper(choice) != 'Q');
/** 13. open the data file in output mode and error-check to ensure
that it was successfully opened.
**/
outFile.open(filename.c_str(), ios::out);
if (!outFile)
{
cout<<"Unable to open "<<filename<<" for output. "<<endl;
return -1;
}
/** 14. overwrite the data file in the order:
student ID, firstname, middle initial and last name, one record per line.
make sure that you have spaces between the fields.
**/
for (i=0;i<numStuds;i++)
{
outFile<<roster[i].studentID<<" "<<roster[i].firstName<<" ";
outFile<<roster[i].midInitial<<" "<<roster[i].lastName<<endl;
}
/** 15. close the output file **/
outFile.close();
return 0;
}
This here
while (!inFile.eof() && numStuds < MAX_SIZE) {
inFile >> roster[numStuds].studentID >> roster[numStuds].firstName;
inFile >> roster[numStuds].midInitial >> roster[numStuds].lastName;
numStuds++;
}
Will leave the value of numStuds one higher than it should be, as inFile.eof() will only return true once the end of file has been reached, which won't occur until you have actually tried to read past the end of the file.
One way of fixing it would be to change it to
while (numStuds < MAX_SIZE &&
(inFile >> roster[numStuds].studentID >> roster[numStuds].firstName >>
roster[numStuds].midInitial >> roster[numStuds].lastName)
) {
numStuds++;
}
Although you're better off defining a function that reads the struct for you
std::istream& operator>>(std::istream& stream, Student& student)
{
stream >> student.studentID >> student.firstName
>> student.midInitial >> student.lastName;
return stream;
}
Which will work as follows:
while (inFile >> roster[numStuds]) {
numStuds++;
}
As suggested by #JoachimPileborg the following would be even better (once operator>> is defined for your struct):
std::vector<Student> roster;
//...
std::copy(
std::istream_iterator<Student>(inFile),
std::istream_iterator<Student>(),
std::back_inserter(roster)
);