Troube overloading operators

Z

Zenon

Folks,
I am having a terrible time overloading operators. I have tried what
I thought was the correct way, I tried the cheating (friend
declarations), all to no avail. Sorry for posting tons of code but I
really need help.

thanks,

Zenon


#ifndef Rational__hpp
#define Rational__hpp

#include<iostream>
#include<iomanip>
#include <cstring>
#include <cmath>
#include <sstream>
#include <fstream>

class Rational
{
// Define data members
int numerator;
int denominator;

// define function prototypes
public:
Rational::Rational(int num, int denom); // Creates a fraction
Rational::Rational(); // Default constructor
Rational::~Rational(); // Default destructor
void Rational::signAdjuster();
int Rational::reducer(); // helper function to reduce fracion if
possible
int Rational::reducer(int numerator, int denominator); // helper
function to reduce fracion if possible


Rational Rational::eek:perator += (const Rational& fraction);
Rational Rational::eek:perator -= (const Rational& fraction);
Rational Rational::eek:perator *= (const Rational& fraction);
Rational Rational::eek:perator /= (const Rational& fraction);

friend const Rational operator << (std::eek:stream& os, const Rational&
fraction);

friend const Rational operator + (const Rational& lhs, const
Rational& rhs);
friend const Rational operator - (const Rational& lhs, const
Rational& rhs);
friend const Rational operator * (const Rational& lhs, const
Rational& rhs);
friend const Rational operator / (const Rational& lhs, const
Rational& rhs);

// friend const Rational operator << (std::eek:stream& os, const
Rational& fraction);

// Rational Rational::eek:perator + (const Rational& lhs, const Rational&
rhs);
// Rational Rational::eek:perator + (const Rational& lhs, const Rational&
rhs);
/* Rational::eek:perator - (const Rational lhs, const Rational rhs);
Rational::eek:perator * (const Rational lhs, const Rational rhs);
Rational::eek:perator / (const Rational lhs, const Rational rhs);
*/
Rational::eek:perator double(); // Typecast to double
Rational::string(); // Typecast to string

/* bool Rational::get(istream& is);
void Rational::put(ostream& os);*/


};
//std::eek:stream& operator<< (std::eek:stream& os, const Rational&
fraction); // Output
std::istream& operator>> (std::istream& is, const Rational& fraction);
// Input

#endif


#include <cstring>
#include <cmath>
#include<iostream>
#include <fstream>
#include <vector>
#include <iomanip>
#include <sstream>
#include "Rational.hpp"

using namespace std;

Rational::Rational(int num, int denom) // Set a fractions numerator
and denominator
{
numerator = num;
denominator = denom;
cout << "constructor numerator " + num ;

signAdjuster();
}

Rational::Rational() {} // Default constructor

Rational::~Rational() {} // Destructor

// std::eek:perator <<(std::eek:stream& os, const Rational& fraction); //
Output

/* Rational::eek:stream& operator <<(std::eek:stream& os, const Rational&
fraction) // Output
{

os << setw(0) << numerator << " / " << denominator << "\n";
// fraction.put(os);
// Rational::put(os);
}*/

/* std::istream& operator >>(std::istream& is, const Rational&
fraction) // Input
{
fraction.get(is);
}*/

Rational Rational::eek:perator += (const Rational& fraction)
{
int tempNumOne = 0;
int tempNumTwo = 0;
int tempDenom = 0;

tempNumOne = fraction.numerator * denominator;
tempDenom = fraction.denominator * denominator;

tempNumTwo = numerator * fraction.denominator;

numerator = tempNumOne + tempNumTwo;
denominator = tempDenom;

int divisor = reducer ();

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return *this;
}

Rational Rational::eek:perator -= (const Rational& fraction)
{
int tempNumOne = 0;
int tempNumTwo = 0;
int tempDenom = 0;

tempNumOne = fraction.numerator * denominator;
tempDenom = fraction.denominator * denominator;

tempNumTwo = numerator * fraction.denominator;

numerator = tempNumOne - tempNumTwo;
denominator = tempDenom;

int divisor = reducer ();

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return *this;
}

Rational Rational::eek:perator *= (const Rational& fraction)
{
numerator *= fraction.numerator;
denominator *= fraction.denominator;

int divisor = reducer ();

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return *this;
}

Rational Rational::eek:perator /= (const Rational& fraction)
{
numerator *= fraction.denominator;
denominator *= fraction.numerator;

int divisor = reducer ();

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return *this;
}

const Rational operator + (const Rational& fractionLeft, const
Rational& fractionRight)
{
int tempNumOne = 0;
int tempNumTwo = 0;
int tempDenom = 0;

tempNumOne = fractionLeft.numerator * fractionRight.denominator;
tempDenom = fractionLeft.denominator * fractionRight.denominator;

tempNumTwo = fractionRight.numerator * fractionLeft.denominator;

int numerator = tempNumOne + tempNumTwo;
int denominator = tempDenom;
Rational obj;

int divisor = obj.reducer(numerator, denominator);

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return Rational(numerator, denominator);
}

const Rational operator - (const Rational& fractionLeft, const
Rational& fractionRight)
{
int tempNumOne = 0;
int tempNumTwo = 0;
int tempDenom = 0;

tempNumOne = fractionLeft.numerator * fractionRight.denominator;
tempDenom = fractionLeft.denominator * fractionRight.denominator;

tempNumTwo = fractionRight.numerator * fractionLeft.denominator;

int numerator = tempNumOne - tempNumTwo;
int denominator = tempDenom;
Rational obj;

int divisor = obj.reducer(numerator, denominator);

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return Rational(numerator, denominator);
}

const Rational operator * (const Rational& fractionLeft, const
Rational& fractionRight)
{
int numerator = fractionLeft.numerator * fractionRight.numerator;
int denominator = fractionLeft.denominator *
fractionRight.denominator;
Rational obj;

int divisor = obj.reducer(numerator, denominator);

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return Rational(numerator, denominator);
}

const Rational operator / (const Rational& fractionLeft, const
Rational& fractionRight)
{
int numerator = fractionLeft.numerator * fractionRight.denominator;
int denominator = fractionLeft.denominator *
fractionRight.numerator;
Rational obj;

int divisor = obj.reducer(numerator, denominator);

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return Rational(numerator, denominator);
}

const Rational operator << (std::eek:stream& os, const Rational&
fraction)
{
cout << "fraction.numerator " + fraction.numerator << "\n";
cout << fraction.numerator + " / " + fraction.denominator;
return Rational(fraction.numerator, fraction.denominator);
}



/* Rational::eek:perator - (const Rational& fractionLeft, const Rational&
fractionRight)
{
int tempNumOne = 0;
int tempNumTwo = 0;
int tempDenom = 0;

tempNumOne = fractionLeft.numerator * fractionRight.denominator;
tempDenom = fractionLeft.denominator * fractionRight.denominator;

tempNumTwo = fractionRight.numerator * fractionLeft.denominator;

numerator = tempNumOne - tempNumTwo;
denominator = tempDenom;

int divisor = reducer ();

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
}*/

/* Rational::eek:perator * (const Rational& fractionLeft, const Rational&
fractionRight)
{
numerator = fractionLeft.numerator * fractionRight.numerator;
denominator = fractionLeft.denominator * fractionRight.denominator;

int divisor = reducer ();

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
}*/

/* Rational::eek:perator / (const Rational& fractionLeft, const Rational&
fractionRight)
{
numerator = fractionLeft.numerator * fractionRight.denominator;
denominator = fractionLeft.denominator * fractionRight.numerator;

int divisor = reducer ();

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
}
*/

Rational::eek:perator double() // Typecast to double
{
return double (numerator/denominator);
}

Rational::string() // Typecast to string
{
return (char (numerator) + char(" / ") + char (denominator)) ;
}


int Rational::reducer() // helper function to reduce fraction if
possible
{
int small = 0;
int num = 0;
int den = 0;

num = numerator;
den = denominator;

if (num == 0)
return den;
if (den == 0)
return num;

// Only absolute value is important
if (den < 0)
den = den * -1;
if (num < 0)
num = num * -1;

// Smaller of the two becomes small
if (num > den)
small = den;
else
small = num;

// Continue till no remainder
while (num % small != 0 || den % small != 0)
{
if (num > small)
{
num = num - (num % small);
small = num;
}
else
{
den = den - (den % small);
small = den;
}
}

// Return thr divisor which leaves no remainder
return small;
}

int Rational::reducer(int numerator, int denominator) // helper
function to reduce fraction if possible
{
int small = 0;
int num = 0;
int den = 0;

num = numerator;
den = denominator;

if (num == 0)
return den;
if (den == 0)
return num;

// Only absolute value is important
if (den < 0)
den = den * -1;
if (num < 0)
num = num * -1;

// Smaller of the two becomes small
if (num > den)
small = den;
else
small = num;

// Continue till no remainder
while (num % small != 0 || den % small != 0)
{
if (num > small)
{
num = num - (num % small);
small = num;
}
else
{
den = den - (den % small);
small = den;
}
}

// Return thr divisor which leaves no remainder
return small;
}

void Rational::signAdjuster() // Make sure that numerator has
negative sign if applicable
{
if (numerator >= 0 && denominator < 0) // Positive numerator,
negative denominator
{
numerator *= -1;
denominator *= -1;
}
if (numerator < 0 && denominator < 0) // Negative numerator,
negative denominator
{
numerator *= -1;
denominator *= -1;
}
}

/* bool Rational::get(istream& is)
{
if (!is)
{
return false;
}

string streamString;
getline(is, streamString);
int position = 0;
int streamConverter = 0;

stringstream ssOne(streamString.substr(position, 1));
ssOne >> streamConverter;
numerator = streamConverter;
position++;

// skip over any spaces and slashes
while (ssOne(streamString.substr(position, 1) == " " ||
ssOne(streamString.substr(position, 1) == "/")
{
position++;
}

stringstream ssOne(streamString.substr(position, 1));
ssOne >> streamConverter;
denominator = streamConverter;

if (inputString == "")
{
return false;
}

else
return true;
}

// Write string to output file

void Rational::put(ostream& os)
{
if (!os)
{
return false;
}
if (os)
{
os << setw(0) << numerator << " / " << denominator << "\n";
}
return true;
}*/
 
D

David B. Held

Zenon said:
I am having a terrible time overloading operators. I have tried
what I thought was the correct way, I tried the cheating (friend
declarations), all to no avail. Sorry for posting tons of code
but I really need help.
[...]

I don't know any psychics, and most people aren't going to simply
try out the code without some idea of what is wrong. So why don't
you summarize what problems you are having, and save us the
trouble of looking through all your code.

Dave
 
Z

Zenon

Perhaps a (small) sample of the errors you are getting would be usefull.

My errors all related to the binary operators and stated that these
operators must be declared with only one parameter. The other bigest
problem was the string() function which is supposed to cast to a
string. I cannot use te keyword operator there lik I can in the
double() cast.... what is the right way to do it?

thanks,

Zenon
 
?

=?ISO-8859-1?Q?Christian_Brechb=FChler?=

Zenon said:
I am having a terrible time overloading operators.

Ok. I see two superficial things.

//...
class Rational
{
// Define data members
int numerator;
int denominator;

// define function prototypes
public:
Rational::Rational(int num, int denom); // Creates a fraction
Rational::Rational(); // Default constructor
Rational::~Rational(); // Default destructor
void Rational::signAdjuster();
int Rational::reducer(); // helper function to reduce fracion if
possible
int Rational::reducer(int numerator, int denominator); // helper
function to reduce fracion if possible //...
};


Inside the class definition, it's obvious your defining members of
Rational. The "Rational::" qualifications are unnecessry, not usual,
and not a pretty sight. I'm not sure if they are harmless.

Then you broke around the lines in your post -- e.g., the word
"possible" is no longer in comments, and it causes the compiler to
complain on the next token:

zenon.cc:25: syntax error before `int'
zenon.cc:26: parse error before `fracion'

Obviously that's not what you meant, but it makes it more work to get to
your real problem. You may need to temporarily change the preferences
of you news reader/poster. E.g., in Mozilla, Edit -> Preferences ->
Mail&Newsgroups -> Composition: wrap plain text messages at XXX characters.

More when I get past these errors. :)

Christian
 
?

=?ISO-8859-1?Q?Christian_Brechb=FChler?=

Zenon said:
Folks,
I am having a terrible time overloading operators. I have tried what
I thought was the correct way, I tried the cheating (friend
declarations), all to no avail. Sorry for posting tons of code but I
really need help.

And supplied his source code for a class Rational.

David B. Held replied:
I don't know any psychics, and most people aren't going to simply
try out the code without some idea of what is wrong.

Well, a bunch of things are wrong :). First, it doesn't compile. My advice
here: heed the compiler's error messages; they are usually specific and accurate.
Here is a number of specific points.


I assume your code should be split into two files, "Rational.hpp" and
"Rational.cc". (Next time, please indicate.) I added a little sample program
that uses a few of your operators. Make sure to write a real test program that
uses EVERY operator. It will look lengthy, but it's essential.


Check out this function,
Rational::string() // Typecast to string
{
return (char (numerator) + char(" / ") + char (denominator)) ;
}
First, every function needs a return type. I made it int. Why? It computes the
sum of three numbers: the numerator, the not very predictable address of the
string literal, and the denominator. They are cast to char, but before adding
them, integral promotion brings them back to int. BTW, this curious computation
is probably not what you wanted, and certainly NOT a typecast to string. And
casting the address to char still gives a warning.


Usually operator<<(std::eek:stream&, ...) returns a reference to the stream. For
convenience and convention, comply. You'll be able to write, e.g.,
os << "x = " << x << std::endl;
Also, write to the stream passed in, NOT cout.


I don't think the "const" qualifier matters in a return by value, as in your
binary operators +, -, *, /. I took it out. (In contrast, returning a const vs.
non-const reference is an important distinction.)

The constructor taking two ints contains this statement:
cout << "constructor numerator " + num ;
The numerator is added to a pointer to the first character of the c-style string
literal, yielding a pointer to another character. So if num is 4, we get a char*
that prints as "tructor numerator". If num is large or negative, worse may
happen. This is not the way to do string concatenation. I guess what was inteded
is a debug statement:
std::cerr << "constructor: numerator = " << num << std::endl;
But I left this one.

As I said before, omit "Rational::" qualifiers inside the class defintion.

Also, limit your lines to 80 characters. And prevent your news poster from
wrapping them shorter.


Lots of code in /* ... */ makes your source harder to read. Delete it.


Here's the output from the sample program (code below):

uctor numerator nstructor numerator a = 6 / 8; b = 2 / 3
onstructor numerator onstructor numerator onstructor numerator onstructor\
numerator c = 1 / 1; a-b = 1 / 12; a b = 1 / 2; a/b = 1 / 1

So, subtraction and multiplication seem fine in this example. Addition and
division need work. Lots to do!

Hoping this gets you started, Zenon

Christian



//------ t_rational.cc
#include "Rational.hpp"
#include <iostream>

int main() {
Rational a(6,8), b(2,3), c;
std::cout << "a = " << a << "; b = " << b << std::endl;
c = a + b;
std::cout << "c = " << c << "; a-b = " << a-b << "; a b = " << a*b
<< "; a/b = " << a/b << std::endl;
}



//----- Rational.hpp
#ifndef Rational__hpp
#define Rational__hpp

#include<iostream>
#include<iomanip>
#include <cstring>
#include <cmath>
#include <sstream>
#include <fstream>

class Rational
{
// Define data members
int numerator;
int denominator;

// define function prototypes
public:
Rational(int num, int denom); // Creates a fraction
Rational(); // Default constructor
~Rational(); // Default destructor
void signAdjuster();
int reducer(); // helper function to reduce fracion if possible
// helper function to reduce fracion if possible
int reducer(int numerator, int denominator);


Rational operator += (const Rational& fraction);
Rational operator -= (const Rational& fraction);
Rational operator *= (const Rational& fraction);
Rational operator /= (const Rational& fraction);

friend std::eek:stream& operator << (std::eek:stream& os,
const Rational& fraction);

friend Rational operator + (const Rational& lhs, const Rational& rhs);
friend Rational operator - (const Rational& lhs, const Rational& rhs);
friend Rational operator * (const Rational& lhs, const Rational& rhs);
friend Rational operator / (const Rational& lhs, const Rational& rhs);

operator double(); // Typecast to double
int string(); // Typecast to string -- actually to a funny int
};

std::eek:stream& operator<< (std::eek:stream& os, const Rational& fraction);
std::istream& operator>> (std::istream& is, Rational& fraction);

#endif




//----- Rational.cc
#include <cstring>
#include <cmath>
#include<iostream>
#include <fstream>
#include <vector>
#include <iomanip>
#include <sstream>
#include "Rational.hpp"

using namespace std;

Rational::Rational(int num, int denom)
// Set a fractions numerator and denominator
{
numerator = num;
denominator = denom;
cout << "constructor numerator " + num ;

signAdjuster();
}

Rational::Rational() {} // Default constructor

Rational::~Rational() {} // Destructor

Rational Rational::eek:perator += (const Rational& fraction)
{
int tempNumOne = 0;
int tempNumTwo = 0;
int tempDenom = 0;

tempNumOne = fraction.numerator * denominator;
tempDenom = fraction.denominator * denominator;

tempNumTwo = numerator * fraction.denominator;

numerator = tempNumOne + tempNumTwo;
denominator = tempDenom;

int divisor = reducer ();

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return *this;
}

Rational Rational::eek:perator -= (const Rational& fraction)
{
int tempNumOne = 0;
int tempNumTwo = 0;
int tempDenom = 0;

tempNumOne = fraction.numerator * denominator;
tempDenom = fraction.denominator * denominator;

tempNumTwo = numerator * fraction.denominator;

numerator = tempNumOne - tempNumTwo;
denominator = tempDenom;

int divisor = reducer ();

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return *this;
}

Rational Rational::eek:perator *= (const Rational& fraction)
{
numerator *= fraction.numerator;
denominator *= fraction.denominator;

int divisor = reducer ();

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return *this;
}

Rational Rational::eek:perator /= (const Rational& fraction)
{
numerator *= fraction.denominator;
denominator *= fraction.numerator;

int divisor = reducer ();

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return *this;
}

Rational operator + (const Rational& fractionLeft,
const Rational& fractionRight)
{
int tempNumOne = 0;
int tempNumTwo = 0;
int tempDenom = 0;

tempNumOne = fractionLeft.numerator * fractionRight.denominator;
tempDenom = fractionLeft.denominator * fractionRight.denominator;

tempNumTwo = fractionRight.numerator * fractionLeft.denominator;

int numerator = tempNumOne + tempNumTwo;
int denominator = tempDenom;
Rational obj;

int divisor = obj.reducer(numerator, denominator);

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return Rational(numerator, denominator);
}

Rational operator - (const Rational& fractionLeft,
const Rational& fractionRight)
{
int tempNumOne = 0;
int tempNumTwo = 0;
int tempDenom = 0;

tempNumOne = fractionLeft.numerator * fractionRight.denominator;
tempDenom = fractionLeft.denominator * fractionRight.denominator;

tempNumTwo = fractionRight.numerator * fractionLeft.denominator;

int numerator = tempNumOne - tempNumTwo;
int denominator = tempDenom;
Rational obj;

int divisor = obj.reducer(numerator, denominator);

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return Rational(numerator, denominator);
}

Rational operator * (const Rational& fractionLeft, const
Rational& fractionRight)
{
int numerator = fractionLeft.numerator * fractionRight.numerator;
int denominator = fractionLeft.denominator *
fractionRight.denominator;
Rational obj;

int divisor = obj.reducer(numerator, denominator);

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return Rational(numerator, denominator);
}

Rational operator / (const Rational& fractionLeft, const
Rational& fractionRight)
{
int numerator = fractionLeft.numerator * fractionRight.denominator;
int denominator = fractionLeft.denominator *
fractionRight.numerator;
Rational obj;

int divisor = obj.reducer(numerator, denominator);

if (divisor != 1)
{
numerator /= divisor;
denominator /= divisor;
}
return Rational(numerator, denominator);
}

std::eek:stream& operator << (std::eek:stream& os, const Rational& fraction)
{
return os << fraction.numerator << " / " << fraction.denominator;
}


Rational::eek:perator double() // Typecast to double
{
return double (numerator/denominator);
}

int Rational::string() // Typecast to string.
{
// sum of the codes of three characters making little sense.
return (char (numerator) + char(" / ") + char (denominator)) ;
}


int Rational::reducer() // helper function to reduce fraction if possible
{
int small = 0;
int num = 0;
int den = 0;

num = numerator;
den = denominator;

if (num == 0)
return den;
if (den == 0)
return num;

// Only absolute value is important
if (den < 0)
den = den * -1;
if (num < 0)
num = num * -1;

// Smaller of the two becomes small
if (num > den)
small = den;
else
small = num;

// Continue till no remainder
while (num % small != 0 || den % small != 0)
{
if (num > small)
{
num = num - (num % small);
small = num;
}
else
{
den = den - (den % small);
small = den;
}
}

// Return thr divisor which leaves no remainder
return small;
}

int Rational::reducer(int numerator, int denominator)
// helper function to reduce fraction if possible
{
int small = 0;
int num = 0;
int den = 0;

num = numerator;
den = denominator;

if (num == 0)
return den;
if (den == 0)
return num;

// Only absolute value is important
if (den < 0)
den = den * -1;
if (num < 0)
num = num * -1;

// Smaller of the two becomes small
if (num > den)
small = den;
else
small = num;

// Continue till no remainder
while (num % small != 0 || den % small != 0)
{
if (num > small)
{
num = num - (num % small);
small = num;
}
else
{
den = den - (den % small);
small = den;
}
}

// Return thr divisor which leaves no remainder
return small;
}

// Make sure that numerator has negative sign if applicable
void Rational::signAdjuster()
{
if (numerator >= 0 && denominator < 0)
// Positive numerator, negative denominator
{
numerator *= -1;
denominator *= -1;
}
if (numerator < 0 && denominator < 0)
// Negative numerator, negative denominator
{
numerator *= -1;
denominator *= -1;
}
}
 
?

=?ISO-8859-1?Q?Christian_Brechb=FChler?=

Zenon said:
My errors all related to the binary operators and stated that these
operators must be declared with only one parameter.

Well you have two options: Either make them member functions taking
one argument, the right hand side. Or make them non-member functions
taking two arguments. Get and read Stroustrup! In particular 11.13:
[6] Prefer member functions over nonmembers for operations that need
access to the representation.
[7] Prefer nonmember functions over members for operations that do not
need access to the representation.
[9] Use nonmember functions for symmetric operators.
[14] Use member functions to express operators that require an lvalue
as its operand.
The latter are the binary operators += etc.
The other bigest
problem was the string() function which is supposed to cast to a
string. I cannot use te keyword operator there lik I can in the
double() cast.... what is the right way to do it?

I would avoid "casting" to string. Just don't supply that operation.
You have operator<<(std::eek:stream&, const Rational&), which should
satisfy most needs.

If really want to do it, use that operator<< and write to a
stringstream.

Good luck!

Christian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top