writing structure to a text file in c++ - c++

struct student{
char name[20];
char course[20];
int age;
float gpa;
};
using namespace std;
main()
{
ifstream infile;
infile.open("student data.txt");
ofstream outfile;
outfile.open("student data 2.txt");
if(!infile || !outfile)
{
cout << "error opening or creating file" << endl;
exit(1);
}
student stu[2];
infile.seekg(0, ios::beg);
while(!infile.eof())
{
int i;
for(i=0; i<=2; i++)
{
infile >> stu[i].name;
infile >> stu[i].course;
infile >> stu[i].age;
infile >> stu[i].gpa;
}
}
outfile.seekp(0, ios::beg);
int i =0;
while(i<3)
{
outfile << stu[i].name << endl;
outfile << stu[i].course << endl;
outfile << stu[i].age << endl;
outfile << stu[i].gpa << endl;
i++;
}
infile.close();
outfile.close();
}
I am trying to figure out why this code is not working... its not giving any compilation error but when i run the application it stops working.it says rough.exe (app name) is not working. can anyone help :(

Alright, so this is fortunately a very simple solution! The problem you are facing is related to memory management. This line is causing you all the trouble:
student stu[2];
AND
int i =0;
while(i<3)
Basically, you're initializing 2 structs (indexes 0-1) of type student, then expecting to iterate over 3 structs (from index 0-2). When attempting to read in the third struct, you can get a memory access violation error.
So I ran your code with this text in "student data.txt"
nasir CS201 23 3
Jamil CS201 31 4
Faisal CS201 25 3.5
When only two structs were initialized, "student data 2" remained blank. However, when increasing the value to student stu[3];, "student data 2.txt" gave the following output:
nasir
CS201
23
3
Jamil
CS201
31
4
Faisal
CS201
25
3.5
Here is the code I used to create a successful version of your program, with a couple of extra printf's for debugging purposes.
#include <iostream>
#include <fstream>
struct student {
char name[20];
char course[20];
int age;
float gpa;
};
using namespace std;
int main()
{
ifstream infile;
infile.open("student data.txt");
ofstream outfile;
outfile.open("student data 2.txt");
if (!infile || !outfile)
{
cout << "error opening or creating file" << endl;
exit(1);
}
student stu[3]; //NOTE THIS LINE NOW HAS 3 STRUCTS INITIALIZED
infile.seekg(0, ios::beg);
while (!infile.eof())
{
int i;
for (i = 0; i <= 2; i++)
{
infile >> stu[i].name;
infile >> stu[i].course;
infile >> stu[i].age;
infile >> stu[i].gpa;
printf("%s %s %d %f\n", stu[i].name, stu[i].course, stu[i].age, stu[i].gpa);
}
}
outfile.seekp(0, ios::beg);
int i = 0;
while (i<3)
{
outfile << stu[i].name << endl;
outfile << stu[i].course << endl;
outfile << stu[i].age << endl;
outfile << stu[i].gpa << endl;
printf("%s %s %d %f\n", stu[i].name, stu[i].course, stu[i].age, stu[i].gpa);
i++;
}
infile.close();
outfile.close();
return 1;
}
Hope this helps!

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.

string is missing when I read data from a text file in binary mode

I have created a class Scholar with attributes: string name, int id, char grade. Then, I had written the data in text file in binary mode using program P1. I had another program P2 which inserts a new data in between previous data.
It shows data (using program P1) when I initially created the text file with some objects. But, when I inserted a new data (using program P2), the attributes id and grade appears but, the attribute name went missing.
The Scholar class code:
#ifndef SCHOLAR_H
#define SCHOLAR_H
#include <iostream>
#include <cstdio>
using namespace std;
class Scholar {
int id;
string name;
char grade;
public:
void read_data() {
cout << "\nEnter ID: ";
cin >> id;
string temp;
getline(cin, temp);
cout << "Enter name: ";
getline(cin, name);
cout << "Enter grade: ";
cin >> grade;
}
void print_data() {
cout << "\nID: " << id << " | Name: " << name << " | Grade: " << grade;
}
int modify_data();
int _id() {
return id;
}
string _name() {
return name;
}
char _grade() {
return grade;
}
};
#endif // SCHOLAR_H
Program P1:
#include "MyHeaderFiles/Scholar.h"
#include <fstream>
#include <cstdlib>
#include <cctype>
int main() {
system("cls");
Scholar sch;
fstream fs;
fs.open("SchDB.txt", ios::out | ios::in | ios::binary | ios::trunc);
if(!fs) {
cerr << "File not found!";
system("PAUSE");
}
char reply;
do {
sch.read_data();
fs.write((char*) &sch, sizeof(sch));
cout << "Do you want to add another scholar (y/n) : ";
cin >> reply;
} while(tolower(reply) == 'y');
fs.seekg(0);
cout << "\nFile content\n------------" << endl;
while(!fs.eof()) {
fs.read((char*) &sch, sizeof(sch));
if(fs.eof()) break;
sch.print_data();
}
fs.close();
cout << endl;
return 0;
}
The initial image of output when I hadn't inserted any new data:
You can see the names!
Program P2:
#include "MyHeaderFiles/Scholar.h"
#include <fstream>
#include <cstdlib>
int main() {
system("cls");
Scholar sch;
Scholar newSch;
ofstream fout;
ifstream fin;
fout.open("Temp.txt", ios::out | ios::binary);
fin.open("SchDB.txt", ios::in | ios::binary);
char last = 'y';
int pos;
cout << "\nYou have to enter data of a new student." << endl;
newSch.read_data();
fin.seekg(0);
cout << "\nFile content\n------------" << endl;
while(!fin.eof()) {
pos = fin.tellg();
fin.read((char*) &sch, sizeof(sch));
if(sch._id() > newSch._id()) {
fout.write((char*) &newSch, sizeof(newSch));
last = 'n';
break;
} else {
fout.write((char*) &sch, sizeof(sch));
}
}
if(last == 'y') {
fout.write((char*) &newSch, sizeof(newSch));
} else if(!fin.eof()) {
fin.seekg(pos);
while(!fin.eof()) {
fin.read((char*) &sch, sizeof(sch));
if(fin.eof()) break;
fout.write((char*) &sch, sizeof(sch));
}
}
fin.close();
fout.close();
remove("SchDB.txt");
rename("Temp.txt", "SchDB.txt");
fin.open("SchDB.txt", ios::in | ios::binary);
fin.seekg(0);
while(!fin.eof()) {
fin.read((char*) &sch, sizeof(sch));
if(fin.eof()) break;
sch.print_data();
}
fin.close();
cout << endl;
return 0;
}
The later image when I used the program P2 to insert new data:
And, now you can see only the name attribute is missing!
I am using Code::Blocks IDE and GNU GCC Compiler.
Can anybody explain me why the string isn't showing up?

Vector Function program issues

#include<iostream>
#include<string>
#include<fstream>
#include<vector>
using namespace std;
void check(ifstream &iFile)
{
if (!iFile.is_open())
{
cout << "Data file not found!" << endl;
system("pause");
exit(1); // exit the program if the file is not found.
}
}
void readIn(ifstream &iFile, vector<string> &fName, vector<string> &lName, vector<string> &jTitle, vector<string> &eID, vector<double> &hoursWorked, vector<double> &wage, vector<int> &deductions, vector<double> &sPay, string sTemp, double dTemp, int iTemp)
{
while (!iFile.eof())
{
iFile >> sTemp;
fName.push_back(sTemp);
iFile >> sTemp;
lName.push_back(sTemp);
iFile.ignore();
getline(iFile, sTemp);
jTitle.push_back(sTemp);
iFile >> sTemp;
eID.push_back(sTemp);
iFile >> dTemp;
hoursWorked.push_back(dTemp);
iFile >> dTemp;
wage.push_back(dTemp);
iFile >> iTemp;
deductions.push_back(iTemp);
iFile >> dTemp;
sPay.push_back(dTemp);
}
cout << "completed" << endl;
}
int main()
{
ifstream iFile;
iFile.open("data.txt");
check(iFile);
vector<string> fName, lName, eID, eStatus, jTitle;
vector<double> nPay, gPay, oPay, oHours;
vector<double> hoursWorked, wage, sPay;
vector<int> deductions;
// temporary names to pass to the vector
string sTemp; // string temp
double dTemp=0; // double temp
int iTemp=0; // integar temp
readIn(iFile, fName, lName, jTitle, eID, hoursWorked, wage, deductions, sPay, sTemp, dTemp, iTemp);
/* while (!iFile.eof())
{
iFile >> sTemp;
fName.push_back(sTemp);
iFile >> sTemp;
lName.push_back(sTemp);
iFile.ignore();
getline(iFile, sTemp);
jTitle.push_back(sTemp);
iFile >> sTemp;
eID.push_back(sTemp);
iFile >> dTemp;
hoursWorked.push_back(dTemp);
iFile >> dTemp;
wage.push_back(dTemp);
iFile >> iTemp;
deductions.push_back(iTemp);
iFile >> dTemp;
sPay.push_back(dTemp);
}*/
int sizeOf = fName.size();
for (int a = 0; a < sizeOf; a++)
{
cout << fName.size() << " FName " << fName[a] << " LName " << lName[a] << " JobTitle " << jTitle[a] << endl;
cout << "EmployeeID " << eID[a] << " Hours Worked " << hoursWorked[a] << " Hourly Wage " << wage[a] << endl;
cout << "Deductions " << deductions[a] << " Salary Pay " << sPay[a] << endl;
}
system("pause");
return 0;
}
I'm running into an issue where my function will not do anything. It will compile, but there is no output. The thing is when I take out the vector sPay from all the parts it works perfectly fine. Any suggestions as to why that one part isn't working? From my limited knowledge it should work perfectly fine, however I can't figure out what would be causing this.
My example text file is
Alan
WakeField
IT GUY
T2034
40
15
1
Hourly
0.00
Your input file does not match your reading code. There are 9 values in the file that you have shown, but your code is attempting to read only 8 values.
When readIn() gets to this code:
iFile >> dTemp;
sPay.push_back(dTemp);
It attempt to read a double but the file has Hourly instead, so the read fails.
So, either remove the Hourly line from the file, or else add a call to iFile >> sTemp to read that line.
Also, the parameters string sTemp, double dTemp, and int iTemp should be declared as local variables instead of as input parameters.
Also, readIn() is not doing any error handling. Your main() code makes an invalid assumption that the vector of first names exactly matches the size of the other vectors, but readIn() does not guarantee that.
And lastly, checking eof() before you have read anything is wrong. The stream's eofbit flag is not updated until a read operation attempts to read past EOF.
You should consider re-writing this code. For example, try something more like this:
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
struct Employee
{
std::string fName;
std::string lName;
std::string title;
std::string eID;
double hoursWorked;
double wage;
int deductions;
std::string wageType;
double sPay;
Employee() :
hoursWorked(0), wage(0), deductions(0), sPay(0)
{
}
};
void check(std::ifstream &iFile)
{
if (!iFile.is_open())
{
std::cout << "Data file not found or unable to open!" << std::endl;
std::system("pause");
exit(1); // exit the program.
}
}
void readIn(std::ifstream &iFile, std::vector<Employee> &employees)
{
std::ios_base::iostate oldstate = iFile.exceptions();
iFile.exceptions(std::ifstream::badbit | std::ifstream::failbit);
try
{
do
{
Employee emp;
iFile >> emp.fName;
iFile >> emp.lName;
std::getline(iFile, emp.title);
iFile >> emp.eID;
iFile >> emp.hoursWorked;
iFile >> emp.wage;
iFile >> emp.deductions;
iFile >> emp.wageType;
iFile >> emp.sPay;
employees.push_back(emp);
}
while (!iFile.eof());
}
catch (const std::ios_base::failure &)
{
std::cout << "Data file corrupted!" << std::endl;
std::system("pause");
exit(1); // exit the program.
}
iFile.exceptions(oldstate);
std::cout << "completed" << std::endl;
}
int main()
{
std::ifstream iFile("data.txt");
check(iFile);
std::vector<Employee> employees;
readIn(iFile, employees);
int sizeOf = employees.size();
for (int a = 0; a < sizeOf; a++)
{
std::cout << "FName " << employees[a].fName
<< " LName " << employees[a].lName
<< " JobTitle " << employees[a].title
<< std::endl;
std::cout << "EmployeeID " << employees[a].eID
<< " Hours Worked " << employees[a].hoursWorked
<< " << employees[a].wageType << " Wage " << employees[a].wage
<< std::endl;
std::cout << "Deductions " << employees[a].deductions
<< " Salary Pay " << employees[a].sPay
<< std::endl;
std::cout << std::endl;
}
std::system("pause");
return 0;
}
Alternatively, since your data is line-based, you should use std::getline() to read each line, and then use std::istringstream to parse values:
void readIn(std::ifstream &iFile, std::vector<Employee> &employees)
{
std::string sTemp;
std::ios_base::iostate oldstate = iFile.exceptions();
iFile.exceptions(std::ifstream::badbit | std::ifstream::failbit);
try
{
do
{
Employee emp;
std::getline(iFile, emp.fName);
std::getline(iFile, emp.lName);
std::getline(iFile, emp.title);
std::getline(iFile, emp.eID);
std::getline(iFile, sTemp);
if (!(std::istringstream(sTemp) >> emp.hoursWorked))
iFile.setstate(std::ifstream::failbit);
std::getline(iFile, sTemp);
if (!(std::istringstream(sTemp) >> emp.wage))
iFile.setstate(std::ifstream::failbit);
std::getline(iFile, sTemp);
if (!(std::istringstream(sTemp) >> emp.deductions))
iFile.setstate(std::ifstream::failbit);
std::getline(iFile, emp.wageType);
std::getline(iFile, sTemp);
if (!(std::istringstream(sTemp) >> emp.sPay))
iFile.setstate(std::ifstream::failbit);
employees.push_back(emp);
}
while (!iFile.eof());
}
catch (const std::ios_base::failure &)
{
std::cout << "Data file corrupted!" << std::endl;
std::system("pause");
exit(1); // exit the program if the file is corrupted.
}
iFile.exceptions(oldstate);
std::cout << "completed" << std::endl;
}
I went derp for a moment. I forgot to read in the hourly or salaried before going to salary pay.

get string array from text list c++

my text file was like
123456123456
Jason
uk
012456788
1000
456789456789
david
uk
012456788
1000
i'm trying to get the data from a text file and save it into arrays
however when i want to store the data from the text file into array it loop non-stop.
what should i do ?
the problem exiting in looping or the method i get the data from text file ?
code:
#include <iostream>
#include <fstream>
using namespace std;
typedef struct {
char acc_no[12];
char name[30];
char address[50];
char phone_no[12];
double balance;
} ACCOUNT;
//function prototype
void menu();
void read_data(ACCOUNT record[]);
int main() {
ACCOUNT record[31]; //Define array 'record' which have maximum size of 30
read_data(record);
}
//--------------------------------------------------------------------
void read_data(ACCOUNT record[]) {
ifstream openfile("list.txt"); //open text file
if (!openfile) {
cout << "Error opening input file\n";
return 0;
} else {
int loop = -1; //size of array
cout << "--------------Data From File--------------"<<endl;
while (!openfile.eof()) {
if (openfile.peek() == '\n')
openfile.ignore(256, '\n');
openfile.getline(record[++loop].acc_no, 12);
openfile.getline(record[loop].name, 30);
openfile.getline(record[loop].address, 50);
openfile.getline(record[loop].phone_no, 12);
openfile >> record[loop].balance;
}
openfile.close(); //close text file
for (int i = 0; i <= loop + 1; i++) {
cout << "Account " << endl;
cout << "Account No. : " << record[i].acc_no << endl;
cout << "Name : " << record[i].name << endl;
cout << "Address : " << record[i].address << endl;
cout << "Phone Number : " << record[i].phone_no << endl;
cout << "Balance : " << record[i].balance << endl;
}
}
}
UPDATE:
The OP didn't properly cite the correct format in his data file. This answer is only valid up until the last iteration.
Don't use .eof() - that's more applicable to when you want to open the file and read it by characters.
A better way would be to use the insertion operator >> as follows:
#define ARR_SIZE 31
ACCOUNT temp;
ACCOUNT record[ARR_SIZE];
int i=0;
while(i < ARR_SIZE) {
openfile >> temp.acc_no >> temp.name >> temp.address >> temp.phone_no >> temp.balance;
record[i] = temp;
i++;
}
Of course, even better is to use std::string to hold the values from the input file, in addition to using std::vectors instead of arrays.