I am doing a small college project where I have to add, edit and search records in/from file using OOP concept. Adding into file is working fine but whenever I try to read from file it is printing in unreadable texts.
Here is full code and output.
main.cpp
#include <iostream>
#include <cstdlib>
#include <fstream>
#define MIN 20
#define MAX 100
#include "student.h"
using namespace std;
void add_student();
void edit_student();
void search_student();
void addToFile(const Student&);
Student* fetchFromFile();
int getFileSize();
void updateFile(Student*);
// Student stud[MAX];
int main()
{
int choice;
system("cls");
system("Color B0");
while(1)
{
cout<<"\n\t\tWhat do you want to do?"<<endl;
cout<<"\t\t----------------------"<<endl;
cout<<"\t\t1-Add student"<<endl;
cout<<"\t\t2-Edit student"<<endl;
cout<<"\t\t3-Search student"<<endl;
cout<<"\t\t4-Quit Program"<<endl;
cout<<"\t\t----------------------"<<endl;
cout<<"Enter your choice: ";
cin>>choice;
switch(choice)
{
case 1:
add_student(); //calling add_student function to add records.
break;
case 2:
edit_student();
break;
case 3:
search_student();
break;
case 4:
return 0;
break;
default:
cout<<"Invalid choice";
break;
}
}
return 0;
}
int Student::id = getFileSize() - 1; //Initialize id equals to size of file
// setData function of class Student definition
void Student :: setData()
{
// taking input from user
cout<<"Enter student roll no in format(1XXX): ";
cin>>roll;
cout<<"Enter student name: ";
cin>>name;
cout<<"Enter stduent date of birth(dd/mm/yy): ";
cin>>dob;
cout<<"Enter stduent phone no: ";
cin>>phone;
cout<<"Enter student address: ";
cin>>address;
stdId = Student::id;
}
void Student :: showData()
{
cout<<stdId<<" ";
cout<<roll<<" ";
cout<<name<<" ";
cout<<dob<<"\t";
cout<<phone<<" ";
cout<<address<<"\n\n";
}
const int Student :: getRoll()
{
return roll;
}
Student& Student::operator = (const Student& newObj)
{
stdId = newObj.stdId;
roll = newObj.roll;
name = newObj.name;
dob = newObj.dob;
phone = newObj.phone;
address = newObj.address;
return *this;
}
void add_student()
{
Student stud;
Student::incrementId();
stud.setData();
addToFile(stud); //adding records to file
system("CLS");
cout<<endl;
cout<<"--------------------------------------------------------------------------------"<<endl;
cout<<"---------------------------Student updated record Table---------------------------------"<<endl;
cout<<"--------------------------------------------------------------------------------"<<endl;
cout<<"ID "<<"Roll "<<"Name "<<"DOB "<<"Phone no "<<"Address\n\n";
cout<<"--------------------------------------------------------------------------------"<<endl;
Student* student = fetchFromFile(); //getting records from file in array of objects
int length = getFileSize(); //getting length of array of objects
for(int i=0; i<(length-1); i++)
{
student[i].showData(); //showing all the data
}
cout<<"--------------------------------------------------------------------------------"<<endl;
cout<<"---------------------------------FINISH-----------------------------------------"<<endl;
cout<<"--------------------------------------------------------------------------------"<<endl;
cout<<"You want to add more?(Y/n): ";
char c;
cin>>c;
if(c=='y' || c=='Y')
{
add_student();
}
else{
system("pause");
}
}
void edit_student(){
//Showing existing record first before editing
cout<<endl;
cout<<"--------------------------------------------------------------------------------"<<endl;
cout<<"---------------------------Student Existing record Table---------------------------------"<<endl;
cout<<"--------------------------------------------------------------------------------"<<endl;
cout<<"ID "<<"Roll "<<"Name "<<"DOB "<<"Phone no "<<"Address\n\n";
cout<<"--------------------------------------------------------------------------------"<<endl;
Student* student = fetchFromFile(); //fetching all records from file
int length = getFileSize();
for(int i=0; i<(length-1); i++)
{
student[i].showData();
}
int idnumber;
cout<<"--------------------------------------------------------------------------------"<<endl;
cout<<"Which ID number your want to edit: ";
cin>>idnumber; //Asking the user at which ID he wants to make a change.
//checking for valid id number
if(idnumber>length || idnumber<0)
{
cout<<"\nInvalid ID Number."<<endl;
}
//showing existing information about that specific record
cout<<"\nExisted information about this record.\n\n";
cout<<"--------------------------------------------------------------------------------"<<endl;
cout<<"ID "<<"Roll "<<"Name "<<"Father\tCell no. "<<"DOB "<<"Address\n\n";
cout<<"--------------------------------------------------------------------------------"<<endl;
student[idnumber].showData();
cout<<"\n\nEnter new data for above shown record.\n\n";
student[idnumber].setData(); //Inputting data for that specific record.
updateFile(student);
cout<<"\n\nRecord updated successfully."<<endl;
cout<<endl;
cout<<"--------------------------------------------------------------------------------"<<endl;
cout<<"---------------------------Updated record Table---------------------------------"<<endl;
cout<<"--------------------------------------------------------------------------------"<<endl;
cout<<"ID "<<"Roll "<<"Name "<<"DOB "<<"Phone no "<<"Address\n\n";
cout<<"--------------------------------------------------------------------------------"<<endl;
for(int i=0; i<(length-1); i++) //Showing updated record Table
{
student[i].showData();
}
}
void search_student(){
Student* student = fetchFromFile();
int fileLenth = getFileSize() - 1;
int searchkey;
cout<<"Enter roll_no of student you want to search: ";
cin>>searchkey; //roll_no as the search key can be entered by user.
for(int i=1; i<fileLenth; i++)
{
if(searchkey==student[i].getRoll()) //checking for roll no
{
student[i].showData();
}
}
cout<<"--------------------------------------------------------------------------------"<<endl;
cout<<"---------------------------------FINISH-----------------------------------------"<<endl;
cout<<"--------------------------------------------------------------------------------"<<endl;
system("pause");
}
//FILE HANDLING
void addToFile(const Student& obj)
{
ofstream fout;
fout.open("records.txt", std::ofstream::app | std::ofstream::binary);
fout.write((char*)&obj, sizeof(obj));
cout<<"Added to file successfully!"<<endl;
fout.close();
}
Student* fetchFromFile()
{
int i=0;
Student obj;
Student* returnObj = new Student[MAX];
ifstream fin;
fin.open("records.txt", std::ifstream::binary);
while(!fin.eof())
{
fin.read((char*)&obj, sizeof(obj));
returnObj[i] = obj;
i++;
}
fin.close();
delete[] returnObj;
return returnObj;
}
int getFileSize()
{
int i=0;
Student obj;
ifstream fin;
fin.open("records.txt", std::ifstream::binary);
while(!fin.eof())
{
fin.read((char*)&obj, sizeof(obj));
i++;
}
fin.close();
return i;
}
void updateFile(Student* student)
{
ofstream fout;
fout.open("records.txt", std::ofstream::binary);
fout.write((char*)&student, sizeof(student));
fout.close();
}
student.h header file
// A student class that hold students attributes like id, name, address and class
// Object of this class will be craeted to store student details
class Student
{
int stdId;
int roll;
std::string name;
std::string dob;
std::string phone;
std::string address;
public:
static int id; //we will increase 'id' whenever student is added to the record
//Member functions declaration
void setData(); //this function will take input from user and set the data to attributes of class
void showData(); //This function will give student data to user when called
static void incrementId()
{
id++;
}
const int getRoll();
Student& operator = (const Student&);
};
Sample output 1
When I add a student object to file
Sample output 2
Reading all records from file
Problem1: Showing garbage value of id.
Sample output 3
Adding another object to file
Sample output 4
Reading all objects from file
Sample output 5
Now went back and chose to edit record
Problem2: See how the records are printing in unreadable form.
Why is this happening. Now if I close program and run it again then it is still showing in unreadable text.
Hope you get my issue. I want to have detailed explanation about this. Also, if I have done other miscellaneous mistakes, please let me know.
Thank you!
Student is too complicated to read with unformatted IO like read and write. In technical terms, it is not Trivially Copyable because it contain std::strings, and string is not Trivially Copyable.
The easiest thing to do is to abandon read and write. Most of your data is string data, so write << and >> overloads for Student and store everything as text.
friend std::ostream & operator<<(std::ostream & out,
const Student & stu)
{
out << stu.stdId << ',' <<stu.roll << ','<< stu.name... <<'\n';
return out;
}
Reading the data back in is a bit trickier
friend std::istream & operator>>(std::istream & in,
Student & stu)
{
std::string line;
if (std::getline(in, line))
{
std::stringstream strm(line);
if (!(strm >> stu.stdId >> comma >> stu.roll >> comma) ||
!std::getline(strm, stu.name, ',') ||
!std::getline(strm, stu.dob, ',') ||
...))
{ // If any read failed, mark the stream as failed so the caller knows.
out.setstate(std::ios_base::failbit);
}
}
return out;
}
First, a minor trick, add a empty constructor for class to initailial all members, integers{0}, and string{}, which will elminiate some unwanted gabages.
Student::Student() :stdId(0), roll(0), name{}, dob{}, phone{}, address{} {;}
Your major problem arised from the function fetchfomrfile() where you delete the fetched Student array, therefore the caller received a undefined data array:
Student* fetchFromFile()
{
int i=0;
Student obj;
Student* returnObj = new Student[MAX];
//reading records from file
fin.close();
delete[] returnObj;// <<<< youe deleted
return returnObj; // and return it as undefined
}
Since you are able to calculate the size of file, I suggest in the caller function:
void search_student(){
// Student* student = fetchFromFile();
Student *student = new Stduent [getFileSize()];
fecchFromFile(student); // use this array in fetch_file
// other things
}
Rewrite fetchFromFile as :
viod fetchFromFile(Stduent *ss)
{
// read file data to array ss[i];
}
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 can I update data from file in c++ without display the old data? I want to delete specific data and update. For example I want to update the name only and another time update gpa only with delete the old gpa?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
int k=0;
string line;
string find;
char name[25];
int id=0;
float gpa=0;
ofstream myfile;
myfile.open("data.txt");
while(k!=3){
cout<<"press 1 for adding data"<<endl;
cout<<"press 2 for update "<<endl;
cin>>k;
if(k==1)
{
cout<<"enter ID "<<endl;
cin>>id;
cout<<"enter Name"<<endl;
cin>>name;
cout<<"enter GPA "<<endl;
cin>>gpa;
myfile<<name<<endl;
myfile<<id<<endl;
myfile<<gpa<<endl<<endl<<endl;
}
if(k==2)
{
cout<<"name u want to update "<<endl;
cin>>find;
ifstream file;
file.open("data.txt");
while (!file.eof() && line!=find)
{
getline(file,line);
}
cout<<"enter ID "<<endl;
cin>>id;
cout<<"enter Name"<<endl;
cin>>name;
cout<<"enter GPA "<<endl;
cin>>gpa;
myfile<<name<<endl;
myfile<<id<<endl;
myfile<<gpa<<endl<<endl<<endl;
}
if(k==3){
myfile.close();
}
}
return 0;
}
First you have to copy all the other records to a temporary file eg. temp.txt and then delete the old file data.txt and rename temp.txt to data.txt. Now write the new record to file data.txt.
code:
if(k==2)
{
cout<<"name u want to update "<<endl;
cin>>find;
ifstream myfile2; //for reading records
myfile2.open("data.txt");
ofstream temp;
temp.open("temp.txt");
while (getline(myfile2, line))
{
if (line != find)
temp << line << endl;
}
myfile2.close();
temp.close();
remove("data.txt");
rename("temp.txt", "data.txt");
//Now add new Record to file
cout<<"enter ID "<<endl;
cin>>id;
cout<<"enter Name"<<endl;
cin>>name;
cout<<"enter GPA "<<endl;
cin>>gpa;
ofstream myfile;
myfile.open("data.txt", ios::app | ios::out);
myfile<<name<<endl;
myfile<<id<<endl;
myfile<<gpa<<endl<<endl<<endl;
}
Line by line read old file and copy lines to a new file. When you find the line which you want to update, change it with your line and copy it to the new file. When you reach EOF, delete old file and rename new file with the name of old file.
It will be something like that:
int replace_line(const char *fname, const char *oldline, const char* newline)
{
int done = 0;
/* Open templorary file */
FILE *newfp = fopen("file.tmp", "a");
if (newfp != NULL)
{
/* Open exiting file */
FILE *oldfp = fopen(fname, "r");
if(oldfp != NULL)
{
ssize_t read;
size_t len = 0;
char * line = NULL;
/* Line-by-line read from exiting file */
while ((read = getline(&line, &len, oldfp)) != -1)
{
if(strstr(line, oldline) == NULL) fprintf(newfp, "%s", line);
else fprintf(newfp, "%s", newline);
}
/* Clean up memory */
fclose(oldfp);
if (line) free(line);
done = 1;
}
fclose(newfp);
remove(fname);
rename("file.tmp", fname);
return done;
}
return 0;
}
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!
I'm writing a program in C++ and I've been able to get it to compile and start to run how ever when I choose an option the coresponding function that is supposed to be called by a switch-case statement isn't called. Am I missing something in my code?
//The following program framework is given.
//Add the programming logic to complete the assignment.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
//function prototypes should be placed here
//Main must be the first function in the program. Write other functions after it.
int main()
{
char cInput;
string strFileName;
vector<string> vecStudent;
cout<<"Please enter the data file name (with location): ";
cin >> strFileName;
//call a function to read the content of the input file into
//the vector vecStudent
while (true)
{
cout<<"----------------------------------------"<<endl;
cout<<" Student Record - Main Menu "<<endl;
cout<<"----------------------------------------"<<endl;
cout<<" Enter 1 to display ALL students"<<endl;
cout<<" Enter 2 to add a student name"<<endl;
cout<<" Enter 3 to delete a student name"<<endl;
cout<<" Enter 4 to SAVE and quit the program"<<endl;
cout<<"----------------------------------------"<<endl;
cout<<"Enter menu option: ";
cin>>cInput;
switch (cInput)
{
case '1':
//call function display names
void displaynames();
break;
case '2':
void addname();
//call a function add name
break;
case '3':
void deletename();
//call function delete names
break;
case '4':
void saveandquit();
//call function save and quit
return 0;
if( cInput != 1,2,3,4)
cout<<"invalid input"<<endl;
break;
}
}
return 0;
}
int displaynames()
{
ifstream inFile;
ofstream outFile;
string strFileName;
string strFName,strLName;
vector<string> vecStudent;
char line[80];
// open input file
inFile.open(strFileName.c_str());
if (inFile.fail())
{
cout << " Input file error!" << endl;
return -1;
}
while (inFile>>strFName>>strLName)
vecStudent.push_back(strFName+ " "+strLName);
inFile.close();
//display the content of the vector
for(int i =0; i< vecStudent.size();i++)
cout<<vecStudent[i]<<endl;
return 0;
}
int addname()
{
ifstream inFile;
ofstream outFile;
string strFileName;
string strFName,strLName;
vector<string> vecStudent;
char line[80];
//add a new name
cout << endl<< " Enter a new name( First and Last Name):";
cin>>strFName>>strLName;
vecStudent.push_back(strFName+ " "+strLName);
// open output file for writing
outFile.open(strFileName.c_str());
if ( outFile.fail())
{
cout<<" Output file error! Student was not added"<<endl;
return -1;
}
//display the content of the vector
for(int i=0; i<vecStudent.size(); i++)
cout<< vecStudent[i]<<endl;
for(int i=0; i<vecStudent.size();i++)
outFile<<vecStudent[i]<<endl;
outFile.close();
return 0;
}
int saveandquit()
{
ifstream inFile;
ofstream outFile;
string strFileName;
string strFName,strLName;
vector<string> vecStudent;
int i=0;
char line[80];
// open output file for writing
outFile.open(strFileName.c_str());
if ( outFile.fail())
{
cout<<" Output file error!"<<endl;
return -1;
}
//display the content of the vector
for(int i=0; i<vecStudent.size(); i++)
cout<< vecStudent[i]<<endl;
for(int i=0; i<vecStudent.size();i++)
outFile<<vecStudent[i]<<endl;
outFile.close();
cout << " file saved. enter -1 to quit";
cin>> i;
if( i=-1)
return 0;
}
int deletename()
{
ifstream inFile;
ofstream outFile;
string strFileName;
string strFName,strLName;
vector<string> vecStudent;
int namepos = 0;
char line[80];
inFile.open(strFileName.c_str());
if (inFile.fail())
cout <<"Input file error!"<<endl;
//read the names from the file into the vector
while (inFile >> strFName >> strLName)
vecStudent.push_back(strFName+" "+strLName);
inFile.close();
cout <<"\nEnter the name to be deleted (First name and Last name): ";
cin >>strFName >>strLName;
int i=0, pos=-1;
int size = vecStudent.size();
bool found=false;
// use a linear search to find the name in the vecotor of names
while (i < size && !found)
{
if (vecStudent [i] == strFName+" "+strLName)
{
found = true;
cout <<"\nthat name is in the "<<(pos + 1) <<" position in the list\n";
cout <<"Please enter the position in list\n";
cin>> pos;
// use an iterator to delete name from vecStudent. vector.erase requires an iterator. used a while loop to find the name and make sure it was in the
// vector of strings. then the loop displays the position in the vector that the string is. the program asks the user to enter the number position of the name
// from there the user enters the name and the program uses a for loop to find the position and the built in vector.erase to remove the name from the list.
for(int i=0; i ==pos; i++)
{
if(i == pos)
{
vecStudent.erase (vecStudent.begin());
}
}
}
}
return 0;
}
You are actually just declaring functions instead of calling them.
void displaynames();
Declares a function.
displaynames();
Calls a function.
You are calling the functions wrong. It should be
case '1':
//call function display names
displaynames();
break;
case '2':
addname();
//call a function add name
break;
case '3':
deletename();
//call function delete names
break;
case '4':
saveandquit();
To call a function, you just need the function name and the function parameters (which in this case, seem to be none. The way you currently have it is declaring a function rather than calling a function.
In your code block (switch), you're not calling any functions, but rather just declaring them.
...
case '1':
//call function display names
void displaynames();
break;
...
Move the (forward) declarations (void displaynames();) to the top level of your source file (as you're defining the functions after using them), and then call them using the normal function application syntax (displaynames();).
From somewhere on the net:
"A declaration for a function is also called a prototype and it
informs the compiler of your intent to define and to use it. A
definition for a function is the body (code) associated with the
prototype."