How to read, write parent class & Inherited class's data to a binary file in C++ altogether? [closed] - c++

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed yesterday.
This post was edited and submitted for review 12 hours ago.
Improve this question
I am working on a routine management system. I just thought like this, the binary file will have 8 lines, 1st line for password matching (8 characters fixed, drama for college), rest of the lines will have the timetable for each day and each line no corresponds to the day no.
Now I made 1 TimeTable Class and a Inherited class Period. Timetable holds day no and Period holds all the details of a period like faculty id, time, sub code, etc.
Now, problem is, how can I write & read the whole data to & from the binary file?
Also, how can I display the whole routine like spreadsheet?
I separated the modules as I have also made login & signup features (module) in my code.
To view the full project you can check my GitHub Repo: https://github.com/ArchismanKarmakar/TimeTable-AK
UPDATE:
Well I just made the modules for faculty. After research, I found that saving a whole routine & getting it in formatted form is impossible with binary files. So, I just switched to CSV / TXT files.
Just made the Faculty modules:
I made the facultyId.csv like this:
id,name,age,phone,email,gender
a12,archisman,0000000000,test#test.com,M\n
But I wanted to represent the whole 2D matrix of routine in the CSV file. Is that possible?
Faculty.hh
#ifndef FACULTY
#define FACULTY
#include <iostream>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
#include <set>
#include <map>
#include <cstring>
#include <queue>
#include <stack>
#include <chrono>
#include <random>
#include <functional>
#include <limits>
#include <fstream>
#include <sstream>
#include <filesystem>
#include <./../include/global.hh>
using namespace std;
class Faculty // ABSTRACT CLASS
{
protected:
string id;
string name;
int16_t age;
string phone;
string email;
char gender;
public:
Faculty();
void addFaculty(int16_t minAge = 18, int16_t maxAge = 100);
void removeFaculty();
void editMap();
void fillMap();
};
#endif
Faculty.cpp
#include <iostream>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
#include <set>
#include <map>
#include <cstring>
#include <queue>
#include <stack>
#include <chrono>
#include <random>
#include <functional>
#include <limits>
#include <fstream>
#include <sstream>
#include <filesystem>
#include <./../include/faculty.hh>
#include <./../include/global.hh>
using namespace std;
Faculty::Faculty()
{
id = -1;
}
void Faculty::addFaculty(int16_t minAge, int16_t maxAge)
{
cout << "\nEnter Id: \n";
getline(cin >> ws, id);
if (std::filesystem::exists("./data/" + id + ".csv"))
return void(cout << "Sorry, this Faculty ID is already registered.\n");
cout << "\nEnter name: ";
getline(cin >> ws, name);
cout << "\nEnter age: \n";
cin >> age;
while (age <= 0)
{
cout << "Was that supposed to make any kind of sense?\nEnter again!\n", cin >> age;
if (age < minAge)
return void(cout << "Sorry, person should be at least " << minAge << " years old to be registered.\n");
else if (age > maxAge)
return void(cout << "Sorry, we can't register a person older than " << maxAge << " years.\n");
}
cout << "\nEnter mobile number (with country code): \n";
getline(cin >> ws, phone);
cout << "\nGender (M = Male || F = Female): \n";
cout << "\nEnter email: \n";
getline(cin >> ws, email);
cin >> gender;
while (gender != 'M' && gender != 'F')
cout << "M or F?\n", cin >> gender;
fstream f;
string path = "./data/" + id + ".csv";
f.open(path, ios::in);
// `le first line conataining column headers:
// f << "Id,Name,age,phone,email,gender\n";
// for (auto i : Faculty::appointmentsList)
f << id << name << "," << age << "," << phone << "," << email
<< "," << gender << endl;
f.close();
// add.takeInput();
return;
}
void Faculty::fillMap()
{
string id;
cout << "\nEnter Id to fill: \n";
cin >> id;
if (!std::filesystem::exists("./data/" + id + ".csv"))
return void(cout << "Sorry, this Faculty ID is not registered.\n");
fstream f;
string path = "./data/" + id + ".csv";
f.open(path, ios::in);
string temp;
// //skipping the first row containing column headers;
// getline(f >> ws, temp);
// analyzing each entry afterwards;
(getline(f >> ws, temp));
{
Faculty a;
// creating a string stream object to read from string 'temp';
stringstream s(temp);
string s1, s5, s6, s7;
// reading from the string stream object 's';
getline(s, a.id, ',');
getline(s, a.name, ',');
getline(s, s1, ',');
getline(s, a.phone, ',');
getline(s, a.email, ',');
// getline(s, a.gender, ',');
getline(s, s7, ',');
a.age = strToNum(s1);
a.gender = s7[0];
// if (!a.idle)
// {
// a.add.strToAdd(s6);
// a.D = Faculty::driversList[strToNum(s7)];
// }
// Faculty::FacultyList[a.id] = a;
}
f.close();
return;
}
void Faculty::editMap()
{
string id;
cout << "\nEnter Id to edit: \n";
cin >> id;
if (!std::filesystem::exists("./data/" + id + ".csv"))
return void(cout << "Sorry, this Faculty ID is not registered.\n");
fstream f;
string path = "./data/" + id + ".csv";
f.open(path, ios::in);
string temp;
// //skipping the first row containing column headers;
// getline(f >> ws, temp);
// analyzing each entry afterwards;
(getline(f >> ws, temp));
{
// Faculty a;
// creating a string stream object to read from string 'temp';
stringstream s(temp);
string s1, s5, s6, s7;
// reading from the string stream object 's';
getline(s, id, ',');
getline(s, name, ',');
getline(s, s1, ',');
getline(s, phone, ',');
getline(s, email, ',');
// getline(s, a.gender, ',');
getline(s, s7, ',');
age = strToNum(s1);
gender = s7[0];
}
f.close();
int choice = 0;
while (choice != 5)
{
cout << "\nWhat do you want to edit?\n";
cout << "1. Name\n";
cout << "2. Age\n";
cout << "3. Phone\n";
cout << "4. Email\n";
cout << "5. Gender\n";
cout << "6. Exit\n";
cin >> choice;
switch (choice)
{
case 1:
{
cout << "\nEnter name: ";
getline(cin >> ws, name);
break;
}
case 2:
{
cout << "\nEnter age: \n";
cin >> age;
while (age <= 0)
{
cout << "Was that supposed to make any kind of sense?\nEnter again!\n", cin >> age;
if (age < 18)
return void(cout << "Sorry, person should be at least 18 years old to be registered.\n");
else if (age > 100)
return void(cout << "Sorry, we can't register a person older than 100 years.\n");
}
break;
}
case 3:
{
cout << "\nEnter mobile number (with country code): \n";
getline(cin >> ws, phone);
break;
}
case 4:
{
cout << "\nEnter email: \n";
getline(cin >> ws, email);
break;
}
case 5:
{
choice = 5;
break;
}
default:
{
return void(cout << "Invalid choice!\n");
break;
}
}
}
remove((char *)path.c_str());
fstream f;
string path = "./data/" + id + ".csv";
f.open(path, ios::out);
f << id << name << "," << age << "," << phone << "," << email
<< "," << gender << endl;
f.close();
// `le first line conataining column headers:
// f << "Id,Name,age,phone,email,gender\n";
// for (auto i : Faculty::appointmentsList)
// f << id << "," << yyyymmdd << "," << i.second.D.id << "," << i.second.P.id
// << "," << i.second.hh << endl;
// f.close();
// rename("./data/temp.csv", "./data/appointments.csv");
return;
}
void removeFaculty()
{
string id;
cout << "\nEnter Id to edit: \n";
cin >> id;
if (!std::filesystem::exists("./data/" + id + ".csv"))
return void(cout << "Sorry, this Faculty ID is not registered.\n");
remove((char *)("./data/" + id + ".csv").c_str());
return void(cout << "Faculty removed successfully!\n");
}

Related

Why is the data in the "addtocart()" function not written into the file ? c++

In this program I'm trying to add data about customers in a file. However, for some reason when I open the file I can only see the data from the "newcustomer()" function. Can somebody tell me the reason for this please.
Here's the related part of my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct cartitem{
string name;
int num_of_copies;
float price;};
int i;
int ci=0;
fstream customersdata;
void newcustomer(fstream &customersdata, string cname){
string arrtime;
customersdata << "Name: " << cname << '\n';
string order = cname+"order";
customersdata << order <<'\n';}
void addtocart(fstream &customersdata, string cname){
ci++;
string bname;
cout << "enter book name \n" ; cin >> bname;
int num_of_copies;
cout << "enter number of copies to add to cart \n" ; cin >> num_of_copies;
string order = cname+"order";
cartitem x;
x.name = bname;
x.num_of_copies=num_of_copies;
if(customersdata.is_open()){
string b;
while (getline(customersdata,b)){
if (b.find(order, 0) != string::npos){
size_t pos;
pos = b.find(order, 0);
customersdata.seekp(pos+ci);
customersdata << "item" << ci << ": " << x.name << " num of copies: " << x.num_of_copies <<'\n';}}}
else { cout << "unable to open file\n";}}
int main(){
string cname;
customersdata.open("customersdata.txt", ios::out | ios::in);
cout << "enter customer name\n"; cin >> cname;
newcustomer(customersdata,cname);
addtocart(customersdata,cname);
customersdata.close();
string filename = "customersdata.txt";
system(filename.c_str());}
that's what the file looks like if I run a test code for a person named james

C++ String Array to Text Document

I am trying to create a program that will make an array of data entered until a stop commands is entered and have it log it into a text document. I am getting a crash of Microsoft Visual Studio after i enter the Fist name and Last name fields.
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
using namespace std;
int main(void) {
string firstName;
string lastName;
string stream;
int outputString;
string dataOutput;
string dataArray[1];
bool askData = true;
int i = 0;
ofstream outfile("data.txt");
while (askData) {
cout << "Type First then Last Name or \"$Stop\" to save and exit" << "\n" << "First: ";
getline(cin, firstName);
if (firstName == "$Stop") {
askData = false;
}
else {
cout << "Last: ";
cin >> lastName;
cout << "\n\n\n";
dataOutput = firstName + " " + lastName + "; ";
dataArray [1 + i] = dataOutput;
i++;
}
cout << dataOutput;
}
outfile << dataArray;
outfile.close();
return 0;
}
EDIT:
Also tried.
string dataArray[];
then later assigning it to an incrementing variable.
int i = 0;
dataArray[i];
i++;
Can you tell me why this doesnt work?

c++ Vector subscript out of range error

The program is supposed to open a .csv file and input the data into a vector. Later I'm supposed to implement a priority queue. However I'm getting this error when I try to run it.
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include "Prisoner.h"
#include "Jailed.h"
using namespace std;
int main()
{
string line, ID, sentenceIn, servedIn, lastName, firstName;
int sentence, served;
vector<string> idNum;
vector<int> sentenceLen;
vector<int> servedTime;
vector<string> lastNameIn;
vector<string> firstNameIn;
ifstream data("prisoner_data.csv");
if (!data.is_open())
{
exit(EXIT_FAILURE);
}
while (getline(data, line))
{
getline(data, ID, ',');
cout << ID << " ";
idNum.push_back(ID);
getline(data, sentenceIn, ',');
cout << sentenceIn << " ";
istringstream(sentenceIn) >> sentence;
sentenceLen.push_back(sentence);
getline(data, servedIn, ',');
cout << servedIn << " ";
istringstream(servedIn) >> served;
servedTime.push_back(served);
getline(data, lastName, ',');
lastNameIn.push_back(lastName);
cout << lastName << " ";
getline(data, firstName, ',');
firstNameIn.push_back(firstName);
cout << firstName << " ";
}
Prisoner p[100]; // Initializing Prisoner class
for (int i = 0; i <= idNum.size(); i++)
{
p[i].setIdNum(idNum[i]);
p[i].setSentence(sentenceLen[i]);
p[i].setTimeServed(servedTime[i]);
p[i].setLastName(lastNameIn[i]);
p[i].setFirstName(firstNameIn[i]);
}
data.close();
system("pause");
return 0;
}
I can also include the prisoner class if needed to figure out the issue.
for (int i = 0; i <= idNum.size(); i++)
should be
for (int i = 0; i < idNum.size(); i++)

Finding a word in C++

I'm able to find the word in my list but I would like to display whatever number there is after the word has been found. My list has names followed by their GPA.
Example...
michael 2.3
Rachel 2.5
Carlos 3.0
I would like to add the feature of displaying the number located after the name once it's found, I declared as int GPA but I'm not sure how to incorporated in my program.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
string name;
int offset;
string line;
int gpa;
ifstream read_file;
read_file.open("alpha.dat");
cout << "Please enter your name: \n";
cin >> name;
if (read_file.is_open())
{
while (!read_file.eof())
{
getline(read_file, line);
if ((offset = line.find(name)) != string::npos)
{
cout << "the word has been found: \n";
// cout << name << gpa; example to display
}
}
read_file.close();
return 0;
}
As far as I can tell, you just need to output the line that you read from file:
while( getline(read_file, line) )
{
if ((offset = line.find(name)) != string::npos) cout << line << endl;
}
Note that this isn't the best way to find the name. For example, what if the user enters Carl? It will be found as part of the string Carlos. Or indeed, if they enter 2, it will match parts of the GPA for multiple people.
What you can do here is use a string stream to read the name out. Let's assume it contains no spaces, which would make it conform to how you are reading the user's name in. You need to include <sstream>, by the way. Note that you can read out the GPA as part of this same mechanism.
istringstream iss( line );
string thisname, gpa;
if( iss >> thisname >> gpa ) {
if( thisname == name ) cout << name << " " << gpa << endl;
}
Finally, you may want to consider ignoring case when comparing strings. The cheeky way is to just use the old C functions for this. I know there are C++ methods for this, but none are as simple as good old stricmp from <cstring>:
if( 0 == stricmp(thisname.c_str(), name.c_str()) ) {
cout << name << " " << gpa << endl;
}
You can split line using stringstream, and store it into a vector, like this:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <vector>
using namespace std;
int main()
{
string name;
int offset;
string line;
int gpa;
ifstream read_file;
read_file.open("alpha.dat");
cout << "Please enter your name: \n";
cin >> name;
if (read_file.is_open())
{
while (!read_file.eof())
{
getline(read_file, line);
if ((offset = line.find(name)) != string::npos)
{
cout << "the word has been found: \n";
stringstream iss(line);
vector<string> tokens;
string str;
while (iss >> str)
tokens.push_back(str);
cout << tokens[0] << tokens[1];
}
}
read_file.close();
return 0;
}
}
You can replace getline(read_file, line)... with:
read_file >> name >> gpa;
if (name == search_name)
cout << name << " " << gpa << endl;

How to read in a set of values from a text file, then go to the next line and do the same

Im trying to read a list like this one
James John 15 5 1
Douglas Frank 23 8 1
Bnejamin Zach 17 1 4
and store each value into a a separate variable. The names are strings, and the other numbers are floats and an int. I can get the data from one line so far, but I dont know how to go onto the next line and do the same. Here is my code so far.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
ifstream employees;
string lastname, firstname, lastname1, firstname1, lastname2, firstname2;
float base, sales, base1, sales1, base2, sales2;
int years, years1, years2;
employees.open("employees.txt");
while (employees)
{
employees >> lastname >> firstname >> base >> sales >> years;
I want to keep it as simple as possible, I dont know user defined functions, arrays, or vectors at all yet. So is there a simple function that will just end the line at years; and go to the next line and carry on?
Thanks.
Use an array. Whenever you end up with "I want to add a number to this variable because I want more than one", if the number reaches more than 2, then you should really use an array (unless very special cases).
You may also want to use a struct to store your different values (firstname, lastname, base, sales and years) - that way, you only get a single array, rather than several different arrays.
Since this is C++, arrays means vector. In other words:
struct employee
{
string firstname, lastname;
float base, sales;
int years;
};
vector<employee> emp_table;
employee e;
while (employees >> e.firstname >> e.lastname >> e.base >> e.sales >> e.years)
{
emp_table.push_back(e);
}
Note I put the input of employees as the while-condition. This avoids an extra loop iteration and "pushing back" a second copy of the last entry when you have reached end of file.
There are many ways in C++ to accomplish what you are trying to do. One approach that allows for data validation is to use the std::getline function to read the file one line at a time and then use a std::stringstream to parse the data.. This allows you to validate the data and continue processing if the data on a line is malformed.
[As Mats noted you can use a data structure and std::vector to make storing and managing the data easier.]
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
struct employee
{
std::string firstname;
std::string lastname;
float base;
float sales;
int years;
};
int main()
{
std::ifstream employeeFile;
employeeFile.open("employees.txt");
std::string tmpLine;
std::vector<employee> employeeTable;
// read in an entire line at a time
while(std::getline(employeeFile, tmpLine))
{
// Place the input line into a stream that reads from
// a string instead of a file.
std::stringstream inputLine(tmpLine);
// Try parsing the data. The ! operator is used here to check
// for errors. Since we expect the data to be in a specific format
// we want to be able to handle situations where the input line
// may be malformed. For example, encountering a string where
// a number should be.
employee e;
if(!(inputLine >> e.firstname >> e.lastname >> e.base >> e.sales >> e.years))
{
// ... error parsing input. Report the error
// or handle it in some other way.
continue; // keep going!
}
// Add to the vector
employeeTable.push_back(e);
}
return 0;
}
You can use getline inside your loop to retrieve each line and then use it with a stringstream
Something like:
string line;
while(getline(employees,line))
{
//doSomething
}
If you can't use arrays to store them easily, you can put a counter to know at which line you're at, but this is very repetitive, and the number of lines in your file cannot vary:
string line;
for (int count = 1 ; count <= 3 ; count++)
{
getline(employees,line);
istringstream iss(line);
if (count == 1)
{
iss >> lastname >> firstname >> base >> sales >> years;
}
else if (count == 2)
{
iss >> lastname1 >> firstname1 >> base1 >> sales1 >> years1;
}
else if (count == 3)
{
iss >> lastname2 >> firstname2 >> base2 >> sales2 >> years2;
}
}
Opening and reading a file properly is harder than learning what an array is. If you don't use an array you have to use too many variables to hold all your data, and you have to repeatedly write the code to read from the file, rather than writing it once in a loop.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string firstNames[3];
string lastNames[3];
float heights[3];
float weights[3];
int ages[3];
ifstream infile("data.txt");
if(!infile)
{
cout << "Couldn't open file!" << endl;
return 1;
}
int count = 0;
while (infile >> firstNames[count]
>> lastNames[count]
>> heights[count]
>> weights[count]
>> ages[count] )
{
++count;
}
infile.close();
for (int i = 0; i<count; ++i) {
cout << firstNames[i] << " "
<< lastNames[i] << " "
<< heights[i] << " "
<< weights[i] << " "
<< ages[i] << " " << endl;
}
return 0;
}
--output:--
James John 15 5 1
Douglas Frank 23 8 1
Bnejamin Zach 17 1 4
Compare to this disaster:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string firstName0,firstName1, firstName2;
string lastName0, lastName1, lastName2;
float height0, height1, height2;
float weight0, weight1, weight2;
int age0, age1, age2;
ifstream infile("data.txt");
if(!infile)
{
cout << "Couldn't open file!" << endl;
return 1;
}
infile >> firstName0 >> lastName0 >> height0 >> weight0 >> age0;
infile >> firstName1 >> lastName1 >> height1 >> weight1 >> age1;
infile >> firstName2 >> lastName2 >> height2 >> weight2 >> age2;
infile.close();
cout << firstName0 << " "
<< lastName0 << " "
<< height0 << " "
<< weight0 << " "
<< age0 << endl;
cout << firstName1 << " "
<< lastName1 << " "
<< height1 << " "
<< weight1 << " "
<< age1 << endl;
cout << firstName2 << " "
<< lastName2 << " "
<< height2 << " "
<< weight2 << " "
<< age2 << endl;
return 0;
}
--output:--
James John 15 5 1
Douglas Frank 23 8 1
Bnejamin Zach 17 1 4
Look at all the code you have to repeat.
Note that when you use an array, the variable names become firstNames[0] (v. firstName0), lastNames[0] (v. lastName0), etc., and firstNames[1] (v. firstName1) and lastNames[1] (v. lastName0).