1

I am working on an assignment for CS2 in C++. I have completed my code and it runs as expected in Visual Studio. However to submit the code we have to copy it over to our unix server and make sure it still runs.

I can't get it to run so I am thinking there must be a mistake I am missing that VS is correcting?

I showed my code to my professor and he agreed that it looks like everything is correct.

Can anyone help?

rational.h

#ifndef  RATIONAL_H
#define RATIONAL_H
#include <iostream>
#include <ostream>
#include <cmath>
#include <cstdlib>
using namespace std;


class rational
{

    friend ostream& operator<<(ostream &, rational&);
    friend istream& operator>>(istream &, rational&);
public:

    rational operator+(const rational &)const;
    rational operator-(const rational &)const;

    bool rational::operator>(const rational &r2);

    rational(int n = 0, int d = 1);

    rational add(const rational &r2) const;

    void add(const rational &r1, const rational &r2);

    rational subtract(const rational &r2) const;

    void subtract(const rational &r1, const rational &r2);


    rational multiply(const rational &r2) const;


    rational divide(const rational &r2) const;

    int compare(const rational &r2) const;

private:
    int num;    // numerator
    int denom;  // denominator
};
#endif

rational.cpp

#include "rational.h"
using namespace std;

ostream& operator<<(ostream &out, rational &robj)
{
    out << robj.num << "/" << robj.denom;
    return out;
}
istream& operator>>(istream &in, rational &obj)
{
    cout << "Enter values for the numerator and denominator of a rational number: ";
    in >> obj.num >> obj.denom;

    return in;
}

rational::rational(int n, int d)
{
    num = n;
    denom = d;
}

rational rational::operator+(const rational &r2) const
{
    rational sum;
    sum.denom = (*this).denom * r2.denom;
    sum.num = ((*this).num * r2.denom) + (r2.num * (*this).denom);
    return sum;

}

rational rational::operator-(const rational &r2) const
{
    rational diff;
    diff.denom = (*this).denom * r2.denom;
    diff.num = ((*this).num * r2.denom) - (r2.num * (*this).denom);
    return diff;
}

bool rational::operator>(const rational &r2)
{
    double x1, x2;

    x1 = double((*this).num) / double((*this).denom);
    x2 = double(r2.num) / double(r2.denom);

    return (x1 > x2);
}

rational rational::add(const rational &r2) const
{
    rational sum;
    sum.denom = (*this).denom * r2.denom;
    sum.num = ((*this).num * r2.denom) + (r2.num * (*this).denom);
    return sum;
}

void rational::add(const rational &r1, const rational &r2)
{
    (*this).denom = r1.denom * r2.denom;
    (*this).num = (r1.num * r2.denom) + (r2.num * r1.denom);

}
rational rational::subtract(const rational &r2) const
{
    rational diff;
    diff.denom = (*this).denom * r2.denom;
    diff.num = ((*this).num * r2.denom) - (r2.num * (*this).denom);
    return diff;
}
void rational::subtract(const rational &r1, const rational &r2)
{
    (*this).denom = r1.denom * r2.denom;
    (*this).num = (r1.num * r2.denom) - (r2.num * r1.denom);

}
rational rational::multiply(const rational &r2) const
{
    rational multi;
    multi.denom = (*this).denom * r2.denom;
    multi.num = (*this).num * r2.num;
    return multi;

}
rational rational::divide(const rational &r2) const
{
    rational div;
    div.denom = (*this).denom * r2.num;
    div.num = (*this).num * r2.denom;
    return div;

}
int rational::compare(const rational &r2) const
{
    if ((*this).denom == r2.denom && (*this).num == r2.num)
        return 0;
    else if (double((*this).num) / double((*this).denom) > double(r2.num) / double(r2.denom))
        return 1;
    else
        return -1;
}

main.cpp

#include "rational.h"

using namespace std;

int main()
{
    rational r1(1,4), r2(1,3),r3;

    cout << "r1 is initialized by the 2nd constructor: r1 = " << r1 << endl;
    cout << "r2 is initialized by the 2nd constructor: r2 = " << r2 << endl << endl;

    cout << "Testing the comapre() member function, found:" << endl << "\t";
    int compare = r1.compare(r2);

    switch (compare){
        case 0:
            cout << r1 << " is equal to " << r2;
            break;
        case 1:
            cout << r1 << " is greater than " << r2;
            break;
        case -1:
            cout << r1 << " is less than " << r2;
            break;
    }
    cout << endl << endl;

    cout << "Testing the four arithmetic member functions:" << endl;
    r3.add(r1, r2);
    cout << "\tr1 + r2 = " << r1 << " + " << r2 << " = " << r3 << endl;
    r3.subtract(r1, r2);
    cout << "\tr1 - r2 = " << r1 << " - " << r2 << " = " << r3 << endl;
    cout << "\tr1 * r2 = " << r1 << " * " << r2 << " = " << r1.multiply(r2) << endl;
    cout << "\tr1 / r2 = " << r1 << " / " << r2 << " = " << r1.divide(r2) << endl;

}

Compiling command g++ -c main.cpp rational.cpp

I get the error

  no match for 'operator<<' in 'std::operator<< [with _Traits = std::char_traits<char>] 

And another whole page worth of errors.

osgx
  • 90,338
  • 53
  • 357
  • 513
Renji1540
  • 13
  • 2
  • Hello Renji1540. Can you tell what did you try to compile and run the code at Unix? Was it compiled successfully? Can you run compiled program? What is the error (are there any error messages; or output of program is not as expected - what was it)? – osgx Apr 18 '18 at 03:16
  • g++ -c main.cpp rational.cpp I get the error no match for 'operator<<' in 'std::operator<< [with _Traits = std::char_traits] A long with another whole page worth of errors. – Renji1540 Apr 18 '18 at 03:22
  • Not only the command you did, but also all error messages it printed. Try to add error messages to the your question by editing it. – osgx Apr 18 '18 at 03:22
  • There are many errors in the cpp code when compiled with g++ or clang++ (llvm). First: there is extra `rational::` prefix of two operator definitions (they are already inside class declaration, prefix is not needed). Second: There are some errors in printing lines with `r1.multiply(r2)` and `r1.divide(r2)`. - Your output functions expects lvalue, and try to use rvalue in these lines (https://stackoverflow.com/a/23209236 may help). Did you use C++11 settings in the visual studio (not the managed c++)? – osgx Apr 18 '18 at 03:33
  • How do I check the c++11 settings? – Renji1540 Apr 18 '18 at 03:35

1 Answers1

1

With gcc and clang/llvm compilers on Unix (Linux) I have error messages about rational:: prefix of two operator definitions (and with modern g++ and clang++ there is color coding with red for errors):

$ gcc *.cpp -o a -w
In file included from main.cpp:1:0:
rational.h:20:10: error: extra qualification ‘rational::’ on member ‘operator>’ [-fpermissive]
     bool rational::operator>(const rational &r2);
          ^~~~~~~~

These prefixes are not needed for operators declared inside the class declaration, just use bool operator>(const rational &r2); when inside the class.

Other error generates a lot of text for two lines with r1.multiply(r2) and r1.divide(r2), and real cause is not too easy to find. There it is:

$ g++ main.cpp rational.cpp -w -o program
main.cpp: In function ‘int main()’:
main.cpp:33:58: error: no match for ‘operator<<’ (operand types are ‘std::basic_ostream<char>’ and ‘rational’)
     cout << "\tr1 * r2 = " << r1 << " * " << r2 << " = " << r1.multiply(r2) << endl;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
....skip... no known conversion for ...
In file included from main.cpp:1:0:
rational.h:13:21: note: candidate: std::ostream& operator<<(std::ostream&, rational&) <near match>
     friend ostream& operator<<(ostream &, rational&);
                     ^~~~~~~~
rational.h:13:21: note:   conversion of argument 2 would be ill-formed:
main.cpp:33:72: error: invalid initialization of non-const reference of type ‘rational&’ from an rvalue of type ‘rational’
     cout << "\tr1 * r2 = " << r1 << " * " << r2 << " = " << r1.multiply(r2) << endl;
                                                             ~~~~~~~~~~~^~~~
main.cpp:34:58: error: no match for ‘operator<<’ (operand types are ‘std::basic_ostream<char>’ and ‘rational’)
     cout << "\tr1 / r2 = " << r1 << " / " << r2 << " = " << r1.divide(r2) << endl;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~

So, compiler can't use your variant of output function... Searching for "candidate function not viable: expects an l-value" for 2nd argument ostream I found https://stackoverflow.com/a/23209236

You need:

ostream& operator<< (ostream& out, Polynomial const& poly) {

This is because a temporary object cannot be bound to a non-const reference.

So, create variant of ostream& operator<<(ostream &out, rational &robj) method to accept const reference, like ostream& operator<<(ostream &out, rational const &robj), as you try to output temporary rational object in lines with multipy and divide.

My Patch:

diff -ur orig/rational.cpp new/rational.cpp
--- orig/rational.cpp   2018-04-18 06:30:14.734426770 +0300
+++ new/rational.cpp    2018-04-18 06:46:49.839818729 +0300
@@ -1,10 +1,15 @@
 #include "rational.h"
 using namespace std;
-
 ostream& operator<<(ostream &out, rational &robj)
 {
     out << robj.num << "/" << robj.denom;
     return out;
+}
+
+ostream& operator<<(ostream &out, rational const &robj)
+{
+    out << robj.num << "/" << robj.denom;
+    return out;
 }
 istream& operator>>(istream &in, rational &obj)
 {
diff -ur orig/rational.h new/rational.h
--- orig/rational.h     2018-04-18 06:20:14.431675001 +0300
+++ new/rational.h      2018-04-18 06:47:00.691799442 +0300
@@ -11,13 +11,14 @@
 {

     friend ostream& operator<<(ostream &, rational&);
+    friend ostream& operator<<(ostream &, rational const&);
     friend istream& operator>>(istream &, rational&);
 public:

     rational operator+(const rational &)const;
     rational operator-(const rational &)const;

-    bool rational::operator>(const rational &r2);
+    bool operator>(const rational &r2);

     rational(int n = 0, int d = 1);

Output:

$ g++ main.cpp rational.cpp -o program
$ ./program
r1 is initialized by the 2nd constructor: r1 = 1/4
r2 is initialized by the 2nd constructor: r2 = 1/3

Testing the comapre() member function, found:
        1/4 is less than 1/3

Testing the four arithmetic member functions:
        r1 + r2 = 1/4 + 1/3 = 7/12
        r1 - r2 = 1/4 - 1/3 = -1/12
        r1 * r2 = 1/4 * 1/3 = 1/12
        r1 / r2 = 1/4 / 1/3 = 3/4
$ clang++ main.cpp rational.cpp -o program
$ ./program
r1 is initialized by the 2nd constructor: r1 = 1/4
r2 is initialized by the 2nd constructor: r2 = 1/3

Testing the comapre() member function, found:
        1/4 is less than 1/3

Testing the four arithmetic member functions:
        r1 + r2 = 1/4 + 1/3 = 7/12
        r1 - r2 = 1/4 - 1/3 = -1/12
        r1 * r2 = 1/4 * 1/3 = 1/12
        r1 / r2 = 1/4 / 1/3 = 3/4
osgx
  • 90,338
  • 53
  • 357
  • 513
  • Thank you osgx! After correcting the one class issue and adding in the const you recommended, it is now running on the server. It is amazing such an small oversight caused so many errors. – Renji1540 Apr 18 '18 at 03:56
  • Class issue may be fixed by `-fpermissive` option printed in the error message... Reading of gcc (g++, or better clang++) pages filled with compile errors should be started from the beginning, with recent version of compiler (messages are much better) and with colors enabled. – osgx Apr 18 '18 at 03:58