Print out inherited structured list c++ - c++

If I have this code
struct Unit{
int coef; //coefficient
int exp; //exponent
};
class Func: private std::list<Unit>{
public:
Func();
friend std::ostream& operator<<(std::ostream &, Func);
};
How do I print it out?
I tried using the concept from here: http://www.cplusplus.com/forum/beginner/5074/
But without success:
ostream& operator<<(ostream &output, Func &pol)
{
list<Unit>::iterator i;
for( i = pol.begin(); i != pol.end(); ++i)
{
Unit test = *i;
output << test.coef << " ";
}
return output;
}
And do I initialize it correctly?
Func::Func()
{
Unit test;
test.coef = 0;
test.exp = 0;
Func::push_back(test);
}
Sorry. New to this about inheritance. Though it wasn't hard when it was about the classes I made myself.
Updated code:
struct Unit{
int coef; //coefficient
int exp; //exponent
Unit():coef(0),exp(0){}
};
class Func : public std::list<Unit>{
public:
Func();
friend std::ostream& operator<<(std::ostream &, const Func &);
};
Func::Func()
{
Unit test;
Func::push_back(test);
}
ostream& operator <<(std::ostream &output, const Func& pol)
{
for (list<Unit>::const_iterator i = pol.begin(); i != pol.end(); output << i->coef << " " << i->exp << " ", ++i);
return output;
}

It is not clear for me what do you want to do. Is is a requirement that you inherit from an STL list? I wouldn't do it.
But this at least would be a solution.
struct Unit{
int coef; //coefficient
int exp; //exponent
};
std::ostream& operator<<(std::ostream &os, Unit const& v)
{
os << v.coef << " " << v.exp << std::endl;
return os;
}
int main()
{
std::list<Unit> myList;
Unit element;
element.coef = 0;
element.exp = 0;
myList.push_back(element);
std::ostringstream os;
for (std::list<Unit>::const_iterator it = myList.begin(); it != myList.end(); ++it)
{
os << *it;
}
std::cout << os.str() << std::endl;
}
With C++11 this could be implemented much nicer, but I don't know what compiler you are using. I did not compile it so far, just hacked it down; so sorry for syntax errors.

First, regarding your printing. You can do it a number of ways, the most robust being defining free operators for each type. Such as:
struct Unit{
int coef; //coefficient
int exp; //exponent
};
std::ostream& operator <<(std::ostream& os, const Unit& unit)
{
os << unit.coef << "X^" << unit.exp;
return os;
}
The function is a little more complex. You would be better served to use the list as a member variable and provide an operator for stream insertion for that class. Such as:
#include <iostream>
#include <iterator>
#include <list>
#include <cstdlib>
struct Unit
{
int coef; //coefficient
int exp; //exponent
Unit(int coef, int exp=0)
: coef(coef), exp(exp)
{}
friend std::ostream& operator <<(std::ostream&, const Unit&);
};
std::ostream& operator <<(std::ostream& os, const Unit& unit)
{
os << unit.coef << "X^" << unit.exp;
return os;
}
class Func
{
public:
std::list<Unit> units;
friend std::ostream& operator <<(std::ostream&, const Func&);
};
std::ostream& operator <<(std::ostream& os, const Func& func)
{
std::copy(func.units.begin(), func.units.end(),
std::ostream_iterator<Unit>(os, " "));
return os;
}
int main()
{
Func func;
func.units.push_back(Unit(3, 2));
func.units.push_back(Unit(2, 1));
func.units.push_back(Unit(1, 0));
std::cout << func << endl;
return EXIT_SUCCESS;
}
Output
3X^2 2X^1 1X^0
Note: I did NOT properly hide members, provide accessors, etc. That I leave to you, but the general idea on how to provide output-stream operators should be obvious. You could significantly further enhance the output operator for a `Unit by:
Not printing exponents of 1
Only printing the coefficient for exponents of 0 (no X),
Not printing a 1 coefficient of any term with an exponent greater than 0
Not printing anything for terms with 0 coefficients.
These tasks I leave to you.

Related

Getting error when overloading << operator

I have a Class called "Vector". It consists of two private fields: std::vector<double> coordinates and int len. Methoddim() returns len.
I am overloading operator << like that:
friend std::ostream& operator<<(std::ostream& os, Vector& vec )
{
std:: cout << "(";
for ( int i = 0; i < vec.dim(); i++ ) {
if ( i != vec.dim()-1){
os << vec[i] << ", ";
} else {
os << vec[i];
}
}
os << ')';
return os;
}
An operator + like that:
friend Vector operator +(Vector& first, Vector& second)
{
if(first.dim() != second.dim()){
throw std::length_error{"Vectors must be the same size"};
}else {
Vector localVec(first.dim()); // same as {0,0,0...,0} - first.dim() times
for (int i = 0; i < first.dim(); i++){
localVec[i] = first[i] + second[i];
}
return localVec;
}
}
And operator [] like that:
double& operator[](int index)
{
return this->coordinates[index];
}
And here's the problem:
Vector x{1,2,4};
Vector y{1,2,3};
Vector z = x + y;
std:: cout << z; // it works perfectly fine - (2, 4, 7)
std:: cout << x + y; // it gives me an error
could not match 'unique_ptr<type-parameter-0-2, type-parameter-0-3>' against 'Vector'
operator<<(basic_ostream<_CharT, _Traits>& __os, unique_ptr<_Yp, _Dp> const& __p)
It seems to me that this error is related to parameter Vector& vec , but I don't know whether it's right and what should I do to fix it. If anyone could give me a hint (or tell me what I should read more about) - I would be very grateful.
Here's full code:
class Vector
{
private:
std::vector <double> coordinates;
int len;
public:
Vector(): len{0}, coordinates{} {};
Vector(std::initializer_list <double> coordinates_): len{static_cast <int>( coordinates_.size())}, coordinates{coordinates_} {}
Vector(int len) : len{len} {
for(int i = 0; i < len; i++){
coordinates.push_back(0);
}
}
int dim() const
{
return this->len;
}
double& operator[](int index)
{
return this->coordinates[index];
}
friend std::ostream& operator<<(std::ostream& os, Vector& vec )
{
std:: cout << "(";
for ( int i = 0; i < vec.dim(); i++ ) {
if ( i != vec.dim()-1){
os << vec[i] << ", ";
} else {
os << vec[i];
}
}
os << ')';
return os;
}
friend Vector operator +(Vector& first, Vector& second)
{
if(first.dim() != second.dim()){
throw std::length_error{"Vectors must be the same size"};
}else {
Vector localVec(first.dim());
for (int i = 0; i < first.dim(); i++){
localVec[i] = first[i] + second[i];
}
return localVec;
}
}
};
friend std::ostream& operator<<(std::ostream& os, Vector& vec)
This signature doesn't accept rvalues, and this is why the error happens for your temporary result here:
std:: cout << x + y;
Change the second parameter into const Vector& vec or provide an overload with an r-value reference parameter.
friend std::ostream& operator<<(std::ostream& os, const Vector& vec);
A temporary cannot bind to a non-const reference argument. You are missing const in at least two places. Most importantly here:
friend std::ostream& operator<<(std::ostream& os, const Vector& vec )
// ^^
And there should a const overload of operator[]

How to overload << for a vector of structures

I'm having trouble with the syntax for a homework program. The prompt is to overload an inserter in such a way that it can properly execute the program fragment:
for (int i = 0; i < v.size(); ++i)
cout << v[i] << endl;
cout << endl;
So, this is what I have so far, but I still get an error at the cout << v[i] statement (Invalid operands to binary expression):
unsigned int seed;
struct node
{
int integer;
double value;
};
double random(unsigned int &seed);
void initialize_vector(vector<node> &v);
template<typename T>
void print_vector(const vector<T> &v);
template<typename T>
ostream &operator <<(ostream &out, const vector<T> &v);
template<typename T>
void output(ostream &out, const vector<T> &v);
int main()
{
vector<node> v(10);
initialize_vector(v);
print_vector(v);
return 0;
}
double random(unsigned int &seed)
{
const int MODULUS = 15749;
const int MULTIPLIER = 69069;
const int INCREMENT = 1;
seed = ((MULTIPLIER * seed) + INCREMENT) % MODULUS;
return double(seed) / double(MODULUS);
}
void initialize_vector(vector<node> &v)
{
for (int i = 0; i < v.size(); ++i)
{
v[i].integer = int (11 * random(seed));
v[i].value = double (11 * random(seed));
}
}
template<typename T>
void print_vector(const vector<T> &v)
{
for (int i = 0; i < v.size(); ++i)
cout << v[i] << endl;
cout << endl;
}
template<typename T>
ostream &operator <<(ostream &out, const vector<T> &v)
{
output(out, v);
return (out);
}
template<typename T>
void output(ostream &out, const vector<T> &v)
{
cout << v.integer;
cout << setprecision(2) << fixed << setw(6) << v.value;
}
I've tried passing node instead of T, along with passing with and without const references for the last 3 functions, so again I assume my syntax in the void output function is wrong somehow. Any help or points in the right direction would be greatly appreciated.
*Note: I can't change the ostream &operator function.
cout << v[i] << endl;
If v is a vector of node, then you need one more function to overload operator << for a node
ostream &operator <<(ostream &out, const node &n)
{
out << n.interger << " " << n.value;
return out;
}

Overload operator<<

I would like to overload operator<< like this:
ostringstream oss;
MyDate a(2000, 1, 2);
oss << dateFormat("%Y/%m/%d") << a;
assert(oss.str() == "2000-01-02");
so that the date at a will be formatted to specific format. How to achieve this?
In order to store custom state in a stream, you need to use the xalloc static function to get a unique index, and then either pword to get a pointer at that index (allocated specifically for each stream it is used on), or iword to get an integer at that index(allocated specifically for each stream it is used on). In your case, you will probably want pword. You can use the pointer returned by pword to point to a dynamically allocated object which stores the formatting information.
struct DateFormatter
{
// The implementation of this class (e.g. parsing the format string)
// is a seperate issue. If you need help with it, you can ask another
// question
static int xalloc_index;
};
int DateFormatter::xalloc_index = std::ios_base::xalloc();
void destroy_date_formatter(std::ios_base::event evt, std::ios_base& io, int idx)
{
if (evt == std::ios_base::erase_event) {
void*& vp = io.pword(DateFormatter::xalloc_index);
delete (DateFormatter*)(vp);
}
}
DateFormatter& get_date_formatter(std::ios_base& io) {
void*& vp = io.pword(DateFormatter::xalloc_index);
if (!vp) {
vp = new DateFormatter;
io.register_callback(destroy_date_formatter, 0);
}
return *static_cast<DateFormatter*>(vp);
}
std::ostream& operator<<(std::ostream& os, const DateFormatter& df) {
get_date_formatter(os) = df;
return os;
}
std::ostream& operator<<(std::ostream& os, const MyDate& date)
{
DateFormatter& df = get_date_formatter(os);
// format output according to df
return os;
}
int main() {
MyDate a ( 2000, 1, 2 );
std::cout << DateFormatter("%Y/%m/%d") << a;
}
This is the standard method. It is terrible, in my opinion. I much prefer an alternative approach, which is to pass the date object together with the formatting as a single object. For example:
class DateFormatter
{
const MyDate* date;
std::string format_string;
DateFormatter(const MyDate& _date, std::string _format_string)
:date(&_date)
,format_string(_format_string)
{}
friend std::ostream& operator<<(std::ostream& os, const DateFormatter& df) {
// handle formatting details here
return os;
}
};
int main() {
MyDate a ( 2000, 1, 2 );
std::cout << DateFormatter(a, "%Y/%m/%d");
}
Or you can do something like that (using static variable):
#include <iostream>
struct MyDate
{
MyDate(int y, int m, int d): year{y}, month{m}, day{d} {}
int year{};
int month{};
int day{};
};
class DateFormatter
{
public:
DateFormatter(const std::string & format)
{
format_ = format;
}
static const std::string & format()
{
return format_;
}
private:
static std::string format_;
};
std::string DateFormatter::format_ = {"Default Format"};
std::ostream & operator<< (std::ostream & stream, const DateFormatter &)
{
return stream;
}
std::ostream & operator<< (std::ostream & stream, const MyDate & date)
{
auto currentFormat = DateFormatter::format();
// some code using current format ...
return stream << currentFormat << " - " << date.year << "/" << date.month << "/" << date.day;
}
int main(void)
{
MyDate date{2016,4,18};
std::cout << date << std::endl;
std::cout << DateFormatter("New format") << date << std::endl;
return 0;
}

Macro Overloading with Different Signatures

Is it possible to overload macros that can perform different operators (=, +=, -=, ++, --, etc) with the same macro name?
I would like to achieve something like this:
int main() {
LOG_STAT("hello") << "world";
LOG_STAT("hello") = 5;
LOG_STAT("hello") += 10;
}
I tried the following and the issue I am having is that I can not redeclare the macro LOG_STAT as it has already been defined. Sample code below, hopefully you get the idea.
#define LOG_STAT(x) Stat(x).streamAdd()
#define LOG_STAT(x) Stat(x).add() // redeclare error here
class Stat {
public:
Stat(const char *type_ ) : type(type_) {}
~Stat(){ std::cout << type << " " << stream.str().c_str() << " " << number << std::endl;}
int& add() { return number; }
std::ostringstream& streamAdd() { return stream; }
const char * type;
int number;
std::ostringstream stream;
};
Create operators for your class:
Stat& Stat::operator += (int rhs)
{
number += rhs;
return *this;
}
Stat operator + (const Stat& lhs, int rhs)
{
Stat res(lhs);
res += rhs;
return res;
}
template <typename T>
Stat& operator << (Stat& stat, const T&value)
{
stat.stream << value;
return stat;
}
Then you may directly use
Stat("hello") << "world";
Stat("hello") = 5;
Stat("hello") += 10;
(You may still use your MACRO with #define LOG_STAT Stat)

Complex class [PrintMax]

So I am working on "TEMPLATES" and I'm required to make a 3 attempt of a function called PrintMax -it's obvious what it does-, to print the maximum element in an array of 3 elements, each attempt is for a different data type in this array -double/int/complex-. So I'm required to first, create the class Complex, and its required operator overloads, after that I use the PrintMax function as template function to work on the 3 types of arrays.
The problem here lies within the 3rd array of course, I can't write the elements of Complex into the array in this for ( a + bi ), because this is my class Complex :
class Complex
{
private :
int imaginary;
int real;
public:
Complex (int = 0, int = 0);
~Complex ();
int getImaginary();
int getReal();
void setImagniary(int i);
void setReal (int r);
bool operator > (Complex&);
};
You can notice, I overloaded operator > to check, but I also have a little problem besides not being able to write the elements in that way, the second problem is I can't -or sleepy and my brain is dying- calculate which is maximum in this array of Complex numbers :
// Input: Complex Array
// 1+3i, 2+4i, 3+3i
// Expected Output: 2+4i
So I want to assign them in the array with this form : Arr[3] = {1+3i, 2+4i, 3+3i};
Why is that the expected output, why not 3+3i ?
Thanks for reading ~
It seems to me that you are looking for something like:
template <typename T> void PrintMax(T array[])
{
// It is assumed that array has 3 elements in it.
std::cout <<
array[0] > array[1] ?
(array[0] > array[2] ? array[0] : array[2]) :
(array[1] > array[2] ? array[1] : array[2])
std::endl;
}
You could use something like the following. Note that there are no range checks in the code, it is just to demonstrate a way how you could solve your problem.
Plus i would suggest you to use a container (eg. std::vector) instead of plain arrays.
#include <algorithm>
#include <cmath>
#include <iostream>
class Complex {
private:
int imaginary;
int real;
public:
Complex(int r, int i) :
imaginary(i), real(r) {
}
~Complex() {
}
int getImaginary() const {
return imaginary;
}
int getReal() const {
return real;
}
void setImaginary(int i) {
imaginary = i;
}
void setReal(int r) {
real = r;
}
double getAbsolut() const {
return std::abs(std::sqrt(std::pow(imaginary, 2) + std::pow(real, 2)));
}
friend bool operator<(const Complex& lhs, const Complex& rhs);
friend std::ostream& operator<<(std::ostream& stream,
const Complex& complex);
};
bool operator<(const Complex& lhs, const Complex& rhs) {
return lhs.getAbsolut() < rhs.getAbsolut();
}
std::ostream& operator<<(std::ostream& stream, const Complex& complex) {
stream << "Complex(" << complex.real << "+" << complex.imaginary
<< "i)";
return stream;
}
template<int size, class T>
void getMax(const T arr[]) {
T max_value = arr[0];
for (size_t i = 1; i < size; ++i) {
max_value = std::max(max_value, arr[i]);
}
std::cout << "max: " << max_value << std::endl;
}
int main(int argc, char **argv) {
Complex arr_complex[] = { Complex(3, 3), Complex(2, 4), Complex(1, 3) };
int arr_int[] = { 3, 5, 1 };
double arr_double[] = { 2.3, 5.6, 9.1 };
getMax<3>(arr_complex);
getMax<3>(arr_int);
getMax<3>(arr_double);
return 0;
}