Little confusion in both write() and read() - c++

Below program take three details of family members i.e name,age and occupation. Stores them in txt file.
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <fstream>
using namespace std;
class Dewan_Family
{
char name[50]; // array for name of the family member
int age; // integer for age of the family member
char oc[50]; // array for occupation of family member
public:
void getdata(); // This func. to collect information
void displaydata(); // This func to display information
};
void Dewan_Family::getdata() // creating func. to get family members info
{
cout << "Enter the Name of the Family member: "; cin.getline(name,50);
cout << "Enter the Age of the member: ";
cin >> age;
cin.ignore();
cout << "Enter the occupation of the member: "; cin.getline(oc,50);
}
void Dewan_Family::displaydata() // creating func. to display info
{
cout << "Name of the Dewan family's member: " << name << endl;
cout << "Age of the member: " << age << endl;
cout << "Occupation of the member: " << oc << endl;
}
int main()
{
Dewan_Family obj[5]; // created object array of class Dewan_Family
fstream file; // created object to handle file
file.open("family.txt", ios_base::app | ios_base::in); // created and attached file with the object.
char ch;
int choice; int j=0;
cout << "Main Menu ! Choose any option 1-3.\n";
cout << "1. To add Members\n";
cout << "2. To Display all Members\n";
cout << "3. Exit\nChoice: ";
cin >> choice;
cin.ignore();
cout << "\n";
switch(choice)
{
case 1: ch='y';
do{
obj[j].getdata();
file.write((char*)&obj[j],sizeof(obj[j]));
j++;
cout << "Data added successfully !.\nDo you want to continue to add: y or n: ";
cin >> ch;
}while(ch =='y' || ch == 'Y');
break;
case 2: file.seekg(0);
while(file)
{
file.read((char*)&obj[j],sizeof(obj[j]));
obj[j].displaydata();
j++;
}
break;
case 3: exit(1);
};
return 0;
}
My question is as follow:-
1) This little program successfully write data(with write function) to family.txt file. But when I see data by opening this family.txt file, data appears in weird form.
for example if I enter below details
Name = Ashok Dewan
Age = 25
occupation = job
then data in the text file is like this
Ashok #{}#1.^.36 .. ) job#..#...
2) when I read data(with read func.) It display like below
Name of the Dewan family's member: Ashok Dewan
Age of the member: 25
Occupation of the member: Job
Name of the Dewan family's member: ##$8&
Age of the member: 42565571
Occupation of the member: {...&6^
It displays other data also which I did not enter. I don't know Why it is showing extra data. Is this because write() and Read() use binary mode also by default? Please check this code at your end.
I am using latest codeblocks
Please help me to understand this behaviour?

In your code you are not checking if read is successful before using it, so the last obj created from a failed read. a possible fix is checking before serializing to an object:
case 2: file.seekg(0);
while(file)
if(file.read((char*)&obj[j],sizeof(obj[j]))){
obj[j].displaydata();
j++;
}
break;
Another solution might be to change the while statement as follows:
case 2: file.seekg(0);
while(file.read((char*)&obj[j],sizeof(obj[j])))
{
obj[j].displaydata();
j++;
}
break;

Related

i made c++ code where its need to pass structure pointer in a function

i got confused about the structure when i need to to pass the value in a function
#include <iostream>
using namespace std;
struct student
{
int studentID;
char studentName[30];
char nickname[10];
};
void read_student(struct student *);
void display_student(struct student *);
int main()
{
student *s;
//struct student *ps;
read_student(s);
display_student(s);
}
void read_student(struct student *ps)
{
int i;
for (i = 0; i <= 2; i++)
{
cout << "Enter the studentID : ";
cin >> ps->studentID;
cout << "Enter the full name :";
cin.ignore();
cin >> ps->studentName;
cout << "Enter the nickname : ";
cin.ignore();
cin >> ps->nickname;
cout << endl;
}
}
void display_student(struct student *ps)
{
int i;
cout << "student details :" << endl;
for (i = 0; i <= 2; i++)
{
cout << "student name : " << *ps ->studentName << " (" << &ps ->studentID << ")" << endl;
ps++;
}
}
its only problem at the variable at line 19 and when i try to edit it will became more problem
student *s;
//struct student *ps;
//struct student *ps;
read_student(s);
display_student(s);
also can someone explain how to transfer pointer value of structure to the function and return it back to the main function
You are suffering from some leftovers from your C-Language time. And, you have still not understood, how pointer work.
A pointer (as its name says) points to something. In your main, you define a student pointer. But it is not initialized. It points to somewhere. If you read data from somewhere, then it is undefined behavior. For writing, it is the same, plus that the system will most likely crash.
So, define a student. And if you want to give it to a sub-function, take its address with th &-operator (this address will point to the student) and then it will work.
You need also to learn abaout dereferencing. Your output statement is wrong.
Last but not least, if you want to store 3 students, then you need an array or some other storage where to put them . . .
In your read function you always overwrite the previously read student and in your display function you show undetermined data.
Please have a look at your minimal corrected code:
#include <iostream>
using namespace std;
struct student
{
int studentID;
char studentName[30];
char nickname[10];
};
void read_student( student*);
void display_student( student*);
int main()
{
student s;
//struct student *ps;
read_student(&s);
display_student(&s);
}
void read_student( student* ps)
{
cout << "Enter the studentID : ";
cin >> ps->studentID;
cout << "Enter the full name :";
cin.ignore();
cin >> ps->studentName;
cout << "Enter the nickname : ";
cin.ignore();
cin >> ps->nickname;
cout << endl;
}
void display_student( student* ps)
{
cout << "student details :" << endl;
cout << "student name : " << ps->studentName << " (" << ps->studentID << ")" << endl;
ps++;
}
And, the commenters are right. You must read a book.

University assignment, cant run program as intended

So im trying to run a program that receives a set data from a file that updates each time the program is run and new data is added. But when i try to run it the program terminates after trying to receive input from user.The full code is as follow, im using devc++ if that matters
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
struct Deets
{
string NameSite[];
string AddressName[];
int numVaccine[];
int numStall[];
string DateVax[];
string ContNum[];
};
void Outputmenu();
int AddData(int,struct Deets V);
void EditData(int,struct Deets V);
void ShowExisting(int,struct Deets V);
void ClearArr(int,struct Deets V);
int main()
{
int i;
ifstream r("Total.txt");
r>>i;
r.close();
Deets V;
ifstream a;
a.open("Data.txt");
for(int c=0;c<=i;c++)
while(a>>V.NameSite[c]>>V.AddressName[c]>>V.numVaccine[c]>>V.numStall[c]>>V.DateVax[c]>>V.ContNum[c]);
a.close();
int menuS;
do
{
Outputmenu();
cout<<"\nPlease choose from 1-4, press 0 to close menu"<<endl;
cin>>menuS;
if (menuS==1)
AddData(i,V);
else if (menuS==2)
EditData(i,V);
else if (menuS==3)
ShowExisting(i,V);
else if (menuS==0)
cout<<"Thank you for your cooperation, We hope to see you soon! \nClosing program..,";
else
cout<<"Error, not within selection"<<endl;
}
while (menuS!=0);
ofstream b("Data.txt");
for(int c=0;c<=i;c++)
while(b<<V.NameSite[c]<<" "<<V.AddressName[c]<<" "<<V.numVaccine[c]<<" "<<V.numStall[c]<<" "<<V.DateVax[c]<<" "<<V.ContNum[c]<<endl);
return 0;
}
void Outputmenu() //instruction about the command for the user
{
cout << " -hello there!- " << endl;
cout << "===================================================================" << endl;
cout << " ***PLEASE CHOOSE ONE OF THE OPTION BELOW*** " << endl;
cout << "===================================================================" << endl;
cout << "\t1. Add Data (about Vaccination Center)" << endl;
cout << "\t2. Edit Data" << endl;
cout << "\t3. Show Existing Data" << endl;
cout << "\t0. Close Program" << endl;
cout << "===================================================================" << endl;
}
int AddData(int c, struct Deets A)
{
bool rq;
int i = c;
cout<<"Enter your company name/ institute name : ";
cin.ignore();
getline(cin,A.NameSite[i]);
cout<<"\n\t\t Safety Measure"<<endl;
cout<<"-Maintain a distance of 1 meter between one other access to vaccine doses.\n"<<"-Have a dedicated toilets for patient\n"<<"-Ability to maintain room temperature between 19 – 25 degrees \n"<<"-Have an adequate place for patients to wait "<<"\n-Have adequate sharps disposal bins, appropriate for the volume of patients, and securely placed and spaced to mitigate the risk of needle stick injuries."<<endl;
cout<<"-Adequate handwashing facilities for staff, and antimicrobial hand sanitizers available.\n"<<"-Store and handle COVID-19 vaccines under proper conditions, including maintaining cold chain conditions and chain of custody at all times in accordance with a EUA or vaccine package insert, manufacturer guidance, and CDC guidance in the Vaccine Storage and Handling Toolkit."<<endl;
cout<<"-Appropriate security provisions to ensure no unauthorized access to vaccine doses."<<endl;
cout<<"\nAre all requirement met? \n1:Yes \n0:No"<<endl;
cin>>rq;
if(rq == 1)
{
cout<<"\nWhere is the location : "<<endl;
cin>>A.AddressName[i];
cout<<"How many vaccines required : "<<endl;
cin>>A.numVaccine[i];
cout<<"How many vaccine stall can a site hold : "<<endl;
cin>>A.numStall[i];
cin.ignore();
cout<<"Date for vaccine to be distributed"<<endl;
getline(cin,A.DateVax[i]);
cin.ignore();
cout<<"Enter your management contact number : "<<endl;
getline(cin,A.ContNum[i]);
cout<<"Certificate for "<<A.NameSite[i]<<endl;
i++;
}
else
{
cout<<"Thanks for the thought. We hope to cooperate with "<<(A.NameSite[i])<<" in the near future\n\n"<<endl;
if(i>0)
{
i = i-1;
}
else
{
i = 0;
}
}
return i;
}
void EditData(int i,struct Deets A)
{
int c,EN,edit=0;
for (int c=0;c<i;c++) //showing all Company/Institute name data
{
cout << c+1 << ". "<<A.NameSite[c]<<endl;
}
cout << "Enter number you would like to edit : "; //asking user to enter which data user want to edit
cin >> EN; //user enter which data they want to edit
c=EN-1;
cout << A.NameSite[c] << "\n" << "Do you want to edit this data? Yes:1 No:0"<<endl; //asking user whether they want to edit Company/Institute name
cin >> edit;
if(edit ==1) //if true, it will change the data
cin >> A.NameSite[c];
cout <<"Total stall : "<< A.numStall[c] << "\n" << "Do you want to edit this data? Yes:1 No:0"<<endl; //asking user whether they want to edit total Company/Institute vaccine stall
cin >> edit;
if(edit ==1) //if true, it will change the data
cin >> A.numStall[c];
cout <<"Adress : " << A.AddressName[c] << "\n" << "Do you want to edit this data? Yes:1 No:0"<<endl; //asking user whether they want to edit Company/Institute's address
cin >> edit;
if(edit ==1) //if true, it will change the data
cin >> A.AddressName[c];
cout << "Contact number : " << A.ContNum[c] << "\n" << "Do you want to edit this data? Yes:1 No:0"<<endl; //asking user whether they want to edit Company/Institute's contact number
cin >> edit;
if(edit ==1) //if true, it will change the data
cin >> A.ContNum[c];
cout << "Total Vaccine : "<< A.numVaccine[c] << "\n" << "Do you want to edit this data? Yes:1 No:0"<<endl; //asking user whether they want to edit total Company/Institute vaccine needed
cin >> edit;
if(edit ==1) //if true, it will change the data
cin >> A.numVaccine[c];
cout << "Date of vaccine : "<< A.DateVax[c]<< "\n" << "Do you want to edit this data? Yes:1 No:0"<<endl; //asking user whether they want to edit Company/Institute's receiving vaccine date
cin >> edit;
if(edit ==1) //if true, it will change the data
cin >> A.DateVax[c];
}
void ShowExisting(int i, struct Deets A) // void of ShowExisting that show the existing data stored in the program
{
for(int c=0; c<i; c++) //array to show all the existing data in the program so far
{
cout << (c+1) << ". "<< endl; //number that show the count of which set of data shown
cout << "Site Name: " << A.NameSite[c] << endl; //show the name of site in appropriate array of turn c
cout << "Address: " << A.AddressName[c] << endl; //show the address of site in appropriate array of turn c
cout << "Amount Vaccine: " << A.numVaccine[c]<< endl; //show the amount of vaccine needed in site in appropriate array of turn c
cout << "Amount Stall: " << A.numStall[c] << endl; //show the amount of stall needed in appropriate array of turn c
cout << "Vaccination Date: " << A.DateVax[c] << endl; //show the vaccination date in appropriate array of turn c
cout << "Contact Num.: " << A.ContNum[c] << "\n" << endl; //show the contact number of the reprsentative from the site in appropriate array of turn c
}
}
The program runs until input when there is no data in the file but when there is data, the program wont even go past
for(int c=0;c<=i;c++)
while(a>>V.NameSite[c]>>V.AddressName[c]>>V.numVaccine[c]>>V.numStall[c]>>V.DateVax[c]>>V.ContNum[c]);
please help as my caffeine brain is fried
*After considering everyone's response ive decided to rework the basis of the program with what everyone taught, Thank you for those who responded
IMHO, I would rewrite/redesign your code rather than debug it.
Let's start by differentiating a single Deet from a container of Deet:
struct Deet
{
string NameSite;
string AddressName;
int numVaccine;
int numStall;
string DateVax;
string ContNum;
};
You can then overload operator>>:
struct Deet
{
//...
friend std::istream& operator>>(std::istream& input, Deet& d);
};
std::istream& operator>>(std::istream& input, Deet& d)
{
std::getline(input, d.NameSite);
std::getline(input, d.AddressName);
input >> d.numVaccine;
input >> d.numStall;
std::getline(input, d.DateVax);
std::getline(input, d.ContNum);
return input;
}
You could declare a container and input the container like so:
std::vector<Deet> deet_container;
Deet d;
while (input_file >> d)
{
deet_container.push_back(d);
}
BTW, you should always put descriptive variables inside your function declarations. This gives people a better understanding of what the variables are and their positions.
Your function declarations could change:
typedef std::vector<Deet> Deet_Vector;
int AddData(int, Deet_Vector& V);
void EditData(int, Deet_Vector& V);
void ShowExisting(int, Deet_Vector& V);
void ClearArr(int, Deet_Vector& V);
By looking at AddData, the usage of the int first parameter is ambiguous.
Are you adding an int to the container?
Is the int the quantities of items to add to the container?
Likewise with the other functions.
Next, I would add one function at a time to the program, compile and debug, then add another, repeat.
BTW, you can simplify your Outputmenu function:
void Outputmenu()
{
static const char menu_text[] =
" -hello there!-\n"
"===========================================================\n"
" ***PLEASE CHOOSE ONE OF THE OPTION BELOW***\n"
"===========================================================\n"
"\t1. Add Data (about Vaccination Center)\n"
"\t2. Edit Data\n"
"\t3. Show Existing Data\n"
"\t0. Close Program\n"
"============================================================\n"
;
std::cout.write(menu_text, sizeof(menu_text);
}
By using the write method, the text is written as a block and is usually a lot faster than using a lot of operator<<.

how to display records sorted according to roll no in c++ .dat file

This is all my code I want to sort the records when display all students using option 2 in the main menu
this code returning me the data as it was saved means unsorted.
#include<iostream>
#include<fstream>
#include<iomanip>
#include<vector>
using namespace std;
class student
{
int Idnum;
char Name[25];
char Course[30];
int Result;
public:
void getdata();
void showdata() const;
void show_tabular() const;
int getIDNum() const;
};
void student::getdata()
{
cout << "\nEnter student's ID Number: ";//prints Enter student's ID Number
cin >> Idnum;
cout << "\n\nEnter student's Name: ";//prints Enter student's Name
cin.ignore();//to ignore from the input buffer
cin.getline(Name, 25);
cout << "\nEnter student's Course: ";//prints Enter student's Course
cin >> Course;
cout << "\nEnter student's Result: ";//prints Enter student's Result
cin >> Result;
}
void student::showdata() const
{
cout << "\nID Number: " << Idnum;//prints ID Number
cout << "\nName: " << Name;//prints Name
cout << "\nCourse: " << Course;//prints Course
cout << "\nResult: " << Result;//prints Result
}
void student::show_tabular() const
{
cout << Idnum << setw(6) << " " << Name << setw(20) << Course << setw(20) << Result << setw(4) << endl;
}
int student::getIDNum() const
{
return Idnum;
}
void SaveStudent();
void displayAll();
void Searchdisplay(int);
void modifyStudent(int);
void deleteStudent(int);
void DisplayResult();
This is the code for creating a student.dat file if it does not exist here and if will exist then write a new student record but this will not sort the records as I want.
void write_student()//to create students record
{
student st;
ofstream outFile;
ifstream inFile;
outFile.open("student.dat", ios::binary | ios::app);//opens file student.dat
st.getdata();
//cout << st.getIDNum();
if (inFile.seekg(reinterpret_cast<char *> (&st)))
{
}
outFile.write(reinterpret_cast<char *> (&st), sizeof(student));//writes the file
outFile.close();//closes the file
cout << "\n\nStudent record Has Been Created ";
cin.ignore();
cin.get();
}
This is the place where I am showing my student's records but this will show unsorted records and I want it in a sorted way means ascending order by roll no of students.
void display_all()//to display the student record
{
student st;
ifstream inFile;
inFile.open("student.dat", ios::binary);//opens file student.dat
if (!inFile)
{
cout << "File could not be open !! Press any Key...";
cin.ignore();//to ignore from the input buffer
cin.get();//to access the char
return;
}
cout << "\n\n\n\t\tDISPLAY ALL RECORD !!!\n\n";
while (inFile.read(reinterpret_cast<char *> (&st), sizeof(st)))
{
st.showdata(); //function to show data on screen
cout << "\n\n====================================\n";
}
inFile.close();//closes the file
cin.ignore();
cin.get();
}
void display_sp(int n)//to search for student record
{
student st;
ifstream inFile;
inFile.open("student.dat", ios::binary);//opens file student.dat
if (!inFile)
{
cout << "File could not be open !! Press any Key...";
cin.ignore();
cin.get();
return;
}
bool flag = false;//for false condition
while (inFile.read(reinterpret_cast<char *> (&st), sizeof(student)))
{
if (st.getIDNum() == n)
{
st.showdata();
flag = true;
}
}
inFile.close();//closes the file
if (flag == false)
cout << "\n\nrecord not exist";//prints record not exist
cin.ignore();
cin.get();
}
void modify_student(int n)//to modify the record
{
bool found = false;//for false condition
student st;
fstream File;
File.open("student.dat", ios::binary | ios::in | ios::out);//opens the file student.dat
if (!File)
{
cout << "File could not be open !! Press any Key...";
cin.ignore();
cin.get();
return;
}
while (!File.eof() && found == false)
{
File.read(reinterpret_cast<char *> (&st), sizeof(student));//reads the file
if (st.getIDNum() == n)
{
st.showdata();
cout << "\n\nPlease Enter The New Details of student" << endl;
st.getdata();
int pos = (-1)*static_cast<int>(sizeof(st));
File.seekp(pos, ios::cur);
File.write(reinterpret_cast<char *> (&st), sizeof(student));
cout << "\n\n\t Record Updated";
found = true;
}
}
File.close();//closes the file
if (found == false)
cout << "\n\n Record Not Found ";
cin.ignore();
cin.get();
}
void delete_student(int n)//to delete the student record
{
student st;
ifstream inFile;
inFile.open("student.dat", ios::binary);//opens the student.dat file
if (!inFile)
{
cout << "File could not be open !! Press any Key...";
cin.ignore();
cin.get();
return;
}
ofstream outFile;
outFile.open("Temp.dat", ios::out);//to open another file
inFile.seekg(0, ios::beg);
while (inFile.read(reinterpret_cast<char *> (&st), sizeof(student)))
{
if (st.getIDNum() != n)
{
outFile.write(reinterpret_cast<char *> (&st), sizeof(student));
}
}
outFile.close();//to open another file
inFile.close();
remove("student.dat");
rename("Temp.dat", "student.dat");
cout << "\n\n\tRecord Deleted ..";
cin.ignore();
cin.get();
}
int main()
{
char ch;
int num;
cout.setf(ios::fixed | ios::showpoint);
cout << setprecision(2);
do
{
system("cls");
cout << "\t===================================";
cout << "\n\n\t1. CREATE STUDENT RECORD";
cout << "\n\n\t2. DISPLAY ALL STUDENTS RECORDS";
cout << "\n\n\t3. SEARCH STUDENT RECORD ";
cout << "\n\n\t4. MODIFY STUDENT RECORD";
cout << "\n\n\t5. DELETE STUDENT RECORD";
cout << "\n\n\t6. EXIT";
cout << "\n\n\t===================================";
cout << "\n\n\tPlease Enter Your Choice (1-6): ";
cin >> ch;
system("cls");
switch (ch)//uses switch casee
{
case '1': write_student(); break;
case '2': display_all(); break;
case '3': cout << "\n\n\tPlease Enter Student's ID number: "; cin >> num;
display_sp(num); break;
case '4': cout << "\n\n\tPlease Enter Student's ID number: "; cin >> num;
modify_student(num); break;
case '5': cout << "\n\n\tPlease Enter Student's ID number: "; cin >> num;
delete_student(num); break;
case '6': exit(0);;
default: cout << "\a";
}
} while (ch != '6');
return 0;
}
The main difficulty with showing students in sorted order is that your program works by having every function read a file and operate on each student record sequentially. Sorting can only happen when you have all of the data loaded into your program. In order to display a sorted list of students, you need to load all of the student records into your program and put them all in the same container. A std::vector<student> is the simplest container to work with here.
So, I think the overall flow of your program should work like this:
Read the entirety of student.dat and put all student information found there in a container like std::vector<student>.
Sort the container.
Let the user manipulate the records (create, read, update, delete) by modifying the members of the std::vector<student>.
When the user wants to exit, write the contents of the std::vector<student> back to the file students.dat (possibly with an option to quit without saving).
In the next section, suggestions 1 and 2 answer your question while suggestion 3 tells how the rest of your program will need to be changed to work with the first two suggestions.
Some suggestions to do this:
Make it easier to load a student from a file.
Create a method for the student class that takes a std::ifstream& as an argument. That way, after you open a file, you can load all of the student data like this:
int main()
{
ifstream inFile("student.dat");
std::vector<student> all_students;
while(inFile)
{
student st;
st.getData(inFile);
all_students.push_back(st);
}
// continue with program
}
This method will be very similar to the current student::getData() method, but it will skip the text prompts. I also find this way much easier to understand than your reinterpret_cast code that makes me worry about what it actually does. Is student.dat human readable in your current code?
Create a comparison function bool operator<(const student& A, const student& B) for sorting.
This function should return true if the A student should be sorted before B student and false otherwise. Once this method is created, then you can call std::sort(all_students.begin(), all_students.end()) to sort the student list by the criteria defined in that comparison function. The std::sort() function will need to be called after every modification to the student list.
All functions that manipulate student data should get passed the all_students data
It is much easier to work with the student data directly through purpose-written methods rather than doing complicated manipulations of filestream data. For example, if you passed std::vector<student>& to the modify_student() function, it would look like this:
void modify_student(std::vector<student>& all_students, int n)//to modify the record
{
for (auto& st : all_students)
{
if (st.getIDNum() == n)
{
st.showdata();
cout << "\n\nPlease Enter The New Details of student" << endl;
st.getdata();
return;
}
}
cout << "\n\n Record Not Found ";
}
If you are not working in C++11 or later, this is equivalent:
void modify_student(std::vector<student>& all_students, int n)//to modify the record
{
for (size_t i = 0; i < all_students.size(); ++i)
{
student& st = all_students[i];
if (st.getIDNum() == n)
{
st.showdata();
cout << "\n\nPlease Enter The New Details of student" << endl;
st.getdata();
return;
}
}
cout << "\n\n Record Not Found ";
}
This is much simpler since you don't have file-traversal and user input/output hiding the actual logic of the function.
If a function is only displaying data like display_all(), then you should pass the student list as const std::vector<student>& all_students.
There's much more to be done to improve this program, but I think these suggestions should get you started thinking in a more organized way.

How do I access an object out of its block scope?

Hey I am trying to figure out how to access an a object out of the scope of the block. I defined Person personData in the For loop which writes data to the file. And after the loop I wanted to access the object again to update the values on the file but its giving me the error - personData is undefined identifier.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstdlib>
#include "Person.h"
using namespace std;
int main() {
string lastName;
string firstName;
int age;
//file output and creation
ofstream outPerson("nameage.dat", ios::out | ios::binary);
Person randPerson;
randPerson.setLastName("unassigned");
randPerson.setFirstName("");
randPerson.setAge(0);
randPerson.setId(0);
//for loop to initialize the file with 100 records that store values lastName and firstName
for (int i = 0; i < 100; i++) {
outPerson.write(reinterpret_cast<const char*>(&randPerson), sizeof(Person)); //use write to output to file
}
cout << "File Created" << endl;
//file input and termination
ifstream inPerson("nameage.dat", ios::in | ios::out | ios::binary);
//loops through 10 times to input 10 values (RECORD VALUES)
for (int j = 0; j < 2; j++) {
int id = 0;
do {
cout << "Enter a valid id number: (1-100)" << endl;
cin >> id;
} while ((id<1)||(id>100)); //breaks do-while after it receives a valid input
Person personData;
inPerson.seekg((id - 1) * sizeof(Person));
inPerson.read(reinterpret_cast<char*>(&personData), sizeof(Person));
//checks to see if there is already data in that area, if not then proceed to record data onto file
if (personData.getId() == 0) {
cout << "Enter lastname: ";
cin >> lastName;
cout << "Enter firstname: ";
cin >> firstName;
cout << "Enter age: ";
cin >> age;
//sets data for the particular object
personData.setLastName(lastName);
personData.setFirstName(firstName);
personData.setAge(age);
personData.setId(id);
//seek position in file of user-specified record
outPerson.seekp((personData.getId() - 1) * sizeof(Person));
//write user-specified information in file
outPerson.write(reinterpret_cast<const char*>(&personData), sizeof(Person));
cout << "Record inserted" << endl;
}
else {
cout << "There is already data there. Try another ID number" << endl;
}//end if
}//end for loop
int idSearch;
do {
cout << "Enter a ID number: " << endl;
cin >> idSearch;
} while ((idSearch < 1) || (idSearch > 100));
if (personData.getId() != 0) {
cout << "Enter new Last name";
cin >> lastName;
cout << "Enter new first name";
cin >> firstName;
cout << "Enter age";
cin >> age;
//sets data for the particular object
personData.setLastName(lastName);
personData.setFirstName(firstName);
personData.setAge(age);
personData.setId(idSearch);
//seek position in file of user-specified record
outPerson.seekp((personData.getId() - 1) * sizeof(Person));
//write user-specified information in file
outPerson.write(reinterpret_cast<const char*>(&personData), sizeof(Person));
cout << "Record updated" << endl;
}
inPerson.read(reinterpret_cast<char*>(&personData), sizeof(Person));
system("pause");
return 0;
}
I'm assuming the problem is because the object cant be accessed when out of scope. So how would I go about accessing the object from the statement below the for loop. Thank you.
It's one of the core ideas of C++ data model: data is deleted as soon, as it leaves the scope.
For this to work, you'd need to change the scope of personData (for example, move variable definition outside of the loop).
But be cautious using something like that. In the very best case personData would store data left by the last iteration of the loop.

how to read from a binary file and search for a record

I am trying to read from a file and search a particular record based on the employee number entered. I have written the code but every time i search for a record which is already present i am getting the message record not found. Can anyone please point out the error.
My code is:
#include <iostream>
#include <fstream>
using namespace std;
class emp
{
int empno;
char name[20];
char dept[10];
float salary;
public:
void getdata()
{
cout << "Enter the employee number " << endl;
cin >> empno;
cout << "Enter the name : " << endl;
cin >> name;
cout << "Enter the department of the employee : " << endl;
cin >> dept;
cout << "Enter the salary of the employee : " <<endl;
cin >> salary;
}
void display()
{
cout << "Emp No : " <<empno;
cout << endl << "Name : " << name << endl << "Department : " <<dept <<endl
<<"Salary : " << salary <<endl;
}
int getempno()
{
return empno;
}
};
int main()
{
emp obj1;
int eno;
char ch = 'n';
ifstream file1("emp.txt", ios:: in); // this file should already exist
cout << "Enter the employee number to be searched for : " <<endl;
cin >> eno;
while(!file1.eof())
{
file1.read((char *)&obj1, sizeof(obj1));
if(obj1.getempno()==eno)
{
obj1.display();
ch = 'y';
break;
}
}
if(ch =='n')
cout << "Record Not Found !!" << endl;
file1.close();
}
I am using a variable eno in my main function and comparing the eno to the empno returned from the function getempno. If it is equal i am calling the member function display but the display function is not working. I am only getting the message record not found.
Open the stream as binary as said in the title:
ifstream file1("emp.txt", ios:: in | ios::binary); // binary
and also change your loop in order to not test on eof() without having read first:
while (file1.read((char *)&obj1, sizeof(obj1)))
I could test successfully this updated code, by producing a quick and dirty binary file, written with ios::binary set (I don't put the constructor code here):
void produceTest(string file) {
ofstream os(file, ios::out | ios::binary);
emp a(1, "Durand", "IT", 1234.30);
emp b(2, "Dupond", "Finance", 1530.20);
emp c(25, "Chris", "MD", 15.30);
os.write(reinterpret_cast<char*>(&a), sizeof(emp));
os.write(reinterpret_cast<char*>(&b), sizeof(emp));
os.write(reinterpret_cast<char*>(&c), sizeof(emp));
}
If it doesn't work, the problem is with your file. Potential issues could for example be:
the file was written without ios::binary, producting alteration of the structure (ignoring 0, on windows tranforming binary bytes 0x0A into binary 0x0D + binary 0x0A)
the file was written on a system with a different int encoding (big endian vs.little endian
the file was written with a leading unicode BOM
the encoding of the file is not as you thought.