File handling in C++ gives .exe stopped working error - c++

I have basic file handling code of reading file named"student.dat" using visual studio.
the output reads the file and displays the result in console but visual studio pops up the dialog as
code:
#include<iostream>
#include<fstream>
#include<conio.h>
#include<string>
using namespace std;
class student
{
int admno;
// char name[20];
string name;
public:
void getdata()
{
cout<<"\n\nEnter The Name of The Student ";
//gets(name);
cin>>name;
getch();
cout<<"\nEnter The admission no. ";
cin>>admno;
// getch();
}
void showdata()
{
cout<<"\nAdmission no. : "<<admno;
cout<<"\nStudent Name : ";
cout<<name;
//puts(name);
}
int retadmno()
{
return admno;
}
};
int main()
{
student obj;
ifstream fp1;
fp1.open("student.dat",ios::binary);
while(fp1.read((char*)&obj,sizeof(obj)))
{
obj.showdata();
}
fp1.close();
return 0;
}

You are allowed to load raw data only to some POD objects. This line is an error:
fp1.read( (char*)&obj,sizeof(obj) );
because student contains std::string. std::string contains a pointer to a memory block which becomes invalid and totally useless after the object is destroyed. It means the data you load to std::string is just a garbage.
I'd think about object serialization. Boost serialization is a good way to start.

You try to store/load an object to a file, which is invalid.
while(fp1.read((char*)&obj,sizeof(obj)))
Objects may contain references to memory (std::string e.g.) that are invalid after loading. You have to provide serialization for your objects or use plain structs without pointers or references to store your data. E.g.:
struct {
int admno;
char[20] name;
}
If you need strings with variable length, you may use a string store:
struct {
int admno;
size_t name_index;
}
std::vector<std::string> names;
To store, iterate over your names and save length and .c_str of each std::string. To read, do it the other way around and read length into n, read n bytes into a buffer and construct a std::string out of the buffer.
You might have a look at http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/index.html

You never call GetData so admno is not instantiated in ShowData

Related

c++ weird characters appear while writing to a file

When i run this code, and open the .dat file in notepad/wordpad it shows some weird characters
#include<iostream>
#include<fstream>
using namespace std;
class Student
{
int rollno;
char name[20];
char div[20];
public:
void accept()
{
cout<<"enter rollno"<<endl;
cin>>rollno;
cout<<"Enter name"<<endl;
cin>>name;
cout<<"Enter div"<<endl;
cin>>div;
}
void write_rec()
{
ofstream f;
f.open("Student.dat",ios::binary|ios::app);
Student s;
s.accept();
f.write((char*)&s,sizeof(s));
f.close();
}
void display()
{
ifstream f;
Student s;
f.open("Student.dat",ios::binary|ios::in);
while(f.read((char*)&s,sizeof(s)))
s.show();
f.close();
}
void show()
{
cout<<rollno<<endl;
cout<<name<<endl;
cout<<div<<endl;
}
};
int main()
{
Student s;
s.write_rec();
s.display();
}
The code is getting compiled and run perfectly but when i open the "Student.dat" file it shows some weird characters
This line:
f.write((char*)&s,sizeof(s));
Is writing the raw binary bytes of your Student object into the file. If that's not the behavior you intended, you'll need to do something else, e.g. translate the member fields of your Student object (in particular the rollno variable, which is an int) into ASCII text strings and write those strings into the file instead.
on both places when you open file:
f.open("Student.dat",ios::binary|ios::app);
and:
f.open("Student.dat",ios::binary|ios::in);
you open as binary. try to remove this option.
as you can see here and here, these are platform specific behaviors.
take a look at this example
EDIT:
and, of course, as Jeremy observed, you have to write meaningful text to your file. on this line:
f.write((char*)&s,sizeof(s));
you are actually writing each byte (as (char*)) of your object. if you understand what you're doing, and that's what you want to observe, than ok. but maybe you should compare both outputs, from this method and from Jeremy's suggestion.

Pointer to a structure in an array of structures

So i need to get code of the structure#1 (e[0]) but i get the following error;
"error: request for member 'get_code' in 'emp1', which is of pointer type 'Employee*' (maybe you meant to use '->' ?)"
i don't really understand how to fix this. Plus, it's an assigment so i'm bound to use structures,and also, i don't know what "->" is, but if it's any operator or something, im not allowed to use it cause we haven't been taught that yet.
(Answers to the similar question suggest using -> so that doesnt work for me.)
i also tried using *(emp1).get_code()
#include <iostream>
#include <string.h>
using namespace std;
struct Employee{
private:
string code;
string name;
float salary;
public:
void set_code(string c){
code=c;
}
void set_name(string n){
name=n;
}
void set_sal(float s){
salary=s;
}
string get_code(){
return code;
}
string get_name(){
return name;
}
float get_sal(){
return salary;
}
};
int main(void) {
Employee e[2],*emp1,*emp2;
string c,n;
float s;
for (int i=0;i<2;i++){
cout<<"Enter code for employee "<<i+1;
cin>>c;
e[i].set_code(c);
cout<<"Enter name for employee "<<i+1;
cin>>n;
e[i].set_name(n);
cout<<"Enter salary for employee "<<i+1;
cin>>s;
e[i].set_sal(s);
}
*emp1=e[0];
cout<<emp1.get_code();
}
First of all, this line is not correct:
*emp1=e[0];
What your line does is assign the structure value 'e[0]' to the structure at pointer 'emp1'. However, the pointer 'emp1' is never initialized, so you'd end up writing in an invalid location.
What you need to write is:
emp1=&e[0];
That will actually set emp1 to the location of 'e[0]'.
Secondly, the symbol '->' is what you use when you want to access a member of a pointer.
In this case you should not write:
cout<<emp1.get_code();
But rather:
cout<<emp1->get_code();
The reason why you need to write that is that 'emp1' is a pointer. Thus, to access its member 'get_code', you need to use the symbol '->'.

File handling in c++ copying data to object of class

#include<iostream>
#include<string>
#include<fstream>
using namespace std;
class telephone
{
string name;
long number;
public :
void getdata();
void display();
};
void telephone :: getdata()
{
cout<<"Enter the name : ";
getline(cin,name);
cout<<"Enter the number : ";
cin>>number;
}
void telephone :: display()
{
cout<<"1. Name : "<<name<<endl;
cout<<"2. Number : "<<number<<endl;
}
int main()
{
fstream f;
telephone p,q;
f.open("dir.txt",ios::out);
p.getdata();
f.write((char*)&p,sizeof(telephone));
f.close();
f.open("dir.txt",ios::in);
while( f.read((char*)&q,sizeof(telephone)))
{
q.display();
}
f.close();
return 0;
}
I have written this code to write and read data from file in class object.It displays the output but shows some error.
OUTPUT :
Enter the name : rahul
Enter the number : 234546
1. Name : rahul
2. Number : 234546
*** Error in `./a.out': double free or corruption (fasttop): 0x08f861a8 ***
Aborted (core dumped)
I have tried by using file extension like .txt,.bin,.dat but it showed the same error.Please help me to remove this error.
Writing a telephone to a file as a binary blob will not work. telephone contains name and name is a std::string. A std::string does not typically contain the string data it represents; it contains a pointer to the string data.
So when you
f.write((char*)&p,sizeof(telephone));
what you actually wrote to the file was not the string data, but a pointer to the string data. This means that
f.read((char*)&q,sizeof(telephone));
reads back p's pointer to q and that means that p and q both point at the same string data. This is bad.
When p or q go out of scope and are destroyed, they destroy name, and name, like a good little std::string, and frees the memory it points at. This leaves the other object containing a std::string pointing at memory that has been freed, and sooner or later that other object will either be used and invoke undefined behaviour or be destroyed and attempt to free the previously freed memory. This is what is meant in the error message by "double free". The same memory has been freed twice.
In your case, if q is deleted before p, q releases the memory that both p and q point at leaving p pointing at an invalid memory location. A few nanoseconds later p is deleted and p cannot free the already freed memory.
To get around this you must ensure the contents of the std::string are written to the file and then read back. This is called serialization.
Typical solutions to this problem are to write the data to the file in a text format with << and read it back with >> (which may require you to implement the << and >> operators for your class)
class telephone
{
string name;
long number;
public :
void getdata();
void display();
friend std::istream & operator<<(std::istream & out, const telephone & tp);
friend std::ostream & operator>>(std::ostream & in, telephone & tp);
};
or add serialization functions to the class
class telephone
{
string name;
long number;
public :
void getdata();
void display();
bool serialize(std::iostream & out);
bool deserialize(std::iostream & in);
};
The writing of these functions is probably the point of this assignment, so I'll stop here. Don't worry. Both are approaches are exceedingly well documented online if you have trouble. I recommend starting with the first option. It is much easier to debug because you can read the text file to see if you got it wrong.

Why I cannot receive a characters in C++

This is my code to receive string.
But I don't know what causes a problem.
Anybody knows?
#include<iostream>
#include<cstring>
using namespace std;
class person{
private:
char name[100];
//char * name;
public:
person(void) : name(){}
person(person& myPerson);
~person(void) {delete []name;}
void read();
void write();
};
person::person(person& myPerson ){
strcpy(name ,myPerson.name);
}
void person::read(){
cout<< "read name from console: " ;
cin >> name;
}
//////// <<---- problem point.
void person::write(){
cout << name << endl;
}
void main(void) {
person p1;
p1.read();
//p1.write();
getchar();
}
//I insert "getchar()" to remain console window for a while
Remove delete []name; from the destructor of person. You should only free memory that is heap allocated, with malloc() or new, and not space that is stack allocated, like your fixed-size array declared char name[100]. This change will fix the memory error you receive when the destructor is executed as the program exits.
Your code has a number of errors or bad style.
First, it's recommend to use C++ standard library facilities as much as possible. So use std::string instead of char[SIZE].
Second, use int main{return 0;} instead of void main{}.
Third, delete [] name; will lead to a memory error. You are freeing stack memory not heap memory.
Last, in my opinion, class names should start with a capital letter (Person).

arrays of structures and file I/O

//i have two errors in my code
#include <iostream>
#include<iomanip>
#include<fstream>
using namespace std;
struct PLAYER
{
string first_name;
string last_name;
};
void showFile(fstream&, PLAYER&); // line 13
int main()
{
const int MAX=21;
PLAYER array[MAX];
ifstream inputFile;
inputFile.open("PlayerNames.txt",ios::in);
if(inputFile)
{
showFile(inputFile, array); // line 22
}else
cout<<"\n\nError opening file";
inputFile.close();
return 0;
}
void showFile(fstream &file, PLAYER &array )
{
int index=0;
int p_num=1;
string lname, fname;
file>>lname>>fname;
while(!file.eof())
{
// array[index].last_name=
cout<<lname<<" "<<fname;
//array[index].first_name=fname;
//array[index].player_number=p_num;
index++;
p_num++;
file>>lname>>fname;
}
// cout<<"\n"<<index;
//cout<<lname<<" "<<fname;
}
This program worked finally untill i put it in functions.
I have two errors in this program
line 22 error: invalid intialization of reference type std:: fstream
line 13 error: in passing argument 1 of void showFile(std:: fstream&, PLAYER&)
An ifstream can't be converted to an fstream, only an istream.
In the documentation you can see basic_ifstream is derived from basic_istream, not basic_fstream.
Make your function:
void showFile(istream&, PLAYER&);
This is actually better in many ways. For one it's correct (c: But also it means you can test it with any input stream rather than just a file stream. It is more loosely coupled and programs to the more abstract interface.
You function declaration at line 13 shows you are passing 1 PLAYER object, not an array. If you want to stay with arrays, search StackOverflow for "[C++] pass array function".
I highly recommend using std::vector as it has easier syntax when passing to functions.