void Rational::reduce(Rational &f3){
		int tnum, tden, temp, gcd;
		tnum = labs(numerator);          								   	  // use non-negative copies
		tden = labs(denominator);          						              //    (needs cmath)
		if(tden==0 ){   											  		  // check for n/0  
			cout << "Illegal fraction: division by 0"; exit(1); }
		else if( tnum==0 ){        									   	      // check for 0/n
			numerator=0; denominator = 1; return; }
					// this ‘while’ loop finds the gcd of tnum and tden
		while(tnum != 0)
			if(tnum < tden){												  // ensure numerator larger
				temp=tnum; tnum=tden; tden=temp;							  // swap them
				tnum = tnum - tden;}									      // subtract them
		gcd = tden;															  // this is greatest common divisor
		numerator = numerator / gcd;										  // divide both num and den by gcd
		denominator = denominator / gcd;									  // to reduce frac to lowest terms
	}	//ends function reduce

	void Rational::normalize(Rational&){ 
		if(denominator < 0){
			numerator = numerator * -1;
			denominator = denominator * -1;}
	}	//ends function normalize
		
		//sets the numerator and denominator to 0
	void Rational::sglfrac() {
		
		cout << "\nnumerator: "; cin >> numerator;  
		cout << "denominator: "; cin >> denominator;
	}	//end function sglfrac
	
	void Rational::add(Rational f1, Rational f2 ) {
		//	a / b + c / d = [n](a * d + b * c) [d](b * d)
		numerator = (f1.numerator * f2.denominator) + (f1.denominator * f2.numerator); //adds the numerator
		denominator = (f1.denominator * f2.denominator);	//adds the denominator	
	}	//end function add

so far I've been trying to get the fraction to be reduced and normalized in the add function and I'm trying to use pass with reference but I am completely lost when it comes to passing by reference
so far all I've understood is passing by reference creates a copy of the item

Recommended Answers

All 13 Replies

so far all I've understood is passing by reference creates a copy of the item

Passing by reference does NOT create a copy of the item, that's the whole point of using it. It manipulates the original(by passing the memory address) so when your function ends any change you make to the variable doesn't go out of scope.

Sorry I'm still getting this down so it's passing by value that makes the copy correct.

so if I run my reduce program it changes my numerator and denominator the same for my normalized function.
So how would I get those changes to print in my add function?

Sorry I'm still getting this down so it's passing by value that makes the copy correct.

No, it's not passing by value, it's passing by reference. The reference is the memory address of the variable.

so if I run my reduce program it changes my numerator and denominator the same for my normalized function.
So how would I get those changes to print in my add function?

Because you're using a class, any variable declared for the class should be kept as long as an object derived from the class stays in scope. I'm not fully understanding the logic of your program. Your functions are taking another Rational object as a parameter but only add is actually doing anything with them. If you could post your class declaration that would help.

This is my class declaration

class Rational{
 private:
	  int numerator;
	  int denominator;
	  float deci;
	  void reduce(Rational&);
	  void normalize(Rational&);

  public:
	Rational() : numerator(0), denominator(0)
	{}
	Rational(int num, int den) : numerator(num), denominator(den)			//constuctor
	{}
	void sglfrac();						//input a single fraction
	void add(Rational, Rational);		//add two fractions
	void sub(Rational, Rational);		//subtract two fractions
	void mult(Rational, Rational);		//multiply two fractions
	void div(Rational, Rational);		//divide two fractions
	void displaysgl();					//display a single fraction in n/d format
	void displayfloat(Rational);		//display a single fraction in floating point format	
  
};	//ends class Rational

This is my class declaration

class Rational{
 private:
	  int numerator;
	  int denominator;
	  float deci;
	  void reduce(Rational&);
	  void normalize(Rational&);

  public:
	Rational() : numerator(0), denominator(0)
	{}
	Rational(int num, int den) : numerator(num), denominator(den)			//constuctor
	{}
	void sglfrac();						//input a single fraction
	void add(Rational, Rational);		//add two fractions
	void sub(Rational, Rational);		//subtract two fractions
	void mult(Rational, Rational);		//multiply two fractions
	void div(Rational, Rational);		//divide two fractions
	void displaysgl();					//display a single fraction in n/d format
	void displayfloat(Rational);		//display a single fraction in floating point format	
  
};	//ends class Rational

Thank you.

Your add, subtract, multiply, and divide functions are a little awkward. You're actually taking in THREE Rational objects (the two you've passed, and the one you called it from). Are you trying to add two and put the value into the Rational object which the function was called? That's what the "add" function you posted is doing. If so, then you're on the right track with that, however, you don't need to pass by reference.

Also, your reduce and normalize functions are private. This means that only the object which owns it can call those functions. None of your functions are calling normalize or reduce, so it's impossible to access them. You need to make those public, that way they can be accessed. You'll also need accessor functions to get the values of numerator and denominator in your other objects. Something as simple as:

int getNumerator(){return numerator;};
int getDenominator(){return denominator;};

will suffice.

You might as well post your whole code, so I can see exactly what you're trying to do and guide you better to achieve what you want.

Here is the full program

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

class Rational{
 private:
	  int numerator;
	  int denominator;
	  float deci;
	  void reduce(Rational&);
	  void normalize(Rational&);

  public:
	Rational() : numerator(0), denominator(0)
	{}
	Rational(int num, int den) : numerator(num), denominator(den)			//constuctor
	{}
	void sglfrac();						//input a single fraction
	void add(Rational, Rational);		//add two fractions
	void sub(Rational, Rational);		//subtract two fractions
	void mult(Rational, Rational);		//multiply two fractions
	void div(Rational, Rational);		//divide two fractions
	void displaysgl();					//display a single fraction in n/d format
	void displayfloat(Rational);		//display a single fraction in floating point format	
  
};	//ends class Rational

		//private member functions
	void Rational::reduce(Rational &f3){
		int tnum, tden, temp, gcd;
		tnum = labs(numerator);          								   	  // use non-negative copies
		tden = labs(denominator);          						              //    (needs cmath)
		if(tden==0 ){   											  		  // check for n/0  
			cout << "Illegal fraction: division by 0"; exit(1); }
		else if( tnum==0 ){        									   	      // check for 0/n
			numerator=0; denominator = 1; return; }
					// this ‘while’ loop finds the gcd of tnum and tden
		while(tnum != 0)
			if(tnum < tden){												  // ensure numerator larger
				temp=tnum; tnum=tden; tden=temp;							  // swap them
				tnum = tnum - tden;}									      // subtract them
		gcd = tden;															  // this is greatest common divisor
		numerator = numerator / gcd;										  // divide both num and den by gcd
		denominator = denominator / gcd;									  // to reduce frac to lowest terms
	}	//ends function reduce

	void Rational::normalize(Rational&){ 
		if(denominator < 0){
			numerator = numerator * -1;
			denominator = denominator * -1;}
	}	//ends function normalize
		
		//sets the numerator and denominator to 0
	void Rational::sglfrac() {
		
		cout << "\nnumerator: "; cin >> numerator;  
		cout << "denominator: "; cin >> denominator;
	}	//end function sglfrac
	
	void Rational::add(Rational f1, Rational f2 ) {
		//	a / b + c / d = [n](a * d + b * c) [d](b * d)
		numerator = (f1.numerator * f2.denominator) + (f1.denominator * f2.numerator); //adds the numerator
		denominator = (f1.denominator * f2.denominator);	//adds the denominator	
	}	//end function add
		
	void Rational::sub(Rational f1, Rational f2) {				
		//	a / b - c / d =[n]( a * d - b * c)[d](b * d)
		numerator = (f1.numerator * f2.denominator) - (f1.denominator * f2.numerator); //subtracts the numerator
		denominator = (f1.denominator * f2.denominator);							   //subtracts the denominator
	}	//end function sub
	
	void Rational::mult(Rational f1, Rational f2) {			
		//a / b * c / d = [n]( a * c) [d](b * d)
		numerator = (f1.numerator * f2.numerator);									   //multiplys the numerator
		denominator = (f1.denominator * f2.denominator);							   //multiplys the denominator
	}	//end function mult
	
	void Rational::div(Rational f1, Rational f2) {			
		//a / b / c / d =[n](a * d)[d](b * c)
		numerator = (f1.numerator * f2.numerator);									   //divides the numerator
		denominator = (f1.denominator * f2.denominator);							   //divides the denominator
	}	//end function div
	
	void Rational::displaysgl() {		
		cout << numerator << "/" << denominator;	
	}	//end function displaysgl

	void Rational::displayfloat(Rational f3) {
		deci = ((float)f3.numerator) / f3.denominator;
		cout << fixed << setprecision( 3 )<< deci;
	}	//end function displayfloat
	
int main() {
	Rational f1;
	Rational f2;
	Rational f3;
	Rational d;
	 int a;
	 do 
	 {
		 cout << endl; 
		 cout <<"1. Input rationals" << endl;
		 cout <<"2. Add rationals" << endl; 
		 cout <<"3. Subtract rationals" << endl;
		 cout <<"4. Multiply rationals" << endl;
		 cout <<"5. Divide rationals" << endl;
		 cout <<"6. Quit" << endl << endl;
		 cout <<"Selection choice: "; 
		 cin >> a;
		 switch(a)
		 {
			 case 1:
				 cout<<endl<<"Enter info for first Rational";
				 f1.sglfrac();
				 cout<<endl<<"Enter info for second Rational";
				 f2.sglfrac();
			 break;
			 case 2:
				f3.add(f1, f2);
						cout << setw(8);
					 f1.displaysgl();
						cout << " + "; 
					 f2.displaysgl();
						cout << " = ";
					 f3.displaysgl();
						cout << " or ";
					 d.displayfloat(f3);
						cout << endl;
			 break;
			 case 3:
				f3.sub(f1, f2);
					 f3.add(f1, f2);
						cout << setw(8);
					 f1.displaysgl();
						cout << " + "; 
					 f2.displaysgl();
						cout << " = ";
					 f3.displaysgl();
						cout << " or ";
					 d.displayfloat(f3);
						cout << endl;								 
			 case 4: 
				f3.mult(f1, f2);
					 f3.add(f1, f2);
						cout << setw(8);
					 f1.displaysgl();
						cout << " + "; 
					 f2.displaysgl();
						cout << " = ";
					 f3.displaysgl();
						cout << " or ";
					 d.displayfloat(f3);
						cout << endl;			 
			 break;
			 case 5:
				f3.div(f1, f2);
						cout << setw(8);
					 f1.displaysgl();
						cout << " + "; 
					 f2.displaysgl();
						cout << " = ";
					 f3.displaysgl();
						cout << " or ";
					 d.displayfloat(f3);
						cout << endl;			 
			 break;
			 case 6:
			 exit(1);
			 break;
		 }
	 } while (a!=6);
 }	//end main

What I'm trying to do is add sub mult divide 2 different fractions.

actually i was told to put the reduce and normalize in the private section
Thank you for the help so far

actually i was told to put the reduce and normalize in the private section
Thank you for the help so far

Ah, I see. So your add is adding the two Rational objects then you want it to call reduce and normalize. If that's the case, you shouldn't need to pass anything by reference. You should only need to call the functions inside your Add function, you shouldn't need parameters.

It seems to me like you might have got a little confused about just what gets copied when you pass by value. If you have a function, like your Rational::add() function, and you declare it as:

void add(Rational f2, Rational f3);

Then you are using pass-by-value. I think that you understand this, correct? But what is being copied exactly might be what you're not clear on. So if you have a statement in your code, like

Rational f1, f2, f3;
f1.add(f2, f3);

Then, when add() is called, copies of f2 and f3 are made within the add() function, for use there. Any changes that you make to f2 and f3 will not be passed back to the original variables in the calling function (probably main() . f1 does not get copied at any point, changes that you make to the members of f1 are retained after add() finishes.

When you pass by reference, then (as Red Goose already said) the memory addresses of the variables are passed to the function and no copies are made. So, your declarations might look like:

void add(Rational &f2, Rational &f3);

There is only ever one version of f2 and f3 (and also, as with the previous example, there is only ever one version of f1 ).

In many cases, it is preferable to pass classes by reference, even when you don't what to change them. In this case, you should use a const reference:

int myFunction(MyClass &arg1, const MyClass &arg2);

the first argument is going to be changed by the function, but arg2 definitely will not.

Some other points on your program:

  • You don't have to pass a variable to a member function so, for example, your function void normalize(Rational &); could be declared as void normalize(); (as Red Goose said).
  • You have a member variable called deci , which I presume stores a decimal version of your number. This violates a principle of program design that you shouldn't repeat yourself. It would be betted to just have a function called deci() that calculates this value when it's needed. Otherwise, you have to worry about updating this value every time you perform an operation on the object.
  • Your function sglfrac is trying to do too much. You should let the person that is using this class deal with details like this. What you should do as the class designed, is provide an access function that enables users to set these variables. So, using your current interface, you can set the values of numerator and denominator by doing:
    Rational r;
    r.sglfrac();

    Seems convenient, right? Maybe, but what if I'm writing a program using your Rational class, and I happen to be Japanese? There's no way I can translate it. It's better to provide a function, called something like set(int, int); that you can use like this:

    Rational r;
    int num, denom;
    cout << "\nnumerator: "; cin >> num;  
    cout << "denominator: "; cin >> denom;
    
    r.set(num, denom);

    This looks less neat, but it's actually much more flexible, and you won't have to keep re-writing your classes for use in different situations. You can sort of see the problem here:

    cout<<endl<<"Enter info for first Rational";
    f1.sglfrac();

    you have half the user interface in the client code (your main() function in this case) and half in the class implementation! This sounds like "nit-picking" at the moment, but these are good habits to break early!

commented: Excellent points. +1
commented: Nice one. +6

In many cases, it is preferable to pass classes by reference, even when you don't what to change them. In this case, you should use a const reference:

And just to clarify, the reason you'd do this is because when you pass by value, and thus create a copy of your object, you also have to allocate the memory for an entirely new object. This isn't that bad with your small classes, but with larger ones, in larger codes, it can greatly hinder performance. The only thing the constant is doing is ensuring you don't accidentally change the value of the object you're passing. This makes tracking bugs easier since your compiler will give you an error if you accidentally try to change the constant. It's a favor to yourself to use it.

ok so I try calling them like this
reduce();
but I get this error
error C2660: 'Rational::reduce' : function does not take 0 arguments

sorry wrote that before i noticed the new posts

Remember, you also need to delete the reference parameter inside your class declaration.

Oh my i am actually understanding this and my program works :D yay thanks you guys. i know my code is super messy i'm a beginner and am just grasping the concepts so far thanks for the tips ravenous i do need to start to get my program to be more flexible and red goose your a life saver thank you even though i didn't need to use pass by reference i now know how to :) yay

commented: Good luck with your programming. +1
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.