Operator overloading questions. (private member issues) - c++

I am doing a tutorial to learn about operator overloading and while writing the code as in the book, i got errors in the following section:
std::ostream &operator<<(std::ostream &outst, const AC_current &c)
{
outst << std::setiosflags(std::ios::fixed)<<std::setprecision(2);
outst << "(" << std::setw(6) << c.mag; //----->'mag' is a private member of 'AC_current'
outst << ", " << std::setw(6) << c.phase<<(char)248<< ") A"; //--->'phase' is a private member of 'AC_current'
return outst;
}
I defined it as a friend function, but its not working. What am I doing wrong?
P.S.This is the complete code.
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
const double Deg2Rad = 2*M_PI/360;
const double Rad2Deg = 360/(2*M_PI);
class AC_current
{
private:
double mag, phase;
double real, imag;
void setRect();
void setPolar();
public:
AC_current(double m=0, double p=0)
{
mag = m; phase = p; setRect();
}
AC_current operator-(const AC_current & c) const;
AC_current operator+(const AC_current & c) const;
AC_current operator*(double) const;
int getCoord();
friend std::istream &operator >> (std::istream &inst, AC_current &c);
friend std::ostream &operator << (std::ostream &outst, AC_current &c);
};
int AC_current::getCoord()
{
int selection;
do
{
std::cout << "\n Select: \n\t1) AC current in polar coordinates ";
std::cout << "\n\t2) AC current in rectangular coordinates ";
std::cout << "\n\t Enter selection: ";
std::cin >> selection;
} while ((selection!=1)&&(selection!=2));
return selection;
}
void AC_current::setRect()
{
real= mag*cos(phase*Deg2Rad);
imag=mag*sin(phase*Deg2Rad);
}
void AC_current::setPolar()
{
mag=sqrt(real*real+imag*imag);
if (!((real==0)&&(imag==0)))
{
phase=atan(imag/real)*Rad2Deg;
}
else
phase=0;
}
AC_current AC_current::operator-(const AC_current &c) const
{
AC_current temp;
double treal, timag;
treal = mag*cos(phase*Deg2Rad)-c.mag*cos(c.phase*Deg2Rad);
timag = mag*sin(phase*Deg2Rad)-c.mag*sin(c.phase*Deg2Rad);
temp.mag = sqrt(treal*treal+timag*timag);
if (!((treal==0)&&(timag==0)))
{
temp.phase = atan(timag/treal)*Rad2Deg;
}else temp.phase=0;
return temp;
}
AC_current AC_current::operator+(const AC_current &c) const
{
AC_current temp;
double treal, timag;
treal = mag*cos(phase*Deg2Rad)+c.mag*cos(c.phase*Deg2Rad);
timag = mag*sin(phase*Deg2Rad)+c.mag*sin(c.phase*Deg2Rad);
temp.mag = sqrt(treal*treal+timag*timag);
if (!((treal==0)&&(timag==0)))
{
temp.phase = atan(timag/treal)*Rad2Deg;
}else temp.phase=0;
return temp;
}
AC_current AC_current::operator*(double r) const
{
AC_current temp;
temp.mag = mag*r;
temp.phase = phase;
temp.setRect();
return temp;
}
std::istream &operator>>(std::istream &inst, AC_current &c)
{
int choice=c.getCoord();
if (choice==1)
{
std::cout << "\nEnter magnitude: ";
inst >> c.mag;
std::cout << "\nEnter phase shift: ";
inst >> c.phase;
c.setRect();
}
else if(choice == 2)
{
std::cout << "\nEnter real part: ";
inst >> c.real;
std::cout << "\nEnter imaginary part: ";
inst >> c.imag;
c.setPolar();
}
return inst;
}
std::ostream &operator<<(std::ostream &outst, const AC_current &c)
{
outst << std::setiosflags(std::ios::fixed)<<std::setprecision(2);
outst << "(" << std::setw(6) << c.mag;
outst << ", " << std::setw(6) << c.phase<<(char)248<< ") A";
return outst;
}
int menu()
{
int selection;
do
{
std::cout << "\n\n\tSelect operation:" << std::endl;
std::cout << "\n\n 1)Add currents" << std::endl;
std::cout << "\n\n 2)Substract currents" << std::endl;
std::cout << "\n\n 3)Multiply current by resistance" << std::endl;
std::cout << "\n\n 4)Exit" << std::endl;
std::cout << "\n\n Enter selection (1-4) => ";
std::cin >> selection ;
} while (selection<1||selection>4);
return selection;
}
int main ()
{
AC_current c1,c2;
int operation;
std::cin >> c1 >> c2;
while (operation !=4) {
operation = menu();
switch (operation) {
case 1:
std::cout << "\n\tc1+c2 = " << (c1+c2);
break;
case 2:
std::cout << "\n\tc1-c2 = " << (c1-c2);
break;
case 3:
double r;
std::cout <<"\nEnter resistance : ";
std::cin >> r;
std::cout << "\n\tc1*R = " << (c1*r);
break;
case 4:
break;
}
}
return 0;
}

Related

why is this code not detecting << operator?

Please explain to me why this is not detecting the << operator.
I tried my best, even tried to overload << on both classes (which is not necessary).
#include<iostream>
using namespace std;
const int MAX = 10;
class Complex;
template<class t>
class stack {
private:
t stk[MAX];
int top;
public:
stack() { top = -1; }
void push(t data) {
if (top == MAX - 1)
cout << "Stack is full.";
else
stk[++top] = data;
}
t pop() {
if (top == -1) {
cout << "Stack is empty.";
return NULL;
}
else {
//return stk[top--];
t data = stk[top];
top--;
return data;
}
}
};
class Complex {
private:
float real, imag;
public:
Complex(float r = 0.0, float i = 0.0) { real = r; imag = i; }
friend ostream& operator << (ostream& s, Complex& c);
};
ostream& operator << (ostream& s, Complex& c) {
s << "(" << c.real << "," << c.imag << ")";
return s;
}
int main() {
stack<int> s1;
s1.push(10);
s1.push(20);
s1.push(30);
s1.push(40);
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
stack<float> s2;
s2.push(3.14f);
s2.push(4.14f);
s2.push(5.14f);
s2.push(6.14f);
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
Complex c1(1.5f, 2.5f), c2(1.5f, 2.5f), c3(1.5f, 2.5f), c4(1.5f, 2.5f);
//cout<<c1;
stack<Complex> s3;
s3.push(c1);
s3.push(c2);
s3.push(c3);
s3.push(c4);
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
return 0;
}
The function signature should be something like:
std::ostream& operator<<(std::ostream& os, const T& obj)
{
// write obj to stream
return os;
}
And the function pop can't return NULL since the type is not the same as t. Fixed code might like:
#include <iostream>
using namespace std;
const int MAX = 10;
class Complex;
template <class t>
class stack {
private:
t stk[MAX];
int top;
public:
stack() { top = -1; }
void push(t data) {
if (top == MAX - 1)
cout << "Stack is full.";
else
stk[++top] = data;
}
t pop() {
if (top == -1) {
cout << "Stack is empty.";
return {}; // May throw, or return std::optional here
} else {
// return stk[top--];
t data = stk[top];
top--;
return data;
}
}
};
class Complex {
private:
float real, imag;
public:
Complex(float r = 0.0, float i = 0.0) {
real = r;
imag = i;
}
friend ostream &operator<<(ostream &s, const Complex &c);
};
ostream &operator<<(ostream &s, const Complex &c) {
s << "(" << c.real << "," << c.imag << ")";
return s;
}
int main() {
stack<int> s1;
s1.push(10);
s1.push(20);
s1.push(30);
s1.push(40);
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
stack<float> s2;
s2.push(3.14f);
s2.push(4.14f);
s2.push(5.14f);
s2.push(6.14f);
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
Complex c1(1.5f, 2.5f), c2(1.5f, 2.5f), c3(1.5f, 2.5f), c4(1.5f, 2.5f);
// cout<<c1;
stack<Complex> s3;
s3.push(c1);
s3.push(c2);
s3.push(c3);
s3.push(c4);
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
return 0;
}
Online demo.
Related question: What are the basic rules and idioms for operator overloading?
It doesn't work because the second parameter should be a const reference
class Complex{
private:
float real,imag;
public:
Complex(float r=0.0,float i=0.0){
real=r;
imag=i;
}
friend ostream& operator<<(ostream& s, const Complex& c);
};
ostream& operator<<(ostream& s, const Complex& c) {
s<<"("<<c.real<<","<<c.imag<<")";
return s;
}
Reason:
The pop function returns an r-value. You can think of an r-value as a nameless object in memory (of course, there is more to it). You cannot put an r-value into an l-value reference. But for a const reference, it does not matter, since you are not going to modify it.
Solution 1:
friend ostream &operator<<(ostream &s, Complex &c); // accepts lvalue - c refers to some external Complex object.
friend ostream &operator<<(ostream &s, Complex &&c); // accepts rvalue - c becomes a normal local variable whose value is the passed rvalue.
Solution 2:
friend ostream &operator<<(ostream &s, const Complex &c); // accepts both

Why is the 'info[]' of the struct records giving errors?

This program uses class and takes the info of employees from a file. I have mentioned the file below too. I have also mentioned the output i received even though there are error. There is something wrong in the output too but I think it is because of the info error that it's getting.
While running this program, I got this error message:
Error: Run-Time Check Failure #2 - Stack around the variable 'info' was corrupted.
There's also this message:
Unhandled exception at 0x00950A89 in employee.exe: Stack cookie instrumentation code detected a stack-based buffer overrun.
// The used file for this program is:
A.Smith 20001 25 40
T.Philip 20002 20 35
S.LOng 20003 15 50
G.Santos 20004 30 30
F.Farkas 20005 22 55
// The output after running even with the errors is:
This week's employee history
Name Id Rate Hours
* A.Smith 20001 $25/h 40h
* T.Philip 20002 $20/h 35h
* S.LOng 20003 $15/h 50h
* G.Santos 20004 $30/h 30h
* F.Farkas 20005 $22/h 55h
This week's payment
Name Payment
* ╠╠╠╠╠╠╠╠ $0 <----------There is this error too
* T.Philip $700
* S.LOng $825
* G.Santos $900
* A.Smith $1000
* The average wages of the employees: $685.00
// The code is:
/*
#include "pch.h"
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string>
#include<iomanip>
*/
using namespace std;
struct records {
char name[50] = {};
char id[5] = {};
int rate = 0;
int hours = 0;
int pay = 0;
};
void take(records array[], const int a);
int calculator(records array[], const int a);
void swap(records array[], const int a);
double Average(records array[], int a);
ifstream infile;
int main()
{
const int n = 5;
This is the first time info is declared:
struct records info[n];
double averageWages;
int overTime = 0, i;
infile.open("Project 3.dat");
cout << "\n This week's employee history \n" << endl;
if (infile.is_open()) {
cout << " Name Id Rate Hours " << endl;
Here take function uses info of the struct:
take(info, n);
cout << endl << endl;
cout << "This week's payment\n" << endl;
cout << " Name Payment" << endl;
Also here other functions use info:
calculator(info, n);
swap(info, n);
for (i = 0; i < n; i++) {
cout << "*" << setw(10) << info[i].name << setw(10) << "$" << info[i].pay << endl;
}
averageWages = Average(info, n);
cout << "\n\n" << "* The average wages of the employees: $" << averageWages << endl << endl;
}
else {
cerr << "Error! file cannot open." << endl;
exit(1);
}
return 0;
}
// Taking records:
void take(records array[], const int a) {
for (int i = 0; i < a; i++) {
while (infile >> array[i].name >> array[i].id >> array[i].rate >> array[i].hours) {
cout << "*" << setw(9) << array[i].name << setw(10) << array[i].id << setw(10) << "$" << array[i].rate << "/h" << setw(10) << array[i].hours << "h " << endl;
}
} infile.close();
}
//swap records to arrange it according to total payment received
void swap(records array[], const int a) {
bool tf; //true or false
do {
tf = false;
for (int i = 0; i < a; i++) {
if (array[i].pay > array[i + 1].pay) {
swap(array[i], array[i + 1]);
tf = true;
}
}
} while (tf);
records temp;
for (int i = 0; i < a - 1; ++i)
{
for (int j = i + 1; j < a; ++j)
{
if (array[i].pay > array[j].pay)
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
}
To calculate average:
double Average(records array[], const int a) {
double total = 0;
double average;
for (int i = 0; i < a; i++) {
total = total + (array[i].pay);
average = total / a;
}
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
return (total / a);
}
// To calculate the salary:
int calculator(records array[], const int a) {
infile.open("Project 3.dat");
if (infile.is_open()) {
for (int i = 0; i < a; i++) {
infile >> array[i].name >> array[i].id >> array[i].rate >> array[i].hours;
if (array[i].hours > 40) {
int overTime = (array[i].hours - 40)*1.5;
array[i].pay = ((array[i].rate) * 40) + (overTime*(array[i].rate));
}
else {
array[i].pay = (array[i].rate)*(array[i].hours);
}
}
for (int i = 0; i < a; i++) {
return (array[i].pay);
}
}
}
It's hard to find all potential problems with that fragmented code, but you'd be better off using std::strings instead of char[]. They are safer and also has a lot of built-in functions. They also work well with misc. functions in the STL.
Your struct records info[n]; will only hold n (5) elements. Use a standard container, like a std::vector instead in case you'd like to add more entries to the file.
Reading and writing to files can usually be done using custom stream operators and all the free functions you have to deal with a number of records could be collected in a class of its own. I've made one record struct and one Records class to demonstrate how they could be used Together.
#include <iostream>
#include <vector>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <numeric>
#include <algorithm>
#include <functional>
struct record {
std::string name{};
std::string id{};
int rate = 0;
int hours = 0;
int pay = 0;
// stream operators for reading/writing a record
friend std::istream& operator>>(std::istream&, record&);
friend std::ofstream& operator<<(std::ofstream&, const record&);
friend std::ostream& operator<<(std::ostream&, const record&);
};
// populate a record from an istream
std::istream& operator>>(std::istream& is, record& r) {
std::string line;
// get a line and check that it's > 30 chars long
if(std::getline(is, line) && line.size()>30) {
// extract the name and remove trailing spaces
r.name = line.substr(0, 30);
auto pos = r.name.find_last_not_of(' ');
if(pos != std::string::npos)
r.name = r.name.substr(0, pos+1);
// put the rest of the line in a stringstream
std::stringstream ss(line.substr(30));
// and extract the rest of the fields
if(ss >> r.id >> r.rate >> r.hours) {
// calculate pay
r.pay = r.rate * r.hours;
} else { // if extraction fails, set the stream in fail mode
is.setstate(std::ios_base::failbit);
}
} else is.setstate(std::ios_base::failbit);
return is;
}
// streaming a record to an ofstream (like a file)
std::ofstream& operator<<(std::ofstream& os, const record& r) {
os << std::setw(30) << std::left << r.name.substr(0, 30) << r.id << " " << r.rate << " " << r.hours << "\n";
return os;
}
// streaming a record to a generic ostream (like std::cout)
std::ostream& operator<<(std::ostream& os, const record& r) {
os << "* " << std::setw(30) << std::left << r.name << std::right << r.id
<< " $" << r.rate << "/h " << r.hours << "h $" << std::setw(4) << r.pay;
return os;
}
class Records { // a class to maintain a number of "record"s
std::vector<record> m_records{}; // stores all "record"s
public:
Records(const std::string& filename) {
record tmp;
std::ifstream e(filename); // open file
// and extract one record at a time and put it in m_records.
while(e>>tmp) m_records.emplace_back(std::move(tmp));
}
// sum on any member in "record"
template <typename field>
auto Sum(field f) const {
return std::accumulate(m_records.begin(), m_records.end(), 0,
[&](int a, const record& b) { return a + (b.*f); });
}
// average of any member in "record"
template <typename field>
auto Average(field f) const {
return static_cast<double>(Sum(f)) / m_records.size();
}
// sorting on any member in "record"
template <typename field, typename T>
void Sort(field f, const T& cmp) {
std::sort(m_records.begin(), m_records.end(),
[&](const record& a, const record& b){ return cmp(a.*f, b.*f); });
}
// return the number of "record" elements
std::vector<record>::size_type size() const { return m_records.size(); }
// access an element via subscript
record& operator[](std::vector<record>::size_type idx) { return m_records[idx]; }
const record& operator[](std::vector<record>::size_type idx) const { return m_records[idx]; }
// iterators to use in for-loops
std::vector<record>::const_iterator cbegin() const noexcept { return m_records.cbegin(); }
std::vector<record>::const_iterator cend() const noexcept { return m_records.cend(); }
std::vector<record>::const_iterator begin() const noexcept { return cbegin(); }
std::vector<record>::const_iterator end() const noexcept { return cend(); }
std::vector<record>::iterator begin() noexcept { return m_records.begin(); }
std::vector<record>::iterator end() noexcept { return m_records.end(); }
// stream operator to show all records
friend std::ostream& operator<<(std::ostream&, const Records&);
};
std::ostream& operator<<(std::ostream& os, const Records& R) {
os << " Name Id Rate Hrs Pay\n";
for(const auto& r : R) std::cout << r << "\n";
os << std::setprecision(2) << std::fixed;
os << "Average pay : $" << std::setw(7) << R.Average(&record::pay) << "\n";
os << " rate : $" << std::setw(7) << R.Average(&record::rate) << "\n";
os << " hours worked: " << std::setw(7) << R.Average(&record::hours) << "h\n";
return os;
}
int main() {
// create a "Records" entity called "info" by reading a file
Records info("Project 3.dat");
// misc sorting and showing the result
std::cout << "Sorted as read from the file:\n";
std::cout << info;
std::cout << "\nSorted according to name:\n";
info.Sort(&record::name, std::less<std::string>());
std::cout << info;
std::cout << "\nSorted according to id:\n";
info.Sort(&record::id, std::less<std::string>());
std::cout << info;
std::cout << "\nSorted according to pay:\n";
info.Sort(&record::pay, std::greater<int>());
// output example using iterators:
for(auto& rec : info) {
std::cout << rec << "\n";
}
std::cout << "\nSorted according to rate:\n";
info.Sort(&record::rate, std::greater<int>());
std::cout << info;
std::cout << "\nSorted according to hours:\n";
info.Sort(&record::hours, std::greater<int>());
std::cout << info;
// example using subscript, operator[]
if(info.size()>2) {
std::cout << "\ninfo[2] = " << info[2] << "\n";
}
}

How can I search for a match through a vector of objects? [closed]

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 4 years ago.
Improve this question
I am building up a program where I create a vector of objects, the input variables that create the object are read from a .txt file. I want to check if the "ID" of the object introduced by the user exists in order to continue.
vector<Producto> vectorProductos;
while(file >> sID >> sDesc >> sUMed >> sFam >> sClass >> dVolumen >> dLongitud >> sPrecio){
vectorProductos.push_back(Producto(sID, sDesc, sUMed,sFam, sClass, dVolumen, dLongitud, stringToDouble(sPrecio)));
iNumProductos++;
}
file.close();
int iNumPartidas;
cout << "iNumPartidas? " << endl;
cin >> iNumPartidas;
for(unsigned int iP = 1; iP <= iNumPartidas; iP++){
cout << endl << "Partida " << iP << ":" << endl;
cout << "Clave de partida:\t";
cin >> sPartida;
for(unsigned int iPrd = 0; iPrd < iNumProductos; iPrd++){
cout << endl << "Clave de producto " << iPrd+1 << ":\t";
cin >> sClave;
if(sClave == vectorProductos[iPrd].getClave()){
cout << endl << "Cantidad:\t";
cin >> iCantProdxP;
}else{
cout << "Producto no existe" << endl;
}
}
}
Producto class
#ifndef Producto_h
#define Producto_h
#include <stdio.h>
#include <string>
#include <iostream>
using namespace std;
class Producto{
protected:
string _sClave, _sDescripcion, _sUMed, _sClass, _sFam;
double _dVolumen, _dPrecio, _dLongitud;
public:
Producto();
Producto(string, string, string, string, string, double, double, double);
inline string getClave(){return _sClave;}
inline string getDescripcion(){return _sDescripcion;}
inline string getUMed(){return _sUMed;}
inline string getFam(){return _sFam;}
inline string getClass(){return _sClass;}
inline double getVol(){return _dVolumen;}
inline double getPrecio(){return _dPrecio;}
inline double getLongitud(){return _dLongitud;}
inline void setClave(string sClave){_sClave = sClave;}
inline void setDescripcion(string sDescripcion){_sDescripcion = sDescripcion;}
inline void setUMed(string sUMed){_sUMed = sUMed;}
inline void setFam(string sFam){_sFam = sFam;}
inline void setClass(string sClass){_sClass = sClass;}
inline void setVol(double dVolumen){_dVolumen = dVolumen;}
inline void setPrecio(double dPrecio){_dPrecio = dPrecio;}
inline void setLongitud(double dLongitud){_dLongitud = dLongitud;}
void toString();
};
Producto::Producto(){
_sClave = "";
_sDescripcion = "Falta descripcion";
_sUMed = "N/A";
_sFam = "Sin Familia";
_sClass = "Sin clase";
_dVolumen = 0.0;
_dPrecio = 0.0;
_dLongitud = 0.0;
}
Producto::Producto(string sClave, string sDescripcion, string sUMed, string sFam, string sClass, double dVolumen, double dLongitud, double dPrecio){
_sClave = sClave;
_sDescripcion = sDescripcion;
_sUMed = sUMed;
_sFam = sFam;
_sClass = sClass;
_dVolumen = dVolumen;
_dPrecio = dPrecio;
_dLongitud = dLongitud;
}
void Producto::toString(){
cout << "\nProducto: " << _sClave;
cout << "\nDescripcion: " << _sDescripcion;
cout << "\nUnidad de Medida: " << _sUMed;
cout << "\nFamilia: " << _sFam;
cout << "\nClase: " << _sClass;
cout << "\nVolumen: " << _dVolumen;
cout << "\nLongitud: " << _dLongitud;
cout << "\nPrecio: " << _dPrecio;
cout << endl;
}
What I need is to see if that "ID" that the user is going to input actually exists and if not mark error. When I run my program I have to type in the ID of the first product to match it with the index number of the loop, and that is the only way it works but I need the program to match it with any "Producto" regardless of the position or index.
In your inner loop, you are prompting the user for an ID on every loop iteration and then comparing that ID only to the product at the index of the current loop iteration. You need to prompt the user one time BEFORE entering the loop and then compare the ID to every product until you find a match:
std::cout << endl << "Clave de producto:\t";
std::cin >> sClave;
bool found = false;
for (std::size_t iPrd = 0; iPrd < vectorProductos.size(); ++iPrd)
{
if (sClave == vectorProductos[iPrd].getClave())
{
found = true;
break;
}
}
if (found) {
// do something ...
}
else {
std::cout << "Producto no existe" << std::endl;
}
Alternatively, you should use std::find_if() instead of searching manually, eg:
Producto.h
#ifndef Producto_h
#define Producto_h
#include <iostream>
#include <string>
class Producto
{
protected:
std::string _sClave, _sDescripcion, _sUMed, _sClass, _sFam;
double _dVolumen, _dPrecio, _dLongitud;
public:
Producto();
Producto(std::string, std::string, std::string, std::string, std::string, double, double, double);
std::string getClave() const { return _sClave; }
std::string getDescripcion() const { return _sDescripcion; }
std::string getUMed() const { return _sUMed; }
std::string getFam() const { return _sFam; }
std::string getClass() const { return _sClass; }
double getVol() const { return _dVolumen; }
double getPrecio() const { return _dPrecio; }
double getLongitud() const { return _dLongitud; }
void setClave(std::string sClave) { _sClave = sClave; }
void setDescripcion(std::string sDescripcion) { _sDescripcion = sDescripcion; }
void setUMed(std::string sUMed) { _sUMed = sUMed; }
void setFam(std::string sFam) { _sFam = sFam; }
void setClass(std::string sClass) { _sClass = sClass; }
void setVol(double dVolumen) { _dVolumen = dVolumen; }
void setPrecio(double dPrecio) { _dPrecio = dPrecio; }
void setLongitud(double dLongitud) { _dLongitud = dLongitud; }
std::string toString() const;
};
std::istream& operator>>(std::istream &in, Producto &p);
#endif
Producto.cpp
#include "Producto.h"
#include <sstream>
std::istream& operator>>(std::istream &in, Producto &p)
{
std::string sID, sDesc, sUMed, sFam, sClass, sPrecio;
double dVolumen, dLongitud;
if (in >> sID >> sDesc >> sUMed >> sFam >> sClass >> dVolumen >> dLongitud >> sPrecio)
{
p.setClave(sID);
p.setDescripcion(sDesc);
p.setUMed(sUMed);
p.setFam(sFam);
p.setClass(sClass);
p.setVol(dVolumen);
p.setLongitud(dLongitud);
p.setPrecio(stringToDouble(sPrecio));
}
return in;
}
Producto::Producto() :
_sClave(),
_sDescripcion("Falta descripcion"),
_sUMed("N/A"),
_sFam("Sin Familia"),
_sClass("Sin clase"),
_dVolumen(0.0),
_dPrecio(0.0),
_dLongitud(0.0)
{
}
Producto::Producto(std::string sClave, std::string sDescripcion, std::string sUMed, std::string sFam, std::string sClass, double dVolumen, double dLongitud, double dPrecio) :
_sClave(sClave),
_sDescripcion(sDescripcion),
_sUMed(sUMed),
_sFam(sFam),
_sClass(sClass),
_dVolumen(dVolumen),
_dPrecio(dPrecio),
_dLongitud(dLongitud)
{
}
std::string Producto::toString() const
{
std::ostringstream oss;
oss << "Producto: " << _sClave;
oss << "\nDescripcion: " << _sDescripcion;
oss << "\nUnidad de Medida: " << _sUMed;
oss << "\nFamilia: " << _sFam;
oss << "\nClase: " << _sClass;
oss << "\nVolumen: " << _dVolumen;
oss << "\nLongitud: " << _dLongitud;
oss << "\nPrecio: " << _dPrecio;
return oss.str();
}
Main
#include <vector>
#include <algorithm>
#include "Producto.h"
std::vector<Producto> vectorProductos;
Producto p;
while (file >> p) {
vectorProductos.push_back(p);
}
file.close();
...
std::string sClave;
std::cout << std::endl << "Clave de producto:\t";
std::cin >> sClave;
auto iter = std::find_if(vectorProductos.begin(), vectorProductos.end(),
[&](const Producto &p){ return (p.getClave() == sClave); });
if (iter == vectorProductos.end()) {
std::cout << "Producto no existe" << std::endl;
}
else {
std::cout << "Producto existe" << std::endl;
// use *iter as needed...
std::cout << iter->toString() << std::endl;
// if you need the index of the found product, you can use:
// auto index = std::distance(vectorProductos.begin(), iter);
}
...

C++ Operator Overloading always false

So I was able to fix it, however, the operator doesn't seem to be comparing them both since I always get false. There seems to be an error with the pLoan where it is not comparing both of them.
My code is
#include <string>
#include <iostream>
#include <sstream>
using namespace std;
//Vehicle Class
class Vehicle {
public:
Vehicle();
void setPrice(double a);
void setMpg(int a);
double getPrice() const;
int getMpg() const;
void printVehicle() const;
Vehicle(double price, int mpg);
private:
double price;
int mpg;
};
//Loan Class
class Loan {
public:
void setBank(string a);
void setLoan(double a);
string getBank() const;
double getLoan() const;
void printLoan() const;
Loan(string bank = "", double loan = 0);
private:
string bank;
double loan;
};
//Car Class
class Car : public Vehicle {
public:
Car(double price = 0, int mpg = 0, string bank = "", double loan = 0, string name = "", int element = 0);
void setName(string a);
void setLoan(string b, double l, int element);
string getName() const;
void printFull() const;
void setNbrOfLoans(int a);
int getNbrOfLoans() const;
Loan* getpLoan() const;
~Car();
private:
string name;
Loan* pLoan;
int nbrOfLoans;
};
bool operator==(const Car &car1, const Car &car2) {
Loan* pLoan1 = car1.getpLoan();
Loan* pLoan2 = car2.getpLoan();
return ((car1.getPrice() == car2.getPrice()) && (car1.getMpg() == car2.getMpg()) && (car1.getName() == car2.getName())
&& (car1.getNbrOfLoans() == car2.getNbrOfLoans()) &&
(pLoan1[0].getBank() == pLoan2[0].getBank()) && (pLoan1[0].getLoan() == pLoan2[0].getLoan()));
}
//Main
int main() {
Car car1(24800, 22, "Citi", 21600, "Mustang", 1);
Car* pCar1 = &car1;
pCar1->setLoan("Citi", 21600, 0);
pCar1->printFull();
pCar1->setNbrOfLoans(1);
Car car2;
Car* pCar2 = &car2;
cout << boolalpha;
cout << "Enter the price of the car: ";
double price;
cin >> price;
pCar2->setPrice(price);
cout << "Enter the mpg: ";
int mpg;
cin >> mpg;
pCar2->setMpg(mpg);
cout << "Enter the name of the car: ";
string name;
cin >> name;
pCar2->setName(name);
string bank;
double loan;
int index;
cout << "Enter the amount of loans you obtained: ";
cin >> index;
pCar2->setNbrOfLoans(index);
for (int i = 0; i < index; i++)
{
cout << "Enter the name of bank " << i + 1 << ": ";
cin >> bank;
cout << "Enter the amount of loan " << i + 1 << ": ";
cin >> loan;
pCar2->setLoan(bank, loan, i);
}
if (pCar1 == pCar2)
cout << "Cars are the same. ";
else
cout << "Cars are not the same. ";
cout << endl;
pCar2->printFull();
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////
//Vehicle class function definitions
////////////////////////////////////////////////////////////////////////////////////////
Vehicle::Vehicle() {
price = 0;
mpg = 0;
}
Vehicle::Vehicle(double price, int mpg) {
price = price;
mpg = mpg;
}
void Vehicle::setPrice(double a) {
price = a;
}
void Vehicle::setMpg(int a) {
mpg = a;
}
double Vehicle::getPrice() const {
return price;
}
int Vehicle::getMpg() const {
return mpg;
}
void Vehicle::printVehicle() const {
cout << "Price: " << price << endl;
cout << "MPG: " << mpg << endl;
}
////////////////////////////////////////////////////////////////////////////////////////
//Loan Class function definitions
///////////////////////////////////////////////////////////////////////////////////////
Loan::Loan(string bank, double loan) {
Loan::bank = bank;
Loan::loan = loan;
}
void Loan::setBank(string a) {
bank = a;
}
void Loan::setLoan(double a) {
loan = a;
}
string Loan::getBank() const {
return bank;
}
double Loan::getLoan() const {
return loan;
}
void Loan::printLoan() const {
cout << "Bank: " << bank << endl;
cout << "Loan: " << loan << endl;
}
////////////////////////////////////////////////////////////////////////////////////
//Car Class function definitions
////////////////////////////////////////////////////////////////////////////////////
Car::Car(double price, int mpg, string bank, double loan, string name, int element) : Vehicle(price, mpg)
{
nbrOfLoans = element;
Car::name = name;
setMpg(mpg);
setPrice(price);
pLoan = new Loan[nbrOfLoans];
}
Loan* Car::getpLoan() const{
return pLoan;
}
void Car::setName(string a) {
name = a;
}
void Car::setLoan(string b, double l, int element) {
pLoan[element].setBank(b);
pLoan[element].setLoan(l);
}
string Car::getName() const {
return name;
}
int Car::getNbrOfLoans() const {
return nbrOfLoans;
}
void Car::setNbrOfLoans(int a) {
nbrOfLoans = a;
if (pLoan != NULL)
delete[] pLoan;
pLoan = new Loan[nbrOfLoans];
}
void Car::printFull() const {
cout << endl << "Car name: " << name << endl;
cout << "Price: " << getPrice() << endl;
cout << "MPG: " << getMpg() << endl;
for (int i = 0; i < nbrOfLoans; i++)
{
cout << "Loan #" << i + 1 << "." << endl;
cout << "Bank: " << pLoan[i].getBank();
cout << endl;
cout << "Loan amount: " << pLoan[i].getLoan();
cout << endl;
}
}
Car::~Car() {
delete[] pLoan;
}
Output:
IS always cars are not the same even when they are
Your main code is not calling your operator ==:
if (pCar1 == pCar2)
cout << "Cars are the same. ";
else
cout << "Cars are not the same. ";
here you're comparing the two pointers. To compare the two pointed-to objects you need
if (*pCar1 == *pCar2) ...
One more error:
pCar1->setLoan("Citi", 21600, 0);
pCar1->printFull();
pCar1->setNbrOfLoans(1);
setNbrOfLoans must be located before setLoan:
pCar1->setNbrOfLoans(1);
pCar1->setLoan("Citi", 21600, 0);
pCar1->printFull();

Access Elements of Vector - C++

I have the following class:
class Friend
{
public:
Friend();
~Friend(){}
void setName(string friendName){ name = friendName; }
void setAge(int friendAge) { age = friendAge; }
void setHeight(int friendHeight) { height = friendHeight; }
void printFriendInfo();
private:
string name;
int age;
float height;
};
//implementations
Friend::Friend()
{
age = 0;
height = 0.0;
}
//printing
void Friend::printFriendInfo()
{
cout << "Name : " << name << endl;
cout << "Age : " << age << endl;
cout << "Height : " << height << endl << endl;
}
And At this moment I can introduce the values in a vector, like this:
std::vector<Friend> regist(4, Friend());
regist[1].setAge(15);
regist[1].setHeight(90);
regist[1].setName("eieiei");
regist[2].setAge(40);
regist[2].setHeight(85);
regist[2].setName("random");
In debug, this solution works fine. But now I am trying to print the vector. So far without success.
for (int i = 0; i < regist.size(); i++) {
cout << regist[i]; //<-- error here
cout << '\n';
}
You might redesign a bit (in essence):
#include <iostream>
class Friend
{
public:
Friend();
// A more general name, const, and taking a stream.
void write(std::ostream&) const;
private:
std::string name;
int age;
float height;
};
Friend::Friend()
{
age = 0;
height = 0.0;
}
void Friend::write(std::ostream& stream) const
{
stream << "Name : " << name << std::endl;
stream << "Age : " << age << std::endl;
stream << "Height : " << height << std::endl << std::endl;
}
// Forward to the member function
inline std::ostream& operator << (std::ostream& stream, const Friend& object) {
object.write(stream);
return stream;
}
int main() {
Friend f;
std::cout << f;
}
Just call the printFriendInfo() member function:
for (int i = 0; i < regist.size(); i++) {
regist[i].printFriendInfo();
}
For
cout << regist[i];
to work, add a few accessor functions in Friend
string getName() const { return name; }
int getAge() const { return age; }
float getHeight() const { return height; }
and implement an overloaded operator<< function:
std::ostream& operator<<(std::ostream& out, Friend const& f)
{
out << "Name : " << f.getName() << std::endl;
out << "Age : " << f.getAge() << std::endl;
out << "Height : " << f.getHeight() << std::endl;
return out;
}