arrays of structures and file I/O - c++

//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.

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.

Simple File processing in C++

Trying to read a record of students with their name and numbers.
Writing to the file seems fine. However, reading from it prints a never-ending output. The statement - while(!file.eof()) - is causing the problem. But it's how I read the remaining person_details. Your help would be greatly appreciated.
#include <iostream>
#include <fstream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::fstream;
using std::string;
using std::ios;
class telephone
{
protected:
string name;
int number;
public:
void getDetails();
void printDetails() const;
};
void telephone:: getDetails()
{
cout<<"Enter name : "; getline(cin,name);
cout<<"Enter number : ";cin>>number;
}
void telephone:: printDetails() const
{
cout<<"Name : "<<name<<endl;
cout<<"Number : "<<number<<endl;
}
int main(int argc, char const *argv[])
{
telephone person;
fstream file("telefile.txt",ios::in | ios::out | ios::binary | ios::app);
if (!file)
{
cout<<"Invalid file name."<<endl;
return 1;
}
//writing
char choice;
do{
cout<<"----------"<<endl;
cout<<"Person : "<<endl;
cout<<"----------"<<endl;
person.getDetails();
file.write(reinterpret_cast<char*>(&person),sizeof(person));
cout<<"Enter one more?";
cin>>choice;cin.ignore();
}while(choice == 'y');
//reading
file.seekg(0);
file.read(reinterpret_cast<char*>(&person),sizeof(person));
while(!file.eof())
{
cout<<"----------"<<endl;
cout<<"Person : "<<endl;
cout<<"----------"<<endl;
person.printDetails();
file.read(reinterpret_cast<char*>(&person),sizeof(person));
}
return 0;
}
Your basic problem is that you're making a binary image of a std::string object, but a string object doesn't contain the character data, only a pointer to it (this is what allows a string to vary in size). So when you read that pointer back in, you'll start accessing whatever is in that memory location now, not what that memory held when you wrote the file. oops. Even worse things will happen when the string destructor runs and tries to free that pointer.
What you should do instead is write person.name.size() to the file, followed by that many bytes starting at &person.name[0]. Then when you read in the size, you can person.name.resize(size_from_file) and then read that many bytes into &person.name[0].
The Standard actually has a formal name for data types you are allowed to take binary images of: trivially copyable. The requirements are set out in section 9 and your telephone type doesn't meet them:
A trivially copyable class is a class that:
has no non-trivial copy constructors,
has no non-trivial move constructors,
has no non-trivial copy assignment operators,
has no non-trivial move assignment operators, and
has a trivial destructor.
The compiler-generated special member functions for telephone are non-trivial because of the std::string member, so instead of meeting all five requirements, you don't meet any of them.
Everyone has mentioned while (!file.eof()). You're not actually doing it wrong, but there is room for improvement.
First, you can catch more errors using while (file.good()) instead. Right now if you have any failure other than EOF, your loop never terminates, which matches your symptom.
Next, streams have a conversion to bool which is equivalent to calling good(), so you can write while (file). Finally, read like most other stream I/O functions returns the original stream, so you can write
while (file.read(buffer, size))
and avoid duplicating the read call both above and inside the loop.
But you didn't fall into the very common trap of checking eof() before doing the read that actually ran into the end. Bravo for that.

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

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

How to declare vector of structure type?

I have a problem with the code below. Here, I want to write a program which will take input from a file and store it in a vector of structure, but when I declare a structure type vector it is showing an error.
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;
struct input
{
char process[10];
int burst_time;
int arrival_time;
}input;
int main()
{
ifstream myfile;
vector<input> store;// problem with initializing vector
myfile.open("input.txt",ios::in);
if(myfile.is_open())
{
while(!myfile.eof())
{
myfile>>input.process;
myfile>>input.burst_time;
myfile>>input.arrival_time;
store.push_back(input);//showing problem in this line also
}
}
myfile.close();
return 0;
}
You have hidden the name input to be an instance of struct input. Un-hide it:
struct intput
{
// as before
};
This is the thing, very simple:
When you declare
struct input
{
char process[10];
int burst_time;
int arrival_time;
} input;
you are defining a struct type named input but also a variable named input, so in the main the compiler gets confused, it doesn't know if you refer to variable or type, so just rename the struct variable declaration and refer to it as its own name like in this:
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;
struct input // Type defined as "input"
{
char process[10];
int burst_time;
int arrival_time;
} input1; // And variable defined as "input1" consider this to be declared in main, to be a local variable.
int main()
{
ifstream myfile;
vector<input> store{};// problem solved referring to type and not variable
myfile.open("input.txt",ios::in);
if(myfile.is_open())
{
while(!myfile.eof())
{
myfile>>input1.process; // Here now the compiler understands that you are referring to the variable and not the type
myfile>>input1.burst_time;
myfile>>input1.arrival_time;
store.push_back(input1);
}
}
myfile.close();
return 0;
}
This way the compiler will not complain.
Consider also always you declare a new type (like your structure) with first character as upper case. Input instead, and variables with first character lower case input to not get confused and avoid this kind of mistakes.

Reading text files c++

i am new to c++ and i'm try to write a code that reads integers of a text file and saves each integer in different variables line by line.
I am having problems with the syntax and how to arrange the code. Basically the text file contains 4 integers per line which values are to be read to the a class planet's coordinates and id as shown below. I know the code beloe is incomplete but this is the first time im programming with c++ and need help. please you do not need to explain this using planets or anything. I just need a general understanding
#include <iostream>
#include <fstream>
using namespace std;
class planet{
public :
float x_coordinates;
float y_coordinates;
float z_coordinates;
int id;
};
planet*generate_planet(istream &fin)
{
planet *x= new planet;
fin >> x->id >> x->x_coordinates >> x->y_coordinates >> x->z_coordinates;
return (x);
}
void report_planet( planet &p)
{
cout<<"planet "<<p.id<<" has coordinates (" << p.x_coordinates<<","<< p.y_coordinates<<","<< p.z_coordinates<<")"<<endl;
}
int main()
{
planet p;
planet *x;
ifstream fin("route.txt");
generate_planet(fin);
report_planet(*x);
return 0;
}
You have some errors in your code.
Note that in this line:
fin>>x->id>>x->x_coordinates>>x->y_coordinates>>x->y_coordinates; You write twice to x->y_coordinate instead of x->z_coordinate.
Also, your void report_planet(planet &p) function receives planet & as argument, but you pass it fin which is of time ofstream
Another thing is you're trying to read a file, not write to one, hence the use of ofstream is wrong, you should use ifstream instead.
Does your code even compile?
Good luck.