|
Another Segmentation Fault Problem
Hello again everybody. Today, my problem is getting a comparisons program to work with Rationals, or fractions for those that don't know. My teacher gave us a test program that would check to see if the program we wrote would work the way he wanted it to. However, when I go to use the program it does the first check, if 1/4 is less than 1/3, says segmentation fault and quits.
The program I wrote is as follows:
#include <iostream>
using namespace std;
#include "Rational.h"
// the setNumerator function sets the numerator value for the object.
void Rational::setNumerator (int numer)
{
numeratorValue = numer;
}
// setDenominator is responsible for changing the denominatorValue data
// member. It does some basic error checking to make sure we don.t try
// to set a 0 as the denominator. Our solution to this is to set the
// denom to 1 after outputting an error message
void Rational::setDenominator (int denom)
{
if (denom != 0)
{
denominatorValue = denom;
}
else
{
cerr << "Illegal denominator. Using 1 instead" << endl;
denominatorValue = 1;
}
return;
}
// specific constructor, called when one or two arguments are given
// in object instantiation. Sets rational to appropriate value
Rational::Rational (int numer, int denom)
{
setNumerator(numer);
setDenominator(denom);
reduce();
}
// getNumerator and getDenominator are simple, private inspector
// member functions that return the values of the numerator and
// denominator for our object.
int Rational::getNumerator() const
{
return numeratorValue;
}
int Rational::getDenominator() const
{
return denominatorValue;
}
// add() performs addition of two Rational objects. One object
// is doing the addition, the other object (the argument) is being
// added. This function creates a very (very!) temporary third
// Rational object as it.s setting itself up to return a value. It
// returns the newly created Rational object. This is one of
// the few times you see a constructor called explicitly.
Rational Rational::add (const Rational &r) const
{
int a = getNumerator();
int b = getDenominator();
int c = r.getNumerator();
int d = r.getDenominator();
Rational result(a*d + b*c, b*d);
return result;
}
// multiply() performs multiplying two Rational objects. One object
// is doing the multiplying, the other object (the argument) is being
// multiplied. This function creates a very (very!) temporary third
// Rational object as it.s setting itself up to return a value. It
// returns the newly created Rational object. This is one of
// the few times you see a constructor called explicitly.
Rational Rational::multiply (const Rational &r) const
{
int a = getNumerator();
int b = getDenominator();
int c = r.getNumerator();
int d = r.getDenominator();
Rational result(a*c, b*d);
return result;
}
// insert() takes an ostream as the only argument. An ostream
// is an output stream, like cout. by making this an argument, you
// could output Rational numbers to files or other devices or streams.
void Rational::insert (ostream &streamout) const
{
streamout << getNumerator() << "/" << getDenominator();
return;
}
// extract() takes an istream as the only argument. An istream
// is an input stream, like cin. by making this an argument, you
// could input Rational numbers from files or other devices or
// streams.
void Rational::extract (istream &streamin)
{
int numer;
int denom;
char slash;
streamin >> numer >> slash >> denom;
setNumerator(numer);
setDenominator(denom);
reduce();
return;
}
// Here we implement the + operator. all this "function" does is end
// up calling the add() behavior of the rational number class.
// by overloading the operator, we are providing the .natural
// interface. for the object that we are looking for to make working
// with Rational objects intuitive.
Rational operator+ (const Rational &left, const Rational &right)
{
return left.add(right);
}
// and here is the implementation for the * operator. We simply end up
// calling the multiply() behavior of a rational object.
Rational operator* (const Rational &left, const Rational &right)
{
return left.multiply(right);
}
// here is the implementation for the << operator. We simply end
// up calling the insert() behavior of a rational object. Because
// of the "nature of output" in C++ (to be explained in more detail in 1620)
// we need to return the ostream out of the function. This is
// a critical step in overloading the << operator.
ostream& operator<< (ostream &output, const Rational &rat)
{
rat.insert(output);
return output;
}
// similar stuff for >> operator.
istream& operator>> (istream &input, Rational &rat)
// is an input stream, like cin. by making this an argument, you
// could input Rational numbers from files or other devices or
// streams.
void Rational::extract (istream &streamin)
{
int numer;
int denom;
char slash;
streamin >> numer >> slash >> denom;
setNumerator(numer);
setDenominator(denom);
reduce();
return;
}
// Here we implement the + operator. all this "function" does is end
// up calling the add() behavior of the rational number class.
// by overloading the operator, we are providing the .natural
// interface. for the object that we are looking for to make working
// with Rational objects intuitive.
Rational operator+ (const Rational &left, const Rational &right)
{
return left.add(right);
}
// and here is the implementation for the * operator. We simply end up
// calling the multiply() behavior of a rational object.
Rational operator* (const Rational &left, const Rational &right)
{
return left.multiply(right);
}
ostream& operator<< (ostream &output, const Rational &rat)
{
rat.insert(output);
return output;
}
istream& operator>> (istream &input, Rational &rat)
{
rat.extract(input);
return input;
}
/* This is all stuff he wrote with the excpetion of reduce() parts. Below is what I wrote.
*/
Rational operator- (const Rational &left, const Rational &right)
{
return left.subtract(right);
}
Rational operator/ (const Rational &left, const Rational &right)
{
return left.divide(right);
}
bool operator< (const Rational &left, const Rational &right)
{
return left.lessThan(right);
}
bool operator<= (const Rational &left, const Rational &right)
{
return left.lessThanEqual(right);
}
bool operator> (const Rational &left, const Rational &right)
{
return left.greaterThan(right);
}
bool operator>= (const Rational &left, const Rational &right)
{
return left.greaterThanEqual(right);
}
bool operator== (const Rational &left, const Rational &right)
{
return left.equalTo(right);
}
bool operator!= (const Rational &left, const Rational &right)
{
return left.notEqualTo(right);
}
Rational Rational::subtract (const Rational &r) const
{
int a = getNumerator();
int b = getDenominator();
int c = r.getNumerator();
int d = r.getDenominator();
Rational result(a*d - b*c, b*d);
return result;
}
Rational Rational::divide (const Rational &r) const
{
int a = getNumerator();
int b = getDenominator();
int c = r.getNumerator();
int d = r.getDenominator();
Rational result(a*d, b*c);
return result;
}
bool Rational::lessThan (const Rational &r) const
{
int a = getNumerator();
int b = getDenominator();
int c = r.getNumerator();
int d = r.getDenominator();
if (Rational(a,b) < Rational(c,d))
return true;
else
return false;
}
bool Rational::lessThanEqual (const Rational &r) const
{
int a = getNumerator();
int b = getDenominator();
int c = r.getNumerator();
int d = r.getDenominator();
if (Rational(a,b) <= Rational(c,d))
return true;
else
return false;
}
bool Rational::greaterThan (const Rational &r) const
{
int a = getNumerator();
int b = getDenominator();
int c = r.getNumerator();
int d = r.getDenominator();
if (Rational(a,b) > Rational(c,d))
return true;
else
return false;
}
bool Rational::greaterThanEqual (const Rational &r) const
{
int a = getNumerator();
int b = getDenominator();
int c = r.getNumerator();
int d = r.getDenominator();
if (Rational(a,b) >= Rational(c,d))
return true;
else
return false;
}
bool Rational::equalTo (const Rational &r) const
{
int a = getNumerator();
int b = getDenominator();
int c = r.getNumerator();
int d = r.getDenominator();
if (Rational(a,b) == Rational(c,d))
return true;
else
return false;
}
bool Rational::notEqualTo (const Rational &r) const
{
int a = getNumerator();
int b = getDenominator();
int c = r.getNumerator();
int d = r.getDenominator();
if (Rational(a,b) != Rational(c,d))
return true;
else
return false;
}
void Rational::reduce()
{
int a = numeratorValue;
int b = denominatorValue;
int c = 1;
for ( int counter = 1; counter <= a; counter++ )
if ( a % counter == 0 && b % counter == 0 )
c = counter;
numeratorValue = a/c;
denominatorValue = b/c;
return;
}
If you noticed, the program called for a class file and that will follow this.
Rational.h
#ifndef RATIONAL_H
#define RATIONAL_H
#include <iostream>
using namespace std;
class Rational
{
public:
Rational (int num = 0, int den = 1);
Rational add (const Rational &r) const;
Rational multiply (const Rational &r) const;
void insert (ostream &output) const;
void extract (istream &input);
// These are new and must be implemented
Rational subtract (const Rational &r) const;
Rational divide (const Rational &r) const;
bool lessThan (const Rational &r) const;
bool lessThanEqual (const Rational &r) const;
bool greaterThan (const Rational &r) const;
bool greaterThanEqual (const Rational &r) const;
bool equalTo (const Rational &r) const;
bool notEqualTo (const Rational &r) const;
private:
int getNumerator() const;
int getDenominator() const;
void setNumerator (int numer);
void setDenominator (int denom);
// Reduce is new and must be implemented
void reduce();
int numeratorValue;
int denominatorValue;
};
// Here, we prototype the overloaded operators. All but the last four are new
// and must be implemented. The operator<->member function relationship should
// be obvious (i.e., operator<= should be implemented to call the lessThanEqual
// member function).
Rational operator- (const Rational &left, const Rational &right);
Rational operator/ (const Rational &left, const Rational &right);
bool operator< (const Rational &left, const Rational &right);
bool operator<= (const Rational &left, const Rational &right);
bool operator> (const Rational &left, const Rational &right);
bool operator>= (const Rational &left, const Rational &right);
bool operator== (const Rational &left, const Rational &right);
bool operator!= (const Rational &left, const Rational &right);
Rational operator+ (const Rational &left, const Rational &right);
Rational operator* (const Rational &left, const Rational &right);
ostream& operator<< (ostream &streamout, const Rational &s);
istream& operator>> (istream &streamin, Rational &r);
#endif
And finally, here is the test program that the teacher gave us.
rattest.cpp
#include <iostream>
using namespace std;
#include "Rational.h"
void printHeader (const Rational &r, const Rational &l, const char * op);
int main ()
{
Rational first(1,4);
Rational second(1,3);
/*************************************************************************
*************************************************************************/
printHeader(first,second,"<");
if (first < second)
{
cout << "This is true. This test was correct." << endl;
}
else
{
cout << "This test failed." << endl;
}
/*************************************************************************
*************************************************************************/
printHeader(first,second,"<=");
if (first <= second)
{
cout << "This is true. This test was correct." << endl;
}
else
{
cout << "This test failed." << endl;
}
/*************************************************************************
*************************************************************************/
printHeader(first,second,">");
if (first > second)
{
cout << "This test failed." << endl;
}
else
{
cout << "This is false. This test was correct." << endl;
}
/*************************************************************************
*************************************************************************/
printHeader(first,second,">=");
if (first >= second)
{
cout << "This test failed." << endl;
}
else
{
cout << "This is false. This test was correct." << endl;
}
/*************************************************************************
*************************************************************************/
printHeader(first,second,"==");
if (first == second)
{
cout << "This test failed." << endl;
}
else
{
cout << "This is false. This test was correct." << endl;
}
/*************************************************************************
*************************************************************************/
printHeader(first,second,"!=");
if (first != second)
{
cout << "This is true. This test was correct." << endl;
}
else
{
cout << "This test failed." << endl;
}
/*************************************************************************
*************************************************************************/
printHeader(first,second,"+");
cout << "\tnote: result should be 7/12" << endl;
cout << "\tYour result: " << first + second << endl << endl;
/*************************************************************************
*************************************************************************/
printHeader(first,second,"-");
cout << "\tnote: result should be -1/12" << endl;
cout << "\tYour result: " << first - second << endl << endl;
/*************************************************************************
*************************************************************************/
printHeader(first,second,"*");
cout << "\tnote: result should be 1/12" << endl;
cout << "\tYour result: " << first * second << endl << endl;
/*************************************************************************
*************************************************************************/
printHeader(first,second,"/");
cout << "\tnote: result should be 3/4" << endl;
cout << "\tYour result: " << first / second << endl << endl;
/*************************************************************************
*************************************************************************/
Rational testReduce (65,165);
cout << endl << "=============================================================================" << endl << endl;
cout << "Now testing reduction of 65/165. Should be 13/33." << endl;
cout << endl << "\tYour result: " << testReduce << endl;
cout << endl;
/*************************************************************************
*************************************************************************/
Rational testReduce2 (165,65);
cout << endl << "=============================================================================" << endl << endl;
cout << "Now testing reduction of 165/65. Should be 33/13." << endl;
cout << endl << "\tYour result: " << testReduce2 << endl;
cout << endl;
/*************************************************************************
*************************************************************************/
Rational testReduce3 (17,17);
cout << endl << "=============================================================================" << endl << endl;
cout << "Now testing reduction of 17/17. Should be 1/1." << endl;
cout << endl << "\tYour result: " << testReduce3 << endl;
cout << endl;
/*************************************************************************
*************************************************************************/
Rational tester4;
cout << endl << "=============================================================================" << endl << endl;
cout << "Now testing input. Enter 8/6 when prompted." << endl;
cout << endl << "Enter 8/6 now: " << flush;
cin >> tester4;
cout << endl << "\tYour Rational number is: " << tester4 << endl;
cout << endl << "\tThe output should be 4/3 since it should reduce.";
cout << endl << endl;
cout << endl << "NOTE: If that scrolled by too quickly, you will want to scroll up to see if all of your functions work correctly.\n\n";
return 0;
}
/****************************************************************************
****************************************************************************/
void printHeader (const Rational &r, const Rational &l, const char * op)
{
cout << endl << "=============================================================================" << endl << endl;
cout << "Now testing the " << op << " operator:" << endl << endl;
cout << "\tTesting " << r << " " << op << " " << l << endl << endl;
}
If that 's not enough to keep people busy for days then I don't know what is. For what I think is wrong is how the printHeader function is running but I was never any good at programming.
I'll be looking at the code for a good while and trying to muddle through it. Any help would be appriciated.
|