Rational Class Lab

This is my first time posting here so I'm sorry if there are some formatting rules that I am not following.

I'm having some trouble with my Rational Class program. I think the problem is with my readRational but I'm not sure. The input that i use in this case is 3/4 and then 4/5 but when i output those inputs, I don't get the value that I input.
Another problem is with my constructors. Whenever I declare them i get the error "undefined reference to `rational::rational()'"


-----------------------------------------------------------------------------
#include <iostream>

using namespace std;

class rational
{
public:
// ToDo: Constructor that takes int numerator and int denominator

// ToDo: Constructor that takes int numerator

// ToDo: Default Constructor

// ToDo: Member function to read a rational in the form: n/d
void readRational();
// ToDo: Member function to write a rational as n/d
void printRational();
// ToDo: declare an accessor function to get the numerator
int getNumerator();
// ToDo: declare an accessor function to get the denominator
int getDenominator();
// ToDo: delcare a function called Sum that takes two rational objects
// sets the current object to the sum of the given objects using the
// formula: a/b + c/d = ( a*d + b*c)/(b*d)
int sum(rational, rational, rational);

private:
int numerator;
int denominator;

};

void rational::readRational()
{
int numerator, denominator;
char slash;

// Use this model for your rational class, even though we
// generally don't loop in an input function.
do {
cin >> numerator >> slash >> denominator;
if (slash != '/' || denominator < 0) {
cout << "wrong input." << endl;
cout << "Enter a valid rational: ";
}
} while (slash != '/' || denominator < 0);

}

void rational::printRational()
{
cout << numerator << "/" << denominator;
}

int rational::getNumerator()
{
return numerator;
}

int rational::getDenominator()
{
return denominator;
}

int rational::sum(rational op1, rational op2, rational op3)
{
op3.numerator = (op1.numerator * op2.denominator) + (op2.numerator * op1.denominator);
op3.denominator = op1.denominator * op2.denominator;
}

int main()
{
// ToDo: declare three rational objects using the default constructor
char answer;
rational op1, op2, op3;

// Main loop to read in rationals and compute the sum
do {
cout << "\nEnter op1 (in the format of p/q): ";
// ToDo: use your input member function to read the first rational
op1.readRational();
op1.printRational();

cout << "\nEnter op2 (in the format of p/q): ";
// ToDo: use your input member function to read the second rational
op2.readRational();
op2.printRational();


// ToDo: use the third rational to call Sum with first and second as parameters
op3.sum(op1, op2, op3);

cout << "\nThe sum of op1 and op2 is: ";
// ToDo: ouptput the third rational
op3.printRational();

cout << endl;

cout << "\nTry again (Y/N)?";
cin >> answer;

} while (answer == 'y' || answer == 'Y');

// ToDo: test getters
cout << "\nC's numerator is: " ;
cout << "\nC's denominator is: ";

// TODO: Use two constructors to declare a whole number 3/1 and a 4/5

// TODO: Use output to print both rationals


return 0;
}
-----------------------------------------------------------------------------
1) In your method readRational():
int numerator, denominator;
These local variables shadow your class properties (it means this method does pretty nothing).


2) Your method sum() doesn’t return anything, but it’s declared ‘int’ (which is unclear, btw; shouldn’t it return a rational?)


3) Your class properties are uninitialized.
It means they contains garbage.
Another problem is with my constructors. Whenever I declare them i get the error "undefined reference to `rational::rational()'"

Cannot reproduce your error: I can add any constructor I want.
Example:
1
2
3
4
5
rational::rational()
    : numerator {}
    , denominator {}
{
}


Please provide a code example which raises that error.
What should I return in my sum function? And yeah I realized that it was supposed to be rational instead of int thank you.



The constructors that I used were. I put these in the rational class
1
2
3
4
5
6
7
public:
	// ToDo: Constructor that takes int numerator and int denominator
    rational(int numerator, int denominator);
	// ToDo: Constructor that takes int numerator
    rational(int numerator);
	// ToDo: Default Constructor
    rational();
typically it looks more like this:

1
2
3
4
5
6
7
8
rational rational::sum(rational &op1, rational &op2)
{
rational result;
result.numerator = (op1.numerator * op2.denominator) + (op2.numerator * op1.denominator);
result.denominator = op1.denominator * op2.denominator;
return result;
}


you can make it pretty with the <> tool on the side-bar editor or [word][/word] tags where word = code

while it is possible to pass in a variable to fill out as the result in a function, you don't see as much of that in object oriented code. Remember to pass by reference as well if you do that. Its best to pass objects by reference anyway, for performance reasons (it avoids a time wasting copy operation).
Last edited on
OK thank you. I got that to work.

Now how can I get the program to print just the numerator or just the denominator of result in the main function?
1
2
3
4
5
6
7
public:
	// ToDo: Constructor that takes int numerator and int denominator
    rational(int numerator, int denominator);
	// ToDo: Constructor that takes int numerator
    rational(int numerator);
	// ToDo: Default Constructor
    rational();	


This compiles:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
rational::rational(int numerator_arg, int denominator_arg)
    : numerator { numerator_arg }
    , denominator { denominator_arg }
{
}

rational::rational(int numerator_arg)
    : numerator { numerator_arg }
    , denominator { 1 }
{
}

rational::rational()
    : numerator {}
    , denominator {}
{
}

Sorry. I'm new to this. Could you explain what the _arg is for and what it means
you do not want to use the same names as the class data members. You "can" but it is messier.

if you have this
class.... etc...
int a; int b;
name::name(int a, int b)
{
a = a; //compiler can't tell which a is which here. this won't do what you want.
this-> a = a; //extra clutter tells it to make the class variable have the input value.
}

_arg is just adding a little something to your variable names to avoid this situation.
he could also have just said num and dem or x and y or whatever. _ is a legal character in a variable name and is often used to split words in some code styles.
Last edited on
jonnin wrote:
he could also have just said num and dem or x and y or whatever

Perfect explanation.

I’ve stolen this charming ‘_arg’ suffix from someone on this forum, I’m quite sure it was mbozzi. I immediately fell in love with it :) and I think it increases code readability a lot.

Ah. I see.

Ok. I think this should be my last question. How can i get the program to print out just the numerator or just the denominator?
cout << variable.getDenominator() << endl; //assuming you filled this out?

because you made them private you can print inside the class where you have access or you have to use the accessor (getter, some call them).

What should I return in my sum function?

The assignment tells you what it should do:
1
2
3
// ToDo: delcare a function called Sum that takes two rational objects
// sets the current object to the sum of the given objects using the
// formula: a/b + c/d = ( a*d + b*c)/(b*d) 


So it it takes two arguments and modifies the current object. I suppose you could return the current object or void, just be sure that you modify the current object.
1
2
3
4
5
Rational sum(Rational a, Rational b)
{
    // add a and b, storing the result in this.
    return *this;
}

Topic archived. No new replies allowed.