Section 5 - Exceptions - Full Listing
5B.5.1 Rational Number Class Listing
This is a listing of the entire program and Rational number class in case you want to try it and/or modify it.
#include <iostream> #include <string> #include <sstream> using namespace std; // Rational prototype -------------------------------- class Rational { // friend operators friend Rational operator+(Rational r1, Rational r2); friend Rational operator-(Rational r1, Rational r2); friend ostream & operator<<(ostream& strm, Rational& r); private: long num, den; long gcd(); void reduce(); public: Rational( long n = 0, long d = 1 ); Rational( string ratString ); void set( long n = 0, long d = 1 ); void set( string ratString ); void show(); // exception classes class BadRationalString { }; class ZeroDenominator { }; }; // main method --------------------------------------- int main() { try { Rational a(1, 2), b(3, 4), c("+5/4"), d("50/-90"), e(5), f("1000"); cout << "a: " << a << " b: " << b << endl; cout << "c: " << c << " d: " << d << endl; cout << "e: " << e << " f: " << f << endl << endl; } catch (Rational::BadRationalString) { cout << "*** bad string ***" << endl; } catch (Rational::ZeroDenominator) { cout << "*** zero denominator ***" << endl; } Rational a, b, c, d; try { a.set(3244, 22); cout << "a: " << a << endl; b.set("45/5"); cout << "b: " << b << endl; c.set("12.3/8"); cout << "c: " << c << endl; d.set(8443, 0); cout << "d: " << d << endl; } catch (Rational::BadRationalString) { cout << "*** bad string ***" << endl; } catch (Rational::ZeroDenominator) { cout << "*** zero denominator ***" << endl; } return 0; } // Rational method definitions -------------------------- Rational::Rational(long n, long d) { set(n, d); } Rational::Rational(string ratString) { set(ratString); } void Rational::set(string ratString) { long tryNum, tryDen, slashPos, lengthOfDenStr; string strNum, strDen; int k; // contingency values in case we throw exception num = 0; den = 1; // must be of form "int/int" slashPos = ratString.find("/"); if (slashPos == 0 || slashPos > 50) throw BadRationalString(); // returns immediately if ( slashPos < 0 ) { // no "/". hopefully just an int strNum = ratString; strDen = "1"; } else { strNum = ratString.substr(0, slashPos); lengthOfDenStr = ratString.length() - slashPos - 1; strDen = ratString.substr(slashPos+1, lengthOfDenStr); } // make sure strNum is valid number // first digit can be digit, or +/- if ( !isdigit(strNum[0] ) && strNum[0] != '-' && strNum[0] != '+') throw BadRationalString(); // returns immed. // rest must be digits for (k = 1; k < strNum.length(); k++) if ( !isdigit(strNum[k]) ) throw BadRationalString(); // returns immed. // same test for strDen if ( !isdigit(strDen[0] ) && strDen[0] != '-' && strDen[0] != '+') throw BadRationalString(); // returns immed. for (k = 1; k < strDen.length(); k++) if ( !isdigit(strDen[k]) ) throw BadRationalString(); // returns immed. // convert to ints istringstream(strDen) >> tryDen; istringstream(strNum) >> tryNum; set(tryNum, tryDen); } void Rational::set(long n, long d) { // defaults in case of user error (bad d) num = 1 ; den = 0; if (d==0) throw ZeroDenominator(); num = n; den = d; reduce(); } long Rational::gcd() // greatest common denominator of num and den { long temp, n, d; for ( n = num, d = den; d != 0; ) { temp = n % d; n = d; d = temp; } return n; } void Rational::reduce() { long myGcd = gcd(); if (myGcd > 1) { num /= myGcd; den /= myGcd; } if (den < 0) { den = -den; num = -num; } } void Rational::show() { cout << " " << num; if (den != 1) cout << "/" << den; } // end Rational method definitions --------------------- // overloaded operator functions --------------------- Rational operator+( Rational r1, Rational r2) { Rational temp; temp.num = r1.num * r2.den + r1.den * r2.num; temp.den = r1.den * r2.den; temp.reduce(); return temp; } Rational operator-(Rational r1, Rational r2) { Rational temp; temp.num = r1.num * r2.den - r1.den * r2.num; temp.den = r1.den * r2.den; temp.reduce(); return temp; } ostream & operator<<(ostream& strm, Rational& r) { strm << " " << r.num; if (r.den != 1) strm << "/" << r.den; return strm; }