How to operate overload ">>"? - c++

Product **products;
int numProducts = 0;
void setup()
{
ifstream finput("products.txt");
//get # of products first.
finput >> numProducts;
products = new Product* [numProducts];
//get product codes, names & prices.
for(int i=0; i<numProducts; i++) {
products[i] = new Product;
finput >> products[i]->getCode() >> products[i]->getName() >> products[i]->getPrice();
}
}
I am getting an "invalid operands to binary expression" error for this line:
finput >> products[i]->getCode() >> products[i]->getName() >> products[i]->getPrice();
Do I need to operator overload >> and how would I do it?

Let's take a very simple example, assuming a basic definition for Product as:
class Product
{
int code;
string name;
double price;
public:
Product(int code, const std::string& name, double price)
: code{code}, name{name}, price{price}
{}
int getCode() const { return code; }
const std::string& getName() const { return name; }
double getPrice() const { return price; }
};
You can't read in using operator>> directly into the return values from getCode(), getName() or getPrice(). Those are for accessing those values.
Instead, you need to read in the values and construct products from those values like this:
for(int x = 0; x < numProducts; ++x)
{
int code = 0;
string name;
double price = 0;
finput >> code >> name >> price;
products[i] = new Product{code,name,price};
}
Now, you could refactor this into operator>>:
std::istream& operator>>(std::istream& in, Product& p)
{
int code = 0;
string name;
double price = 0;
in >> code >> name >> price;
p = Product{code,name,price};
return in;
}
There are a bunch of other things to consider about this code:
Use std::vector<Product> instead of your own array
The examples below won't work if name has spaces
There's no error checking and operator>> can fail

In your Class, write down this function
friend ifstream& operator >> (ifstream& in, Product& p1)
{
in >> p1.code >> p1.name /* ..etc */;
return in;
}

Related

Adding Objects from a Class to another Class

INPUT STDIN -> <street> <city> <house_number> <number of objects of house> <object1> <price1> .......<object-n> <price-n> (until EOF)
I need to use the "add" method in the "House" Class.
objective: adding the specific n objects of each House in "House" class
This is what i did since now:
#include <iostream>
#include <utility>
#include<vector>
#include<string>
using namespace std;
class Object {
public:
string valuable;
float price;
public:
Object() : Object("",0) {}
Object(string v, float p) : valuable(std::move(v)), price(p) {}
string getValuable() {
return valuable;
}
float getPrice() {
return price;
}
};
class House{
public:
string street;
string city;
uint32_t number;
vector<Object>valuables;
public:
House(): House("","",0){}
House(string s,string c,uint32_t n): street(std::move(s)),city(std::move(c)),number(n){}
string getStreet() {
return street;
}
string getCity() {
return city;
}
uint32_t getNumber() {
return number;
}
uint32_t getValuablesSize() {
return valuables.size();
}
Object getValuable(uint32_t x){
return valuables[x];
}
void add(Object a){
valuables.emplace_back(a);
}
};
float getTotalPrice(House a) {
float sum = 0;
for (int i = 0; i < a.getValuablesSize(); i++) {
sum +=a.valuables[i].getPrice();
}
return sum;
}
int main() {
vector<Object>obj;
vector<House>house;
char object[30],street[30],city[30];
float price;
uint32_t house_number;
int n;
while(cin>>street>>city>>house_number>>n) {
house.emplace_back(string(street),string(city),house_number);
Object a;
for(int i=0;i<n;i++){
cin>>object>>price;
obj.emplace_back(object,price);
a.valuable=object;
a.price=price;
for(int k=0;k<house.size();k++)
house[k].add(a);
}
}
for(int i=0;i<obj.size();i++){
cout<<obj[i].getValuable()<<" "<<obj[i].getPrice()<<endl;
} // trying to print the object vector
for(int i=0;i<house.size();i++){ //trying to verify if i have the correct input
cout<<house[i].getStreet()<<" "<<house[i].getCity()<<" "<<house[i].getNumber()<<" ";
for(int j=0;j<house[i].getValuablesSize();j++) {
cout << house[i].valuables[j].valuable<< " "<<house[i].valuables[j].price<<" ";
}
cout<<endl;
}
return 0;
}
That's what i think:
-when i read <house_number> ,read the objects and prices and then the add method should be used in order to have the vector<Object>valuables usable.
It's necesarly to check if the input is stored corectly in the class "House", in order to continue summing the objects in every house
With the statements
for(int k=0;k<house.size();k++)
house[k].add(a);
you add the current "valuable" object to every house that has been created thus far.
I suggest you instead create the house object separately, then add the valuable objects to the current house, and after that add the house to your collection of houses.
Perhaps something like:
std::string street;
std::string city;
unsigned house_number;
unsigned n;
while(std::cin >> street >> city >> house_number >> n) {
House current_house(street, city, house_number);
std::string object;
float price;
for(int i = 0; i < n && std::cin >> object >> price; ++i) {
Object a(object, price)
current_house.add(a);
}
house.push_back(current_house);
}

After writing binary file and reading a record (an object) from the binary file, enum type last attribute of the record is NULL ( default value)

I'm trying to write a C++ code that read from a text file, write all the contents into a binary file, and read a record from the binary file.To hold records, I created a Student class that one of its attribute is enum type.I read from text file successfully, I write the Student records successfully (I check it while debugging), but I have a problem with reading one Nth record from the binary file.Although all attribute are taken successfully, the last attribute whic is enum type is not changed and seems as default even for all records.Although no error exists in the VS 2017, with debugging I recognize that the problem is at binaryRead and readRecord parts (The data in "this" shows the enum attribute as NONE.Also sizeOfOneStudentRecord in seekg, read, readRecord, binaryRead etc. can be not true. I need help friends.
The code is given below. I will aprreciate your help.
enum Category { NONE = 0, Honor=1, High_Honor = 2 };
class Student
{
private:
string name;
double weight;
int age;
Category degree;
public:
Student();
Student(string _name, double _weight, int _age, Category _degree);
Student* txtRead(ifstream& myFile);
size_t sizeOfOneStudentRecord(Student* a);
void binaryWrite(fstream& myFile);
void binaryRead(fstream& myFile);
void readRecord(fstream& binmyFile, int order);
friend ostream& operator<<(ostream& output, Student& s) {
..
}
};
Student::Student()
{
name = "";
weight = 0.0;
age = 0;
degree = NONE;
}
Student::Student(string _name, double _weight, int _age, Category _degree)
{
name = _name;
weight = _weight;
age = _age;
degree = _degree;
}
size_t Student::sizeOfOneStudentRecord(Student* c) {
return sizeof(this->name) + sizeof(this->weight) + sizeof(this->age) + sizeof(this->degree);
}
Student* Student::txtRead(ifstream& myFile) {
...
}
void Student::binaryWrite(fstream& myFile) {
myFile.write((char *)this, sizeOfOneStudentRecord(this));
}
void Student::binaryRead(fstream& myFile) {
myFile.read((char*)this, sizeOfOneStudentRecord(this));
}
void Student::readRecord(fstream& binmyFile, int order) {
binmyFile.seekg((order)*sizeOfOneStudentRecord(this));
binaryRead(binmyFile);
name = this->name;
age = this->age;
weight = this->weight;
degree = this->degree;
}
int main() {
Student *StudentArr[20];
ifstream myFile("Student.txt", ios::in);
ofstream txtmyFile("newStudentFile.txt", ios::out | ios::trunc);
fstream binmyFile("StudentBin.bin", ios::out | ios::in | ios::trunc | ios::binary);
for (int i = 0; i < 20; i++) {
StudentArr[i] = new Student();
StudentArr[i]->txtRead(myFile);
txtmyFile << *StudentArr[i];
StudentArr[i]->binaryWrite(binmyFile);
}
myFile.close();
txtmyFile.close();
Student s1;
s1.readRecord(binmyFile, 8);
std::cout << s1 << endl;
binmyFile.close();
return 0;}

Need help implementing istream& operator >> method

I have looked over many questions available on SO, but I could not find something that actually answered my question.
I was wondering how to implement the istream& operator >> method to create an array of Books.
I just need help with the istream method, not the whole program.
#include "Warehouse.h"
#include "Book.h"
#include <iostream>
#include<string>
using namespace std;
static const int MAX_BOOKS = 35;
clss Warehouse {
/**
* #param is the input stream
* #param warehouse the warehouse object reference
* #return the input stream
*/
friend istream& operator >> (istream& is, Warehouse& warehouse);
/**
* #param os the output stream
* #param warehouse the warehouse object reference
* #return the output stream
*/
friend ostream& operator << (ostream& os, const Warehouse& warehouse);
public:
static const int MAX_BOOKS = 35;
Warehouse();
/**
* #param isbn the ISBN number to search for
* #param book reference to the matched book object, if found
* #return true if found.
*/
bool find (string isbn, Book& book) const;
/**
* Prints the inventory of the Warehouse (i.e. list all the books)
*/
void list () const;
private: /* extra credit */
void sort_();
private:
Book books[Warehouse::MAX_BOOKS];
int bookCount;
};
#endif /* WAREHOUSE_H */
This is the cpp file for the Book:
#include "Book.h"
#include <iostream>
#include <string>
using namespace std;
static const int MAX_BOOKS = 35;
static const int MAX_AUTHORS = 20;
string title_;
string authors_[Book::MAX_AUTHORS];
int authorCount_;
string publisher_;
short yearPublish_;
bool hardcover_;
float price_;
string isbn_;
long copies_;
istream& operator >> (istream& is, Book& book){
is >> book.title_;
is.ignore();
is >> book.authorCount_;
for (int j=0;j<book.authorCount_;j++){
is >> book.authors_[j];
is.ignore();
}
is >> book.publisher_;
is.ignore();
is >> book.yearPublish_;
is.ignore();
is >> book.hardcover_;
is.ignore();
is >> book.price_;
is.ignore();
is >> isbn_;
is.ignore();
is >> copies_;
is.ignore();
return is;
}
ostream& operator << (ostream& os, const Book& book){
os<< book.title_ << endl;
for (int j=0; j<book.authorCount_; j++){
os<< book.authors_[j] << endl;
}
os<< book.publisher_ << endl;
os<< book.yearPublish_;
os<<book.hardcover_;
os<< book.price_ << endl;
os<< book.isbn_ << endl;
os<< book.copies_ << endl;
return os;
}
Book :: Book() {};
Book :: Book (string title, string authors[], int authorCount, string publisher, short yearPublish, bool hardcover, float price, string isbn, long copies){
title_ = title;
authorCount_ = authorCount;
for (int i=0;i<authorCount_;i++){
authors_[i] = authors[i];
}
publisher_ = publisher;
yearPublish_ = yearPublish;
hardcover_ = hardcover;
price_ = price;
isbn_ = isbn;
copies_= copies;
}
void Book::setTitle(string title){
title_=title;
}
string Book::getTitle()const{
return title_;
}
void Book:: setAuthorCount(short authorCount){
authorCount_ = authorCount;
}
void Book::setAuthors(string authors[]){
authors_[MAX_AUTHORS]=authors[MAX_AUTHORS];
}
string Book::getAuthors() const{
return authors_[MAX_AUTHORS-1];
}
void Book::setPublisher(string publisher){
publisher_ = publisher;
}
string Book::getPublisher() const{
return publisher_;
}
void Book::setYearPublish(short yearPublish){
yearPublish_ = yearPublish;
}
short Book:: getYearPublish() const{
return yearPublish_;
}
void Book::setHardcover(bool hardcover){
hardcover_ = hardcover;
}
bool Book::getHardcover() const{
return hardcover_;
}
void Book:: setIsbn(string isbn){
isbn_ = isbn;
}
string Book::getIsbn() const{
return isbn_;
}
void Book:: setPrice(float price){
price_ = price;
}
float Book:: getPrice() const{
return price_;
}
void Book:: setCopies(long copies){
copies_ = copies;
}
long Book::getCopies()const{
return copies_;
}

usage of istream in class constructor c++

I have a text file that contains a list of students and their marks and looks like this:
Name_of_student 78 4; 98 5; 90 5; 63 3;
...
I have an assignment to create a class that will read and store that data. This is what I've done so far.
group.h
class Subject {
public:
Subject(int mark0, int mark1);
Subject();
int get_m0() { return mark0; }
int get_m1() { return mark1; }
private:
int mark0;
int mark1;
};
class Student {
public:
Student(string name);
Student();
vector<Subject>my_marks;
string get_name() { return name; }
private:
string name;
};
class Reading
{
public:
Reading(vector<Student>, istream& );
istream& read_student();
private:
vector<Student>group;
istream& is;
};
text.cpp
Subject::Subject(int m0, int m1) :
mark0(m0), mark1(m1) {}
Subject::Subject() :
mark0(1), mark1(1) {}
Student::Student(string n0) :
name(n0) {}
Student::Student() :
name("null") {}
Reading::Reading(vector<Student>group0, istream& is0) :
group(group0), is(is0) {}
istream& Reading::read_student()
{
string n;
is >> n;
if (!is) return is;
Student st = Student(n);
for (int i = 0; i < 4; ++i)
{
int m0, m1;
is >> m0 >> m1;
char ch;
is >> ch;
Subject sub = Subject(m0, m1);
st.my_marks.push_back(sub);
}
group.push_back(st);
return is;
}
It compiles, but refuses to read anything.
int main()
{
ifstream ifs("text");
if(!ifs) error("can`t open input file");
vector<Student> group;
Readding r(group, ifs);
r.read_student();
cout << group.size();
}
And what it shows:
0
If anyone has any ideas I'd appreciate it.
In Reading::read_student(), you are filling up the member variable Reading::group. You are not filling up the function variable group in main.
Use:
int main()
{
ifstream ifs("text");
vector<Student> group;
Readding r(group, ifs);
r.read_student();
cout << r.group.size();
// ^^^^^^^^ access the member variable of r.
}
If you want the function variable group to be filled up, Reading needs to store a reference to the input group.
class Reading
{
public:
Reading(vector<Student> & , istream& );
// ^^^^^^ Take a reference as input
istream& read_student();
private:
vector<Student>& group;
// ^^^^^^ store a reference
istream& is;
};
What i have changed:
group.h
class Reading
{
public:
Reading( istream& );
vector<Student>group;
istream& read_student();
private:
istream& is;
};
text.cpp
Reading::Reading(istream& is0) :
is(is0) {}
int main()
{
ifstream ifs("text");
if(!ifs) error("can`t open input file");
Readding r(ifs);
r.read_student();
cout << r.group.size();
}
And now it works all correct!!!

Overloading addition operator with many objects c++

I need to overload the addition operator of multiple different objects and return a 'cluster object:
"Overload the addition operator(+) to add any combination of instances for Desktops, Laptops, and Clusters. This operator should return an object of type cluster"
So if I had desktop1+laptop1+laptop2; I would need it to return a cluster that adds all of the RAM, and other variables of each object. But it will only be adding the variables that all of the objects inherit from the computer class. Here is my code of the rest of the project. Thanks!
#include <iostream>
using namespace std;
class computer
{
public:
double RAM;
double CPUSpeed;
int numberOfCores;
double HDDSize;
virtual void print();
};
class desktop : public computer
{
public:
bool hasMonitor;
double monitorSize;
friend istream& operator>> (istream &in, desktop &myDesktop);
};
class laptop : public computer
{
public:
double screenSize;
};
class cluster : public computer
{
public:
int numOfComp;
};
desktop::desktop()
{
RAM = 0;
CPUSpeed = 0;
numberOfCores = 0;
HDDSize = 0;
hasMonitor = 0;
monitorSize = 0;
}
laptop::laptop()
{
RAM = 0;
CPUSpeed = 0;
numberOfCores = 0;
HDDSize = 0;
screenSize = 0;
}
cluster::cluster()
{
RAM = 0;
CPUSpeed = 0;
numberOfCores = 0;
HDDSize = 0;
numOfComp = 0;
}
istream& operator>> (istream &in, desktop &myDesktop)
{
in >> myDesktop.hasMonitor;
in >> myDesktop.monitorSize;
in >> myDesktop.RAM;
in >> myDesktop.CPUSpeed;
in >> myDesktop.HDDSize;
in >> myDesktop.numberOfCores;
return in;
}
istream& operator>> (istream &in, laptop &mylaptop)
{
in >> mylaptop.RAM;
in >> mylaptop.CPUSpeed;
in >> mylaptop.HDDSize;
in >> mylaptop.numberOfCores;
in >> mylaptop.screenSize;
return in;
}
istream& operator>> (istream &in, cluster &myCluster)
{
in >> myCluster.RAM;
in >> myCluster.CPUSpeed;
in >> myCluster.HDDSize;
in >> myCluster.numberOfCores;
in >> myCluster.numOfComp;
return in;
}
operator+(computer &myComp)
{
return
If you only want to add up the values common to all the classes that they inherit from computer, you can do it like this:
cluster operator+(const computer& comp1, const computer& comp2)
{
cluster ret;
ret.RAM = comp1.RAM+comp2.RAM;
ret.CPUSpeed = comp1.CPUSpeed+comp2.CPUSpeed;
ret.numberOfCores = comp1.numberOfCores+comp2.numberOfCores;
ret.HDDSize = comp1.HDDSize+comp2.HDDSize;
return ret;
}
int main()
{
laptop laptop1;
desktop desktop1;
desktop desktop2;
cluster mycluster = laptop1+desktop1+desktop2;
return 0;
}
The chained + operators are evaluated from the right leftwards. The function returns a cluster object, which can then be used as the right hand operand for the next addition.