I'm trying to store pointers of a class in a vector but get the error
Implicit instantiation of undefined template 'std::__1::vector<Item *>'
The code is:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class Item{
private:
string itemName;
float itemPrice;
int itemQuantity;
public:
Item(string name = "NULL", float price = 0, int quantity = 0){
itemName = name;
itemPrice = price;
itemQuantity = quantity;
}
friend ofstream & operator<<(ofstream &ofs, Item &i);
friend ifstream & operator>>(ifstream &ifs, Item &i);
friend ostream & operator<<(ostream &os, Item &i);
};
ofstream & operator<<(ofstream & ofs, Item &i){
ofs << i.itemName << endl;
ofs << i.itemPrice << endl;
ofs << i.itemQuantity << endl;
return ofs;
}
ostream & operator<<(ostream &os, Item &i){
os << i.itemName << endl;
os << i.itemPrice << endl;
os << i.itemQuantity << endl;
return os;
}
ifstream & operator>>(ifstream & ifs , Item & i){
ifs >> i.itemName;
ifs >> i.itemPrice;
ifs >> i.itemQuantity;
return ifs;
}
int main() {
int n;
string name;
float price;
int qty;
cout<<"Enter number of Item:";
cin>>n;
vector<Item *> items;
cout<<"Enter All Item "<<endl;
for(int i=0;i<n;i++)
{
cout<<"Enter "<<i+1<<" Item Name , price and quantity";
cin>>name;
cin>>price;
cin>>qty;
items.push_back(new Item(name,price,qty));
}
ofstream fos("Items.txt");
for(int i=0;i<n;i++)
{
fos<<*items[i];
}
Item item;
ifstream fis("Items.txt");
for(int i=0;i<3;i++)
{
fis>>item;
cout<<"Item "<<i<<item<<endl;
}
}
It looks like a basic error, but I couldn't find a way over it.How can I store pointers of a user defined class inside a vector? Is my syntax off or vectors just won't work that way?
You didn't include
#include <vector>
adding it, your code will compile cleanly.
Related
I tried the below code to write an object to a dat file:
#include<iostream>
#include<fstream>
#include<string>
#include<string.h>
using namespace std;
class Student
{ //data members
int adm;
string name;
public:
Student()
{
adm = 0;
name = "";
}
Student(int a,string n)
{
adm = a;
name = n;
}
Student setData(Student st) //member function
{
cout << "\nEnter admission no. ";
cin >> adm;
cout << "Enter name of student ";
cin.ignore();
getline(cin,name);
st = Student(adm,name);
return st;
}
void showData()
{
cout << "\nAdmission no. : " << adm;
cout << "\nStudent Name : " << name;
}
int retAdmno()
{
return adm;
}
};
/*
* function to write in a binary file.
*/
void demo()
{
ofstream f;
f.open("student.dat",ios::binary);
for(int i = 0;i<4;i++)
{
Student st;
st = st.setData(st);
f.write((char*)&st,sizeof(st));
}
f.close();
ifstream fin;
fin.open("student.dat",ios::binary);
Student st;
while(!fin.eof())
{
fin.read((char*)&st,sizeof(st));
st.showData();
}
}
int main()
{
demo();
return 0;
}
But when I am executing the demo function I am getting some garbage values from the "student.dat"
file. I am creating a database and want to get the records but I am not able to get all the records in the dat file.
Please suggest a solution
You cannot write complex data types to a file in binary mode. They have some additional variables and functions inside,which you do not know or see. Those data types have some internal state that or context dependent. So, you cannot store in binary and then reuse it somewhere else. That will never work.
The solution is serialization/deserialization.
This sounds complicated, but is not at all in your case. It basically means that all your data from your struct shall be converted to plain text and put in a text-file.
For readin the data back, it will be first read as text, and then converted to your internal data structures.
And the default approach for that is to overwrite the inserter << operator and extractor >> operator.
See the simple example in your modified code:
#include<iostream>
#include<fstream>
#include<string>
#include<iomanip>
class Student
{ //data members
int adm;
std::string name;
public:
Student()
{
adm = 0;
name = "";
}
Student(int a, std::string n)
{
adm = a;
name = n;
}
Student setData(Student st) //member function
{
std::cout << "\nEnter admission no. ";
std::cin >> adm;
std::cout << "Enter name of student ";
std::getline(std::cin>> std::ws, name);
st = Student(adm, name);
return st;
}
void showData()
{
std::cout << "\nAdmission no. : " << adm;
std::cout << "\nStudent Name : " << name;
}
int retAdmno()
{
return adm;
}
friend std::ostream& operator << (std::ostream& os, const Student& s) {
return os << s.adm << '\n' << s.name << '\n';
}
friend std::istream& operator >> (std::istream& is, Student& s) {
return std::getline(is >> s.adm >> std::ws, s.name);
}
};
/*
* function to write in a binary file.
*/
void demo()
{
std::ofstream f("student.dat");
for (int i = 0; i < 4; i++)
{
Student st;
st = st.setData(st);
f << st;
}
f.close();
std::ifstream fin("student.dat");
Student st;
while (!fin.eof())
{
fin >> st;
st.showData();
}
}
int main()
{
demo();
return 0;
}
Ok so I figured out and learned a lot of stuff today and I want to thank the community for that. I haven't had any bump in the roads for a few hours now but now I'm stuck.
The last bump in the road. Saving and Loading my program. I have no idea where to start. I looked at how fwrite... and fread... works and all the examples are for programs that aren't split. I don't know where to start with my files. I'll put up 2 functions. If someone can help me how to do save those I can probably figure out the rest.
in gradebook.h
class Student {
public:
string last;
string first;
int student_id;
};
class Course {
public:
string name;
int course_id;
vector <Student> students;
};
class Gradebook {
public:
Gradebook();
void addCourse();
void addStudent();
private:
vector <Course> courses;
};
in gradebook.cpp
void Gradebook::addCourse() {
int i, loop=0;
cout << "Enter Number of Courses: ";
cin >> loop;
for(i=0; i<loop; i++) {
//create newEntry to store variables
Course newEntry;
cout << "Enter Course ID: ";
cin >> newEntry.course_id;
cout << "Enter Course Name: ";
cin >> newEntry.name;
//set variables from newEntry in Courses
courses.push_back(newEntry);
}
}
void Gradebook::addStudent() {
int i, loop=0;
cout << "Enter Number of Students: ";
cin >> loop;
for(i=0; i<loop; i++) {
//create newEntry to store variables
Student newEntry;
cout << "Enter Student ID: ";
cin >> newEntry.student_id;
cout << "Enter Last Name: ";
cin >> newEntry.last;
cout << "Enter First Name: ";
cin >> newEntry.first;
//set variables from newEntry in Students
courses[0].students.push_back(newEntry);
}
}
So if a user was to input some variables in courses and students how would i use fwrite... to save the data?
I wouldn't recommend fwrite, instead look into <fstream>. ifstream, ofstream
Basic saving:
ofstream out("data.txt"); //save file data.txt
out << thedata; //use the << operator to write data
Basic loading:
ifstream in("data.txt"); //reopen the same file
in >> thedata; //use the >> operator to read data.
Here's some sample code that might help without solving the whole thing for you.
#include<iostream>
#include<string>
#include<vector>
#include<fstream>
class Student {
public:
Student()
: student_id(0)
{
}
Student(const std::string &f, const std::string &l, int id)
: first(f)
, last(l)
, student_id(id)
{
}
std::string last;
std::string first;
int student_id;
};
std::ostream &operator <<(std::ostream &os, const Student &s)
{
os << s.last << '\t'
<< s.first << '\t'
<< s.student_id << '\t';
return os;
}
std::istream &operator >>(std::istream &is, Student &s)
{
is >> s.last
>> s.first
>> s.student_id;
return is;
}
bool WriteIt(const std::string &sFileName)
{
std::vector<Student> v;
v.push_back(Student("Andrew", "Bogut", 1231));
v.push_back(Student("Luc", "Longley", 1232));
v.push_back(Student("Andrew", "Gaze", 1233));
v.push_back(Student("Shane", "Heal", 1234));
v.push_back(Student("Chris", "Anstey", 1235));
v.push_back(Student("Mark", "Bradtke", 1236));
std::ofstream os(sFileName);
os << v.size();
for (auto s : v)
os << s;
return os.good();
}
bool ReadIt(const std::string &sFileName)
{
std::ifstream is(sFileName);
int nCount(0);
is >> nCount;
if (is.good())
{
std::vector<Student> v(nCount);
for (int i = 0; i < nCount && is.good(); ++i)
is >> v[i];
if (is.good())
for (auto s : v)
std::cout << s << std::endl;
}
return is.good();
}
int main()
{
const std::string sFileName("Test.dat");
return !(WriteIt(sFileName) && ReadIt(sFileName));
}
Bonus points if you recognise who my "students" are. :-)
I need to merge two text files and have them sort by "lastName" on a third outputted file. My code is below, it is outputting gibberish, all on one line. I understand my overload may be stupid, any help is appreciated.
//header
#include <fstream>
#include <string>
#include <iostream>
using namespace std;
struct mergedList {
string firstName;
string lastName;
float gpa;
int hours;
};
ostream& operator << (ostream& os, mergedList A) {
os << A.firstName << "\t" << A.lastName << "\t" << A.gpa << "\t" << A.hours;
return os;
}
istream& operator >> (istream& is, mergedList& A) {
is >> A.firstName >> A.lastName >> A.gpa >> A.hours;
return is;
}
void swap(mergedList D1[], int i, int j);
void sort(mergedList D1[], int size);
int main() {
ifstream indata;
ifstream indata2;
ofstream outdata;
indata.open("merge1.txt");
indata2.open("merge2.txt");
outdata.open("merged.txt");
//begin sentinel controlled loop for both lists
mergedList D1[100];
int index = 0;
indata >> D1[index];
while (!indata.eof()) {
index++;
indata >> D1[index];
}
sort(D1, index);
mergedList D2[100];
int index2 = 0;
indata2 >> D2[index2];
while (!indata2.eof()) {
index2++;
indata2 >> D2[index2];
}
sort(D2, index); {
int i = 0, j = 0;
while ((i < index) && (j < index2)) if (D1[i].lastName < D2[j].lastName) {
outdata << D1[i];
i++;
indata >> D1[i];
} else {
outdata << D2[j];
j++;
indata2 >> D2[j];
}
}
indata.close();
indata2.close();
outdata.close();
return 0;
}
void swap(mergedList D1[], int i, int j) {
mergedList temp;
temp = D1[i];
D1[i] = D1[j];
D1[j] = temp;
return;
}
void sort(mergedList D1[], int size) {
for (int p = 1; p < size; p++) {
for (int c = 0; c < size - p; c++) {
if (D1[c].lastName > D1[c + 1].lastName) swap(D1, c, c + 1);
}
}
return;
}
Here is some code. I have tried to explain as much as I can. If you are using C++ you should try to take advantage of the containers and algorithms that are already available for you.
struct mergedList
{
string firstName;
string lastName;
float gpa;
int hours;
};
ostream& operator <<(ostream& os, mergedList A)
{
os << A.firstName << "\t" << A.lastName << "\t" << A.gpa << "\t" << A.hours;
return os;
}
istream& operator >>(istream& is, mergedList& A)
{
is >> A.firstName >> A.lastName >> A.gpa >> A.hours;
return is;
}
// We use this to compare two MergedList structs. i.e. by first name
// http://www.cplusplus.com/reference/algorithm/sort/ for an example
struct my_sorter {
bool operator() (mergedList one, mergedList two) { return one.firstName < two.firstName ; }
};
int main()
{
ifstream indata;
ifstream indata2;
ofstream outdata;
indata.open("merged.txt");
indata2.open("merged2.txt");
outdata.open("merged.txt");
// This can be a vector. No need for array here.
vector<mergedList> D1;
int index=0, index2 = 0;
mergedList tmp;
// You can read from streams like this if the data is formatted.
while (indata >> tmp)
{
D1.push_back(tmp);
index++; // Maybe you need this??
}
// Read the second file in to the same vector.
// You don't need another one.
while (indata2 >> tmp)
{
D1.push_back(tmp);
index2++;
}
cout << "Before sorting" << endl;
copy(D1.begin(), D1.end(), ostream_iterator<mergedList>(cout, "\n"));
// Sort the vector using the std::sort algorithm.
// http://www.cplusplus.com/reference/algorithm/sort/ for an example
sort(D1.begin(), D1.end(), my_sorter());
cout << "After sorting" << endl;
copy(D1.begin(), D1.end(), ostream_iterator<mergedList>(cout, "\n"));
// Write the sorted list to the output file
copy(D1.begin(), D1.end(), ostream_iterator<mergedList>(outdata, "\n"));
indata.close();
indata2.close();
outdata.close();
return 0;
}
If optimization is an issue for you, I suggest you use STL containers as the proper sort methods are implemented. Do not use static arrays if your code should work on every given input file. I might also add that you can first merge the two files and then sort the third one.
There is more code to this question in this previous question: C++ Trouble Inputting Data into Private Vector (invalid use)
I'm trying to output a vector of type "Account"
Account:
class Account
{
string firstName;
string lastName;
string accountPass;
int accountID;
float accountBalance;
private:
int depositAmount;
int withdrawAmount;
public:
static Account createAccount( int, float, string, string, string ); //creates new account
void deposit( int ); //deposits money into account
void withdraw(int); //withdrawals money from account
int retdeposit() const; //function to return balance amount
friend class BankingSystem;
}; //end of class Account
This is the way I'm declaring the vector:
std::vector<Account> accounts_;
And here's how I'm trying to print it to the screen:
for(int i=0; i < accounts_.size(); i++)
{ cout<< accounts_[i] <<endl; }
But I'm getting this error "invalid operands to binary expression".
Current code;
class BankingSystem
{
int accountID;
char fileName;
private:
std::vector<Account> accounts_;
public:
void addAccount();
void storeAccount( Account );
void deleteAccount();
void accountInquiry();
void saveAccounts();
void loadAccountsFromFile();
friend class Account;
friend std::ostream& operator << (std::ostream&, const Account&);
}; // end of class BankingSystem
#endif
std::ostream& operator << (std::ostream& os, const Account& acc)
{
// output members to os
return os;
}
void BankingSystem::addAccount()
{
int ID;
float balance;
std::string pass, first, last;
cout << "\n\t Enter the Account ID: ";
cin >> ID;
cout << "\n\t Enter the passcode: ";
cin >> pass;
cout << "\n\t Enter Client's first name: ";
cin >> first;
cout << "\n\t Enter Client's last name: ";
cin >> last;
cout << "\n\t Enter starting balance: ";
cin >> setw(6) >> balance;
storeAccount( Account::createAccount( ID, balance, pass, first, last ) );
return;
}
//function gets data from createAccount
void BankingSystem::storeAccount( Account newAccountToAdd )
{
//append to vector "accounts_"
accounts_.push_back(newAccountToAdd);
}
void BankingSystem::deleteAccount()
{
cout << "\nEnter The Account ID: ";
cin >> accountID;
}
void BankingSystem::accountInquiry()
{
int n;
cout << "\n\t Enter The Account ID (-1 for all): ";
cin >> n;
//cout << accounts_.size();
if (n == -1)
{
cout << "\n\t List of all Accounts; (" << accounts_.size() << ") TOTAL: ";
for(int i=0; i < accounts_.size(); i++)
{
cout<< accounts_[i] << endl;
}
}
else
{
cout << "\n\t Listing Account: " << n;
cout << "\n\t I should search the vector for the ID you input";
}
}
You need to provide the insertion operator:
std::ostream& operator<<( std::ostream& out, const Account& acct );
Then implement it internally by dumping each one of the fields with the appropriate format.
You should overload operator << for Account class. In class:
friend std::ostream& operator << (std::ostream&, const Account&);
In global (or yours, where Account is defined) namespace
std::ostream& operator << (std::ostream& os, const Account& acc)
{
// output members to os
return os;
}
or create some output function in class for example
void print(std::ostream& os) const { }
And then free-operator <<
std::ostream& operator << (std::ostream& os, const Account& acc)
{
acc.print(os);
return os;
}
//Student file
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;
#include "student.h"
#define cap 100
void main()
{ string s;
class student student[cap],l;
int i;
fstream f;
i=0;
cout << "Enter the file name: "; //Display to enter the file name
cin >>s;
f.open(s.data(),ios::in);
if(!f.is_open())
cout << "could not open file";
while(i<cap && !f.eof())
{ cout << "good";
student[i].get(f);
//Display if okay
if(f.good())
{
i++;
student[i].put(cout);
cout << i;
}
}
f.close();
}
class student
{
public:
student(); //Constructor without parameters
student(int,string,string,int,float); //Constructor with parameters
~student(); //Deconstructors
bool get(istream &); //Input
void put(ostream &); //Output
int read_array(string,int);
private:
int id,age;
float gpa;
string last,first;
};
student::student()
{
id = 0;
first = "null";
last = "null";
age = 0;
gpa = 0.0;
}
bool student::get(istream &in)
{
in >> id >> first >> last >> age >> gpa;
return(in.good());
}
void student::put(ostream &out)
{
out << id << first << last << age << gpa;
}
When i run this It displays the constructor values over, and over and the data from the file that should be going into the array and displaying them. I am not sure if I am doing the right way to put the data into the class array correctly.
Here's one problem:
if (f.good())
{
// student[i] has just been read from the file.
i++; // Increment counter.
student[i].put(cout); // Print whatever was in the next element.
cout << i;
}
The counter is incremented first, so student[i] refers to the element after the one that was just updated.