Hey guys,
I was wondering if you could help me fix my program. I'm witing a program in C++ that adds, subtracts, multiplies and divides fractions. I'm suppose to put in the cosntructor that the denominator cannot be 0 or a negative number and i also I have to reduce the fraction. I have no problem adding, subtracting , etc. When i run it saids that there's no appropriate default constructor available for x, a, and b. Well take a look at my code so, you can see what i mean.

#include <iostream.h>
#include <math.h>
class RationalNumbers
{
public:
 RationalNumbers(double, double);
 RationalNumbers operator+(const RationalNumbers &) const;
 RationalNumbers operator-(const RationalNumbers &) const;
 RationalNumbers operator*(const RationalNumbers &) const;
 RationalNumbers operator/(const RationalNumbers &) const;

 friend ostream &operator<<(ostream&, const RationalNumbers &);
 friend istream &operator>>(istream&, RationalNumbers & );
private:
 double numerator;
 double denominator;
};
 
// Constructor
RationalNumbers::RationalNumbers( double num, double den ) 
{ 
num=numerator;
if (den>0)
{den=denominator;}
 
 

}
//void RationalNumbers::reduce()
//{}
// addition 
RationalNumbers RationalNumbers::operator+( const RationalNumbers &part2 ) const
{
   return RationalNumbers( numerator*part2.denominator+part2.numerator*denominator, 
	  denominator*part2.denominator );
} 
// subtraction 
RationalNumbers RationalNumbers::operator-( const RationalNumbers &part2 ) const
{
   return RationalNumbers( numerator*part2.denominator-part2.numerator*denominator, 
	  denominator*part2.denominator  );
}
//multiplication
RationalNumbers RationalNumbers::operator *( const RationalNumbers &part2 ) const
{
 return RationalNumbers(numerator*part2.numerator, denominator*part2.denominator);
}
//Division
RationalNumbers RationalNumbers::operator /(const RationalNumbers &part2) const
{
 return RationalNumbers(numerator*part2.denominator, denominator*part2.numerator);
}
 
 
istream &operator>>(istream &in, RationalNumbers &part2)
{
 in>>part2.numerator;
 in.ignore();
 in>>part2.denominator ;
 
 return in;
}
// show form: (a, b)
ostream &operator <<(ostream &out, const RationalNumbers &part2)
{out<<part2.numerator<<"/"<<part2.denominator <<endl;
return out;
}

int main()
{
 RationalNumbers x;
 RationalNumbers a;
 RationalNumbers b;
 
 cout<<"Enter 2 integers for a:\n";
 cin>>a;
 
 cout<<"\nEnter 2 integers for b:\n";
 cin>>b;

 
 cout<<"x = a + b: ";
 x=a+b;
 cout<<x;
 
 cout<<"x = a - b: ";
 x=a-b;
 cout<<x;
 cout<<"x = a*b: ";
 x=a*b;
 cout<<x;
 
 cout<<"x=a/b:  ";
 x=a/b;
 cout<<x;
 

 
 return 0;
}

Your only constructor takes two parameters.

// Constructor
RationalNumbers::RationalNumbers( double num, double den )
{
num=numerator;
if (den>0)
{den=denominator;}
}

But you instantiate some objects without supplying parameters.

RationalNumbers x;
 RationalNumbers a;
 RationalNumbers b;

1. You need to define a constructor that takes no parameters.

// Constructor
RationalNumbers::RationalNumbers( ) 
: numerator(0.0), denominator(1.0) {}

2. Or supply defaults for your constructor that takes two parameters.

// Constructor
RationalNumbers::RationalNumbers( double num = 0.0, double den = 1.0 ) 
: numerator(num), denominator(den) {}

3. Or instantiate your objects using your existing constructor.

RationalNumbers x(0.0,1.0);
 RationalNumbers a(0.0,1.0);
 RationalNumbers b(0.0,1.0);

Thank you, The Other Dave.

I fixed my problem. Now is running perfectly. Now my program has a constructor that prevents a 0 denominator in a fraction and reduces fractions that are not in reduce form and avoids negative numbers. I overloaded the addition, multiplication, subtraction and division operators and the relational and equality operators too. Here is how it looks now.
Feel free to give any comments.

#include <iostream.h>
#include <math.h>
class RationalNumbers
{
public:
 RationalNumbers(double=0.0, double=1.0);
 RationalNumbers operator+(const RationalNumbers &) const;
 RationalNumbers operator-(const RationalNumbers &) const;
 RationalNumbers operator*(const RationalNumbers &) const;
 RationalNumbers operator/(const RationalNumbers &) const;
 bool operator<(const RationalNumbers &) const;
 bool operator>(const RationalNumbers &) const;
 bool operator<=(const RationalNumbers &) const;
 bool operator>=(const RationalNumbers &) const;
 bool operator==(const RationalNumbers &) const;
 bool operator!=(const RationalNumbers &) const;
 friend ostream &operator<<(ostream&, const RationalNumbers &);
 friend istream &operator>>(istream&, RationalNumbers & );

private:
 double numerator;
 double denominator;
};
 
// Constructor
RationalNumbers::RationalNumbers( double num, double den ) 
   : numerator( num ), denominator(den) 
	
{ num=numerator;
if (denominator>0)
den=denominator;
else cout<<"Error Try again"<<endl;
int i;
 for(i=2; i<=numerator; ++i) {
  if( ((numerator/i) == ((int)(numerator/i))) && ((denominator/i) == ((int)(denominator/i))) ) {
   numerator /= i;
   denominator /= i;
   --i;	   
  }
 }
} 
 
 
// addition 
RationalNumbers RationalNumbers::operator+( const RationalNumbers &part2 ) const
{
   return RationalNumbers( numerator*part2.denominator+part2.numerator*denominator, 
	  denominator*part2.denominator );
} 
// subtraction 
RationalNumbers RationalNumbers::operator-( const RationalNumbers &part2 ) const
{
   return RationalNumbers( numerator*part2.denominator-part2.numerator*denominator, 
	  denominator*part2.denominator  );
}
//multiplication
RationalNumbers RationalNumbers::operator *( const RationalNumbers &part2 ) const
{
 return RationalNumbers(numerator*part2.numerator, denominator*part2.denominator);
}
//Division
RationalNumbers RationalNumbers::operator /(const RationalNumbers &part2) const
{
 return RationalNumbers(numerator*part2.denominator, denominator*part2.numerator);
}
//a is less than b
bool RationalNumbers::operator <(const RationalNumbers &part2) const
{double temp, temp2;
temp=numerator*part2.denominator;
temp2=part2.numerator*denominator;
 if (temp < temp2)
 return true;
 else
 return false;
}
//a is greater than b
bool RationalNumbers::operator >(const RationalNumbers &part2) const
{double temp, temp2;
temp=numerator*part2.denominator;
temp2=part2.numerator*denominator;
if(temp > temp2)
return true;
else
return false;
}
//a is less or equal to b
bool RationalNumbers::operator <=(const RationalNumbers &part2) const
{double temp, temp2;
temp=numerator*part2.denominator;
temp2=part2.numerator*denominator;
if(temp <= temp2)
return true;
else
return false;
}
bool RationalNumbers::operator >=(const RationalNumbers &part2) const
{double temp, temp2;
temp=numerator*part2.denominator;
temp2=part2.numerator*denominator;
if(temp >= temp2)
return true;
else
return false;
}
// a is equal to b
bool RationalNumbers::operator ==(const RationalNumbers &part2) const
{
if(numerator == part2.numerator && denominator==part2.denominator)
return true;
else
return false;
}
//a not equal to b
bool RationalNumbers::operator !=(const RationalNumbers &part2) const
{
if(numerator == part2.numerator && denominator==part2.denominator)
return false;
else
return true;
}
istream &operator>>(istream &in, RationalNumbers &part2)
{
 in>>part2.numerator;
 in.ignore();
 in>>part2.denominator ;
 
 return in;
}
// show form: (a, b)
ostream &operator <<(ostream &out, const RationalNumbers &part2)
{out<<part2.numerator<<"/"<<part2.denominator <<endl;
return out;
}

int main()
{
 
 RationalNumbers x;
 RationalNumbers a;
 RationalNumbers b;

 cout<<"Enter a fraction for a:\n";
 cin>>a;
 
 cout<<"\nEnter a fraction for b:\n";
 cin>>b;

 cout<<"x = a + b: ";
 x=a+b;
 cout<<x;
 
 cout<<"x = a - b: ";
 x=a-b;
 cout<<x;
 cout<<"x = a*b: ";
 x=a*b;
 cout<<x;
 
 cout<<"x=a/b:  ";
 x=a/b;
 cout<<x;
 
 a<b;
 if (a<b)
 cout<<"a<b"<<endl;
 a>b;
 if(a>b)
 cout<<"a>b"<<endl;
 
 a<=b;
 if(a<=b)
 cout<<"a<=b"<<endl;
 a>=b;
 if(a>=b)
 cout<<"a>=b"<<endl;
 a==b;
 if(a==b)
 cout<<"a equals b"<<endl;
 a!=b;
 if (a!=b)
 cout<<"a not equal to b"<<endl<<endl;
 return 0;
}

I wanted to put a while loop so the program keeps asking the user to enter another fraction but i didn't know how to stop the loop. I wanted to do something like this:

int main()
{
 
 RationalNumbers x;
 RationalNumbers a;
 RationalNumbers b;
		 while(1){	  // loop  I don't know how to stop it
 cout<<"Enter a fraction for a:\n";
 cin>>a;
 
 cout<<"\nEnter a fraction for b:\n";
 cin>>b;
		 if(?) exit(0);  // I don't know what to put between the parentesis
 cout<<"x = a + b: ";
 x=a+b;
 cout<<x;
  blah, blah, blah...
........
  a==b;
 if(a==b)
 cout<<"a equals b"<<endl;
 a!=b;
 if (a!=b)
 cout<<"a not equal to b"<<endl<<endl;
 }
 return 0;
}

>I wanted to put a while loop so the program keeps asking the user to enter another fraction but i didn't know how to stop the loop.

Here is one way.

int main()
{
   char c;
   do
   {
	  /* ... */
	  cout << "Continue? (y/n) ";
	  cin  >> c;
   } while ( c == 'y' );
   return 0;
}

Something you should know about checking for floating point equality:
http://www.eskimo.com/~scs/C-faq/q14.5.html

You're not using anything from <math.h>

The linter also tells me this.

[Info 1739] Binary operator 'RationalNumbers::operator+(const RationalNumbers &) const' should be non-member function
[Info 1754] Expected symbol 'operator+=' to be declared for class 'RationalNumbers'
[Info 1739] Binary operator 'RationalNumbers::operator-(const RationalNumbers &) const' should be non-member function
[Info 1754] Expected symbol 'operator-=' to be declared for class 'RationalNumbers'
[Info 1739] Binary operator 'RationalNumbers::operator*(const RationalNumbers &) const' should be non-member function
[Info 1754] Expected symbol 'operator*=' to be declared for class 'RationalNumbers'
[Info 1739] Binary operator 'RationalNumbers::operator/(const RationalNumbers &) const' should be non-member function
[Info 1754] Expected symbol 'operator/=' to be declared for class 'RationalNumbers'
[Info 1739] Binary operator 'RationalNumbers::operator<(const RationalNumbers &) const' should be non-member function
[Info 1739] Binary operator 'RationalNumbers::operator>(const RationalNumbers &) const' should be non-member function
[Info 1739] Binary operator 'RationalNumbers::operator<=(const RationalNumbers &) const' should be non-member function
[Info 1739] Binary operator 'RationalNumbers::operator>=(const RationalNumbers &) const' should be non-member function
[Info 1739] Binary operator 'RationalNumbers::operator==(const RationalNumbers &) const' should be non-member function
[Info 1739] Binary operator 'RationalNumbers::operator!=(const RationalNumbers &) const' should be non-member function

I'm not exactly sure what it is trying to tell me, though. Here are the explanations of the diagnostic messages.

1739 Binary operator 'Symbol' should be non-member function -- The indicated function was declared as a member function. There were a number of indicators to suggest that it should have been a non-member function. The class, X of which it was a member has a constructor that could be used to convert numeric values to X. The parameter to the operator was X or its equivalent. For this reason the operator would behave unsymmetrically. A numeric value on the right hand side would be promoted but not a value on the left hand side. For example, X op 27 would work but 27 op X would not. [12, Item 19].

1754 Expected symbol 'Symbol' to be declared for class 'Symbol' -- The first Symbol is of the form: operator op= where op is a binary operator. A binary operator op was declared for type X where X is identified by the second Symbol. For example, the appearance of:

X operator+( const X &, const X & );

somewhere in the program would suggest that a += version appear as a member function of class X. This is not only to fulfill reasonable expectations on the part of the programmer but also because operator+= is likely to be more efficient than operator+ and because operator+ can be written in terms of operator+=. [23, Item 22]

The message is also given for member binary operators. In all cases the message is not given unless the return value matches the first argument (this is the implicit argument in the case of a member function).

Perhaps this may mean more to you.

I've gotten to like a particular style, and I'm not pushing it here. Style can make code easier to read and thus easier to debug. Just for the sake of comparison, here is much the same code done with shorter names and more whitespace between operators.

#include <iostream>
using std::cin;
using std::cout;
using std::endl;
using std::istream;
using std::ostream;

class rational
{
   double num;
   double den;
public:
   // Constructor
   rational::rational( double n = 0.0, double d = 1.0 ) : num( n ), den( d )
   {
	  if ( den > 0 )
	  {
		 d = den;
	  }
	  else
	  {
		 cout << "Error Try again" << endl;
	  }
	  for ( int i = 2; i <= num; ++i )
	  {
		 if ( ((num/i) == ((int)(num/i))) && ((den/i) == ((int)(den/i))) )
		 {
			num /= i;
			den /= i;
			--i;
		 }
	  }
   }
   // addition
   rational rational::operator+ ( const rational &rhs )
   {
	  return rational( num * rhs.den + rhs.num * den, den * rhs.den );
   }
   // subtraction
   rational rational::operator- ( const rational &rhs ) const
   {
	  return rational( num * rhs.den - rhs.num * den, den * rhs.den );
   }
   // multiplication
   rational rational::operator* ( const rational &rhs ) const
   {
	  return rational(num * rhs.num, den * rhs.den);
   }
   // division
   rational rational::operator/ ( const rational &rhs ) const
   {
	  return rational(num * rhs.den, den * rhs.num);
   }
   // less than
   bool rational::operator<  ( const rational &rhs ) const
   {
	  return( num * rhs.den < rhs.num * den );
   }
   // greater than
   bool rational::operator>  ( const rational &rhs ) const
   {
	  return( num * rhs.den > rhs.num * den );
   }
   // less or equal to
   bool rational::operator<= ( const rational &rhs ) const
   {
	  return( num * rhs.den <= rhs.num * den );
   }
   // greater than or equal to
   bool rational::operator>= ( const rational &rhs ) const
   {
	  return( num * rhs.den >= rhs.num * den );
   }
   // equality
   bool rational::operator== ( const rational &rhs ) const
   {
	  return num == rhs.num && den==rhs.den;
   }
   // inequality
   bool rational::operator!= ( const rational &rhs ) const
   {
	  return !( num == rhs.num && den==rhs.den );
   }
   // extraction
   friend ostream &operator<< ( ostream&, const rational& );
   // insertion
   friend istream &operator>> ( istream&, rational& );
};

istream &operator>> ( istream &in, rational &rhs )
{
   return in >> rhs.num >> rhs.den;
}

// show form: (a, b)
ostream &operator<< ( ostream &out, const rational &rhs )
{
   return out << rhs.num << "/" << rhs.den;
}

int main()
{
   rational x, a, b;
   char c;
   do
   {
	  cout << "Enter a fraction for a: ";
	  cin  >> a;

	  cout << "Enter a fraction for b: ";
	  cin  >> b;

	  x = a + b; cout << "x = a + b: " << x << endl;
	  x = a - b; cout << "x = a - b: " << x << endl;
	  x = a * b; cout << "x = a * b: " << x << endl;
	  x = a / b; cout << "x = a / b: " << x << endl;

	  cout << "Continue? (y/n) ";
	  cin  >> c;
   } while ( c == 'y' );
   return 0;
}

/* my output
Enter a fraction for a: 1 2
Enter a fraction for b: 1 3
x = a + b: 5/6
x = a - b: 1/6
x = a * b: 1/6
x = a / b: 3/2
Continue? (y/n) y
Enter a fraction for a: 1 4
Enter a fraction for b: 1 5
x = a + b: 9/20
x = a - b: 1/20
x = a * b: 1/20
x = a / b: 5/4
Continue? (y/n) n
*/

I also shortened a few of the functions. And I moved the endl out of the extraction operator.

But notice in your constructor how you are using initializer syntax to assign to the denominator, then in the body you check for greater than zero to see whether to assign it -- it may have already been assigned. Also, how do you "Try again" on a constructor?

oops, I forgot to erase num( n ), den( d ) when i made the restrictions for the denominator. I didn't notice since it didn't give me a error message. Thanks for pointing that out.


The Other Dave, your program doesn't read a fraction, it only reads two intergers.

>The Other Dave, your program doesn't read a fraction, it only reads two intergers.

Sure it does. I just chose to use whitespace as the delimiter instead of a '/'. Add in more code to ignore the '/' if you wish.

This article has been dead for over six months. Start a new discussion instead.