Data doesn`t enter properly in .dat file - c++

#include "stdafx.h"
#include<iostream>
#include<fstream>
using namespace std;
class Motherboards
{
char name[50];
char chip[50];
float price;
public:
void getdata()
{
cout << "Enter name :\n";
cin.getline(name, 50);
cout << "Chip :\n";
cin.getline(chip, 50);
cout << "Price:\n";
cin >> price;
}
void putdata()
{
cout << name << endl;
cout << chip << endl;
cout << price << endl;
}
}M;
int main()
{
long pos;
fstream input("Motherboard.txt", ios::in | ios::out | ios::app);
M.getdata();
pos=input.tellg();
input.seekg(pos);
input.write((char*)&M,sizeof(M));
M.putdata();
return 0;
}
I can`t enter the data properly to the Motherboard.dat or the Motherboard.txt. I have included pictures of when i run the program with one more edit to the above code and the output is not as expected. I am a beginner
so please explain in detail on how to correct it.
Text:
Asus X99 #GAsus Z97 #œFÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
1st Run
2nd Run after edit which i actually want to do

Related

Reading from a file and into a dynamically allocated array of type Student in C++

I thought I had a decent understanding of fstreams and struct's, but for some reason I can't figure out what's wrong with my code. The file I'm reading from starts with an integer 'n' that represents the amount of students in the file, it's then used as the size of the dynamically allocated array of Students.
I go on to read each name, major, and grade from the file into the array of type Student. But for whatever reason, it's only reading the first "line" in the file (as in it reads the first name, major, and grade), and does that n times. I messed around with the code and I believe I've narrowed the problem down to the array not actually being of size n. It correctly reads the first int in the file, as I've printed it out to make sure that's working, and I've tried manually reading in each Student for the array from the file with the same issues.
This is an assignment, so I'm not looking for any straight forward answer, but a nudge in the right direction would be incredibly helpful.
Here's my code:
using namespace std;
struct Student {
string name, major;
double grade;
void display(Student);
void filterByMajor(Student[], int, string);
void filterByGrade(Student[], int, double);
};
int main() {
ifstream inputFile;
Student* students = nullptr;
string filename;
int n;
cout << “Enter an input file to read from: “;
cin >> filename;
inputFile.open(filename);
if (inputFile.fail()) {
cout << “ERROR: Could not open the file.” << endl;
}
else {
inputFile >> n;
students = new Student[n];
for (int i = 0; i < n; i++) {
inputFile >> students[i].name;
inputFile >> students[i].major;
inputFile >> students[i].grade;
}
cout << “ Student info” << endl;
students->display(students[0]);
cout << endl;
students->display(students[3]);
}
delete[] students;
inputFile.close();
return 0;
}
void Student::display(Student s) {
cout << “Name: “ << name << endl;
cout << “Major: “ << major << endl;
cout << “Grade: “ << grade << endl;
}
And the input file I'm reading from:
7
John CS 3.0
Joe Math 2.5
Jane Math 3.7
Mike CS 2.2
Carol CS 3.3
James Math 2.8
Mary CS 3.6
The problem is not with your reading code. That is actually reading the file data just fine. The real problem is in the display code. You are calling display() on the 1st entry in the array each time, and display() is ignoring the Student that is passed to it, instead displaying the data of the Student it is called on, so you see only the data of the 1st entry being printed each time.
Try this instead:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct Student {
string name, major;
double grade;
void display() const;
};
int main() {
ifstream inputFile;
Student* students = nullptr;
string filename;
int n;
cout << “Enter an input file to read from: “;
cin >> filename;
inputFile.open(filename);
if (inputFile.fail()) {
cout << “ERROR: Could not open the file.” << endl;
}
else {
inputFile >> n;
students = new Student[n];
for (int i = 0; i < n; i++) {
inputFile >> students[i].name;
inputFile >> students[i].major;
inputFile >> students[i].grade;
}
cout << “ Student info” << endl;
students[0].display();
cout << endl;
students[3].display();
}
delete[] students;
inputFile.close();
return 0;
}
void Student::display() const {
cout << “Name: “ << name << endl;
cout << “Major: “ << major << endl;
cout << “Grade: “ << grade << endl;
}

File program won't stop displaying garbage values

I am trying to insert object in file and then read the object to display the student data but when It goes to display program just goes in infinite loop and starts displaying 0 which I have initialized in constructor.I am simply not getting what is happening. I am using visual studio 17 just in case anyones wondering. I even tried to create a new file named Student.txt in same directory as the program but it won't work. Can somone explain me what I am doing wrong?
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
//class to handle individual record
class Student
{
public:
char name[20];
int year;
char division;
char address[50];
int rollno;
Student()
{
strcpy_s(name," ");
strcpy_s(address, " ");
rollno = 0;
year = 0;
division = 0;
}
};
class operations
{
public:
void insertdata();
void printg();
};
void operations::insertdata()
{
int n;
cout << "\nEnter how many student data you want to insert:";
cin >> n;
fstream fin;
Student obj;
fin.open("Student.txt", ios::in | ios::out | ios::binary| ios::trunc);
if (!fin)
{
cout<<"\nFILE NOT Opened!";
}
for (int v = 0; v < n; v++)
{
cout << "\nEnter Roll no:";
cin >> obj.rollno;
cout << "\nEnter Name:";
cin.ignore();
cin >> obj.name;
cout << "\nEnter year:";
cin >> obj.year;
cout << "\nEnter division:";
cin >> obj.division;
cout << "\nEnter Address:";
cin.ignore();
cin >> obj.address;
fin.seekp(0, ios::end);
fin.write((char*)&obj, sizeof(obj));
}
fin.close();
}
void operations::printg()
{
Student obj;
fstream fin("Student.txt", ios::in | ios::out | ios::binary);
fin.seekg(0, ios::beg);
fin.read((char*)&obj, sizeof(obj));
if (!fin)
{
cout << "\n FIle doenst exist";
}
while (!fin.eof())
{
cout << "\n" << obj.name;
cout << "\n" << obj.year;
cout << "\n" << obj.division;
}
fin.close();
}
int main() {
operations obj;
obj.insertdata();
obj.printg();
system("pause");
return 0;
}
A few wrong things:
Writing objects like fin.write((char*)&obj, sizeof(obj)); is a bad idea. A compiler may decide to have different padding between members at any moment for your Student objects, so your file format is like a quantum particle: you don't really know how the file was laid out.
strcpy_s takes 3 parameters, not 2. Anyway, do not use them, they are not really portable (even if they are in the C standard).
Your paths are wrong, so the file will not open (as Sam explains in the comment).
Even if you succeeded in opening a file, in operations::printg() you are not reading the file, so you will not get any data.
Why do you have an operations class? I guess it is intended to be expanded in the future, but seems weird. If you do not intend to have state, use a namespace instead.

Displaying content of a file in C++

I've made a program using which we can add records in a file is an
order, but the displaying of the file after adding the record is
not working.
If I add "|ios::app" in "ofstream fo" to open the file in append
mode, the displaying by "fin" is working.
Why is it so? I'm using mingw4.8.1
#include<fstream>
#include<iostream>
#include<stdio.h>
class c{
public:
int r;
char nm[20];
};
using namespace std;
int main()
{
c a,b;
ifstream fi("old.txt",ios::binary);
ofstream fo("new.txt",ios::binary); // if |ios::app is added here, the
// display by fin below is working fine
cout<<"Enter roll\t";
cin>>b.r;
cout<<"Enter name\t";
fflush(stdin);
gets(b.nm);
int w=0;
while(true)
{
fi.read((char *)&a,sizeof(a));
if(fi.eof()) break;
if(b.r<a.r&&w==0)
{
fo.write((char *)&b,sizeof(b));
w++;
}
else
fo.write((char *)&a,sizeof(a));
}
ifstream fin("new.txt",ios::binary); // this is not working of the //ios:: is not added in the ofstream fo
while(true)
{
fin.read((char *)&a,sizeof(a));
if(fin.eof()) break;
cout<<a.r<<endl;
puts(a.nm);
}
return 0;
}
This is the correct code closest to what you want
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct c {
int roll;
string name;
};
int main() {
c a, b;
ifstream fi("old.txt");
ofstream fo("new.txt");
cout << "Enter roll no. and name" << endl;
cin >> b.roll >> b.name;
while (fi >> a.roll >> a.name) {
if (b.roll < a.roll)
fo << b.roll << " " << b.name << endl;
else
fo << a.roll << " " << a.name << endl;
}
fi.close();
fo.close();
ifstream fin("new.txt");
while (fin >> a.roll >> a.name)
cout << a.roll << " " << a.name << endl;
fin.close();
return 0;
}
It is my understanding that if you use ios::app you must also indicate ios::out try ios::app | ios::out | ios::binary and see if that helps.

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.

Passing fstream to a function

I'm trying to pass an fstream to a function which then writes struct to the file. I'm aware that you have to pass the stream by reference, but nothing is being written to the file at runtime. Heres what I have so far:
struct Record
{
char name [16];
char phoneNum [16];
float balance;
};
void newRec (fstream &);
int main()
{
fstream ref;
ref.open("prog2.dat", ios::in | ios::out | ios::app | ios::binary);
if(!ref.fail() )
{
int choice = menu(ref);
system("CLS");
while(choice != 6)
{
choice = menu(ref);
system("CLS");
}
}
else
cout << "Error opening file. " << endl;
return 0;
}
void newRec (fstream& ref)
{
Record rec;
cout << "Enter customer name: ";
cin.ignore();
cin.getline(rec.name, sizeof(rec.name));
cout << "Enter customer phone number: ";
cin >> rec.phoneNum;
cout << "Enter beginning account balance: ";
cin >> rec.balance;
ref.write(reinterpret_cast<char*>(&rec), sizeof(rec));
}
rec being just a 3 member struct. Any ideas why this wouldn't work? I appreciate any help.
Note: I do have to use .write() as opposed to << as per my assignment
If you are using Visual Studio: maybe you are looking in the wrong directory, the file will be created in Projects\Project_Name\Project_Name when debugging, not in Projects\Project_Name\Debug.
Streams work just like cout and cin. You would probably be better off using
ref << rec.name << "," << rec.phoneNum << "," << rec.balance << endl;