Reputation: 31
I'm writing a fraction.cpp and fraction.h that inputs fraction types and does mathematical operations on them. I have a weird error that says "undefined reference", but the reference is defined as far as I can see. There's also a bunch of errors that say "no matching function for call to fraction::outputFormat(fracForm)" and "candidate is" and others. Here is all of my code for reference: main.cpp
#include <iostream>
#include <iomanip>
using namespace std;
#include "fraction.h"
int main()
{
fraction f0;
fraction f1;
cin >> f0; // input format numerator/denominator, ex 23/9
cout << "input: " << f0 << endl; // outputs what was input
// Note the << and >> operators should also work for file streams
// cin >> f0 >> f1; // reads 2 fractions, ex 8/5 12/16
f1.setFraction(17,6); // 17/6
cout << f1.getNumerator() << '/' << f1.getDenominator() << endl; // 17/6
f1.setFraction(-4.75); // -19/4
cout << f1.decimalValue() << endl; // outputs -4.75
fraction f2(4,8); // 4/8
fraction f3(2.875); // 2 7/8
cout << f3 << endl; // outputs 2 7/8 (the default output format is mixed)
cout << f2 << endl; // outputs 4/8
fraction f4(16,8);
cout << f4 << endl; // outputs 2
fraction::outputFormat(improper); // set output format to improper fraction
cout << f4 << endl; // outputs 16/8
cout << f3 << endl; // outputs 23/8
cout << f1 << endl; // outputs -19/4
fraction::outputFormat(decimal); // set output format to decimal value
cout << f3 << endl; // outputs 2.875
cout << f2 << endl; // outputs 0.5
cout << f1 << endl; // outputs -4.75
fraction::outputFormat(mixed); // set output format back to default mixed
cout << f3 << endl; // outputs 2 7/8
f1.setFraction(-4.75);
cout << f1 << endl; // outputs -4 3/4
cout << f2 << endl; // outputs 4/8
fraction f5(12,8);
fraction::outputFormat(improper);
cout << f5 << endl; // outputs 12/8
f2.reduce(); // convert to lowest terms
f5.reduce();
cout << f2 << endl; // outputs 1/2
cout << f5 << endl; // outputs 3/2
f5.setDenominator(16); // change denominator and numerator
// error if numerator is not a whole number
cout << f5 << endl; // outputs 24/16
f5.setDenominator(22);
cout << f5 << endl; // outputs 33/22
f5.setDenominator(5); // output error as numerator would have to be 7.5
cout << f5 << endl; // outputs 33/22 (fraction remained the same)
f1 = f3+f2; // f1 put in lowest terms
cout << f1 << endl; // outputs 27/8
f1 = f3-f2;
cout << f1 << endl;
f1 = f3*f2;
cout << f1 << endl;
f1 = f3/f2;
cout << f1 << endl;
f1 = f3;
cout << f1 << endl; // outputs 23/8
f1 = 7.75;
f1 = f2 = 7.75;
cout << f1 << endl; // outputs 31/4
cout << setw(6) << f1 << setw(6) << f2 << endl; // outputs 31/4 31/4
f0.setFraction(31,4);
if (f0 == f1)
cout << "correct\n";
else
cout << "incorrect\n";
// all relational operators should work for comparing 2 fractions
if (f0 == 7.75)
cout << "correct\n";
else
cout << "incorrect\n";
// all relational operators should work for comparing fraction to double
f0.setFraction(2);
if (f0 < 3)
cout << "correct\n";
else
cout << "incorrect\n";
// all relational operators should work for comparing fraction to int
return 0;
}
fraction.h
#ifndef fraction
#include <iostream>
using namespace std;
enum fracForm {improper, mixed, decimal};
class fraction {
enum fracForm {improper, mixed, decimal};
friend istream& operator>>(istream&, fraction&);
friend ostream& operator<<(ostream&, fraction&);
public:
fraction();
fraction(int, int);
fraction(double);
void setFraction(int, int);
void setFraction(double);
void setDenominator(int);
int getNumerator() const;
int getDenominator() const;
double decimalValue() const;
static void outputFormat(fracForm);
void reduce();
fraction operator+(const fraction&) const;
fraction operator-(const fraction&) const;
fraction operator*(const fraction&) const;
fraction operator/(const fraction&) const;
bool operator==(const fraction&) const;
bool operator!=(const fraction&) const;
bool operator<(const fraction&) const;
bool operator>(const fraction&) const;
bool operator<=(const fraction&) const;
bool operator>=(const fraction&) const;
fraction operator+(const int) const;
fraction operator-(const int) const;
fraction operator*(const int) const;
fraction operator/(const int) const;
bool operator==(const int) const;
bool operator!=(const int) const;
bool operator<(const int) const;
bool operator>(const int) const;
bool operator<=(const int) const;
bool operator>=(const int) const;
fraction operator+(const float) const;
fraction operator-(const float) const;
fraction operator*(const float) const;
fraction operator/(const float) const;
bool operator==(const float) const;
bool operator!=(const float) const;
bool operator<(const float) const;
bool operator>(const float) const;
bool operator<=(const float) const;
bool operator>=(const float) const;
fraction operator+(const double) const;
fraction operator-(const double) const;
fraction operator*(const double) const;
fraction operator/(const double) const;
bool operator==(const double) const;
bool operator!=(const double) const;
bool operator<(const double) const;
bool operator>(const double) const;
bool operator<=(const double) const;
bool operator>=(const double) const;
string mix();
private:
int num, denom;
static fracForm format;
};
#endif
fraction.cpp
#include "fraction.h"
#include <iostream>
#include <algorithm>
fraction::fraction() {
num = 0;
denom = 1;
}
fraction::fraction(int numerator, int denominator) {
setFraction(numerator, denominator);
}
fraction::fraction(double deci) {
setFraction(deci);
}
void fraction::setFraction(int numerator, int denominator){
num = numerator;
denom = denominator;
}
void fraction::setFraction(double deci) {
int decimal = deci;
denom = 1;
while (deci != decimal) {
deci = deci * 10;
denom = denom * 10;
decimal = deci;
}
num = deci;
reduce();
}
void fraction::setDenominator(int denominator) {
int denom2 = denominator;
int proportion = num * denom2;
double newProp = proportion / denom;
int intProp = newProp;
if (newProp != intProp) {
try
{
throw 20;
}
catch (int n)
{
cout << "This does not create a fraction with integers." << endl;
}
}
else {num = newProp; denom = denom2;}
}
int fraction::getNumerator() const {
return num;
}
int fraction::getDenominator() const{
return denom;
}
double fraction::decimalValue() const {
double deci = num/denom;
return deci;
}
void fraction::outputFormat(fracForm fType) {
format = fType;
}
void fraction::reduce() {
num = num / __gcd(num, denom);
denom = denom / __gcd(num, denom);
}
fraction fraction::operator+(const fraction& frac) const {
return fraction(decimalValue() + frac.decimalValue());
}
fraction fraction::operator-(const fraction& frac) const {
return fraction(decimalValue() - frac.decimalValue());
}
fraction fraction::operator*(const fraction& frac) const {
return fraction(decimalValue() * frac.decimalValue());
}
fraction fraction::operator/(const fraction& frac) const {
return fraction(decimalValue() / frac.decimalValue());
}
bool fraction::operator==(const fraction& frac) const {
return decimalValue() == frac.decimalValue();
}
bool fraction::operator!=(const fraction& frac) const {
return decimalValue() != frac.decimalValue();
}
bool fraction::operator<(const fraction& frac) const {
return decimalValue() < frac.decimalValue();
}
bool fraction::operator>(const fraction& frac) const {
return decimalValue() > frac.decimalValue();
}
bool fraction::operator<=(const fraction& frac) const {
return decimalValue() <= frac.decimalValue();
}
bool fraction::operator>=(const fraction& frac) const {
return decimalValue() >= frac.decimalValue();
}
fraction fraction::operator+(const int frac) const {
return fraction(decimalValue() + frac);
}
fraction fraction::operator-(const int frac) const {
return fraction(decimalValue() - frac);
}
fraction fraction::operator*(const int frac) const {
return fraction(decimalValue() * frac);
}
fraction fraction::operator/(const int frac) const {
return fraction(decimalValue() / frac);
}
bool fraction::operator==(const int frac) const {
return decimalValue() == frac;
}
bool fraction::operator!=(const int frac) const {
return decimalValue() != frac;
}
bool fraction::operator<(const int frac) const {
return decimalValue() < frac;
}
bool fraction::operator>(const int frac) const {
return decimalValue() > frac;
}
bool fraction::operator<=(const int frac) const {
return decimalValue() <= frac;
}
bool fraction::operator>=(const int frac) const {
return decimalValue() >= frac;
}
fraction fraction::operator+(const float frac) const {
return fraction(decimalValue() + frac);
}
fraction fraction::operator-(const float frac) const {
return fraction(decimalValue() - frac);
}
fraction fraction::operator*(const float frac) const {
return fraction(decimalValue() * frac);
}
fraction fraction::operator/(const float frac) const {
return fraction(decimalValue() / frac);
}
bool fraction::operator==(const float frac) const {
return decimalValue() == frac;
}
bool fraction::operator!=(const float frac) const {
return decimalValue() != frac;
}
bool fraction::operator<(const float frac) const {
return decimalValue() < frac;
}
bool fraction::operator>(const float frac) const {
return decimalValue() > frac;
}
bool fraction::operator<=(const float frac) const {
return decimalValue() <= frac;
}
bool fraction::operator>=(const float frac) const {
return decimalValue() >= frac;
}
fraction fraction::operator+(const double frac) const {
return fraction(decimalValue() + frac);
}
fraction fraction::operator-(const double frac) const {
return fraction(decimalValue() - frac);
}
fraction fraction::operator*(const double frac) const {
return fraction(decimalValue() * frac);
}
fraction fraction::operator/(const double frac) const {
return fraction(decimalValue() / frac);
}
bool fraction::operator==(const double frac) const {
return decimalValue() == frac;
}
bool fraction::operator!=(const double frac) const {
return decimalValue() != frac;
}
bool fraction::operator<(const double frac) const {
return decimalValue() < frac;
}
bool fraction::operator>(const double frac) const {
return decimalValue() > frac;
}
bool fraction::operator<=(const double frac) const {
return decimalValue() <= frac;
}
bool fraction::operator>=(const double frac) const {
return decimalValue() >= frac;
}
fraction::mix() {
int integer = 0;
int n = num;
while (num > denom) {
num = num - denom;
integer = integer + 1;
}
return to_string(integer) + " " + to_string(num) + "/" + to_string(denom);
}
istream& operator>>(istream& in, fraction& frac) {
in >> frac.num;
char i;
in >> i;
in >> frac.denom;
return i;
}
ostream& operator<<(ostream& out, fraction& frac) {
switch (frac.format) {
case improper:
out << to_string(frac.getNumerator()) + "/" + to_string(frac.getDenominator()); break;
case decimal:
out << frac.decimalValue(); break;
case mixed:
out << frac.mix(); break;
}
}
Here are the specific errors:
main.cpp: In function ‘int main()’:
main.cpp:27:35: error: no matching function for call to ‘fraction::outputFormat(fracForm)’
fraction::outputFormat(improper); // set output format to improper fraction
^
In file included from main.cpp:4:0:
fraction.h:27:21: note: candidate: static void fraction::outputFormat(fraction::fracForm)
static void outputFormat(fracForm);
^~~~~~~~~~~~
fraction.h:27:21: note: no known conversion for argument 1 from ‘fracForm’ to ‘fraction::fracForm’
main.cpp:32:34: error: no matching function for call to ‘fraction::outputFormat(fracForm)’
fraction::outputFormat(decimal); // set output format to decimal value
^
In file included from main.cpp:4:0:
fraction.h:27:21: note: candidate: static void fraction::outputFormat(fraction::fracForm)
static void outputFormat(fracForm);
^~~~~~~~~~~~
fraction.h:27:21: note: no known conversion for argument 1 from ‘fracForm’ to ‘fraction::fracForm’
main.cpp:37:32: error: no matching function for call to ‘fraction::outputFormat(fracForm)’
fraction::outputFormat(mixed); // set output format back to default mixed
^
In file included from main.cpp:4:0:
fraction.h:27:21: note: candidate: static void fraction::outputFormat(fraction::fracForm)
static void outputFormat(fracForm);
^~~~~~~~~~~~
fraction.h:27:21: note: no known conversion for argument 1 from ‘fracForm’ to ‘fraction::fracForm’
main.cpp:44:35: error: no matching function for call to ‘fraction::outputFormat(fracForm)’
fraction::outputFormat(improper);
^
In file included from main.cpp:4:0:
fraction.h:27:21: note: candidate: static void fraction::outputFormat(fraction::fracForm)
static void outputFormat(fracForm);
^~~~~~~~~~~~
fraction.h:27:21: note: no known conversion for argument 1 from ‘fracForm’ to ‘fraction::fracForm’
fraction.cpp:235:15: error: ISO C++ forbids declaration of ‘mix’ with no type [-fpermissive]
fraction::mix() {
^
fraction.cpp:235:1: error: prototype for ‘int fraction::mix()’ does not match any in class ‘fraction’
fraction::mix() {
^~~~~~~~
In file included from fraction.cpp:1:0:
fraction.h:69:16: error: candidate is: std::string fraction::mix()
string mix();
^~~
fraction.cpp: In function ‘std::istream& operator>>(std::istream&, fraction&)’:
fraction.cpp:250:12: error: invalid initialization of reference of type ‘std::istream& {aka std::basic_istream&}’ from expression of type ‘char’
return i;
Upvotes: 0
Views: 316
Reputation: 3001
You declare the enum fracForm
two times:
enum fracForm {improper, mixed, decimal};
class fraction {
enum fracForm {improper, mixed, decimal};
The functions in class fraction
are now using the enum fraction::fracForm
, and the code outside (so in main.cpp
) uses fracForm
These two enums
aren't the same, so the code won't compile.
To solve the problem, you can use either the "global
" approach, where fracForm is resolved from the fraction
class:
enum fracForm {improper, mixed, decimal};
class fraction {
//enum fracForm {improper, mixed, decimal};
With that solution, I would think most errors are gone.
The other solution would be, to put the fracForm error in the fraction class scope:
//enum fracForm {improper, mixed, decimal};
class fraction {
public:
enum fracForm {improper, mixed, decimal};
Now you have to use the enum outside the class like:
fracForm type = fraction::improper;
Upvotes: 2