Reputation: 45
I've been trying to overload the << (cout) and >> (cin) operators for awhile now for a class of complex numbers that I was given the prototypes for in a .h file to do.
This is my attempt to do so in the class.cpp file:
std::istream &operator>> (std::istream &in, complex& c) {
double h, j;
in >> h >> j;
c.set(h,j);
return in;
}
std::ostream &operator<<(std::ostream &out, complex c) {
out << c.getReal;
out << c.getImag;
return out;
}
This is really the first time I've seen the std:: istream
and std:: ostream
rather than cout and cin and i'm not really sure how cout <<
and cin >>
are all related
I try testing it on the main.cpp file but i get errors
The >>
should absorb a complex argument into the complex class argument and change the value of private members real
and imag
Not sure if I'm supposed to use my set function here
This is the protype .h file filled I was given:
#ifndef COMPLEX_H
#define COMPLEX_H
class complex {
public:
complex();
complex(double a);
complex(double a, double b);
complex(int a, int b);
void print() const;
void set(double a = 0, double b = 0);
void set(int a = 0, int b = 0);
double getReal() const;
double getImag() const;
void get(double&, double&) const;
complex operator+ (double& x);
complex operator+ (complex&);
complex operator+= (complex&);
complex operator+= (int&);
complex operator++ (int);
complex operator++ ();
complex operator- (double&);
complex operator- (complex&);
complex operator-= (complex&);
complex operator-= (double&);
complex operator-- (int);
complex operator-- ();
complex operator* (complex&);
complex operator* (double&);
complex operator*= (complex&);
complex operator*= (double&);
complex operator/ (complex&);
complex operator/= (complex&);
complex operator/= (double);
complex operator/ (double);
void operator= (const complex&);
bool operator== (complex&);
bool operator!=(complex &c);
friend std::istream &operator>> (std::istream &in, complex& c);
friend std::ostream &operator<<(std::ostream &out, complex c);
/*complex conj() const;
double norm() const;
double modulus() const;
*/
private:
double real;
double imag;
};
#endif // COMPLEX_H
Can someone show me how to properly overload for this?
Ok so I'm now trying for output a + bi :
std::ostream& operator<< (std::ostream& out, complex const& c) {
return out << c.getReal() << "+" << c.getImag() << "i";
}
and for input:
std::istream& operator>> (std::istream& in, complex& c) {
double h, j;
if (in >> h >> "+" >> j >> "i") {
c.set(h, j);
}
return in;
}
However I get the following error when I compile:
This is for line 181 of my complex.cpp file(class complex implementation file) where if (in >> h >> "+" >> j >> "i") {
is located of the above function definition is located:
binary '>>': no operator found which takes a right-hand operand of type 'const char [2]' (or there is no acceptable conversion)
the following are all for line 45(Note each error is separate,total of 7 for this line) of my complex.h file where friend std::istream &operator>> (std::istream &in, complex& c);
protoype is located.
'istream':is not a member of 'std'
syntax error missing ';' before '&'
'istream':'friend' not permitted on data declarations
missing type specifier-int assumed. Note:C++ does not support default-int
unexpected token(s) preceding';'
namespace "std" has no member "istream"
namespace "std" has no member "istream"
the following are for line 46 of my complex.h file where
friend std::ostream &operator<<(std::ostream &out, complex c);
is located
'ostream': is not a member of 'std'
syntax error: missing ';' before '&'
'ostream':'friend' not permitted on data declarations
missing type specifier -int assumed.Note: C++ does not support default-int
unexpected token(s) preceding ';'
namespace "std" has no member "ostream"
namespace "std" has no member "ostream"
I noticed both are the same type of errors. Note I have
#include<iostream>
using namespace std;
both on the complex.cpp file and the main.cpp file
Upvotes: 1
Views: 2937
Reputation: 153802
Let's start with the simple stuff: std::cin
is an instance of a type derived from std::istream
. Similarly, std::cout
is an instance of a type derived from std::ostream
. These stream types are used to have something you can overload the input and output operators for (and you should not try to derive from them to change their behavior - that's done using std::streambuf
). There are other stream types, e.g., std::ifstream
/std::ofstream
(to read from/write to files) and std::istringstream
/std::ostringstream
(to read from/write to strings).
The next thing to look at is your output operator: for starters, you need parenthesis when calling a member function. You'll also need a separator between the two values as otherwise the real and the imaginary part may blend into each other. I'd probably implement the operator as
std::ostream& operator<< (std::ostream& out, complex const& value) {
return out << value.getReal() << " " << value.getImag();
}
The use of a space and no other delimiter may be suboptimal in general but makes reading easier. For an actual implementation of a complex class I might use a format writing real+
imagi
or (
real,
imag)
but these are harder to parse.
Reading values from a stream should always be checked after an attempt to read a value was made. For example, the code could look like this:
std::istream& operator>> (std::istream& in, complex& c) {
double h, j;
if (in >> h >> j) {
c.set(h, j);
}
return in;
}
Except for the missing check the input function looks OK assuming the two values are separated by a space: before attempting to read a value, space is skipped by default with the input operators. If the values are formatted more fancy with some separators, these would need to be separately processed. The code to do so could look like the this:
template <char C>
std::istream& skip_char(std::istream& in) {
if ((in >> std::skipws).peek() != C) {
in.setstate(std::ios_base::failbit);
}
else {
in.ignore();
}
return in;
}
std::istream& (*const open_parenthesis)(std::istream&) = &skip_char<'('>;
std::istream& (*const close_parenthesis)(std::istream&) = &skip_char<')'>;
std::istream& (*const comma)(std::istream&) = &skip_char<','>;
std::istream& operator<< (std::istream& in, complex& c) {
double real, imag;
if (in >> open_parenthesis >> real >> comma >> imag >> close_parenthesis) {
c.set(real, imag);
}
return in;
}
These funny looking entities open_parenthesis
, close_parenthesis
, and comma
are function pointers initialized to point to instance of the function template skip_char
. They have a specific signature which qualifies them as being manipulators. When "reading into" a manipulator, the corresponding function is called with the stream they are "read" from. That is, for example std::cin >> comma
results in a call comma(std::cin)
which is actually a call to skip_char<','>(std::cin)
. However, I guess for this assignment the full-blown approach is a bit of overkill.
Upvotes: 7