-1

I am making a class called Time in C++ and the class has three integers as private member variables. I am pretty new at using classes in C++ and am trying to figure out how to solve this particular problem. The problem is that when I try to do this:

cout << "Almost midnight: " << Time(0,0,0) - Time(0,0,1) << endl;

I get a compiler error, and I think it is because the constructor that takes three parameters needs to be coded differently, because the private variables in the class take the value from the first constructor and then tries to subtract from the value from the second constructor so the first values get lost (I believe). So how does the constructor need to be in order to keep the old values, so I can do the subtraction without storing it in a named variable.

This is my code:

#include <iostream>
#include <cctype>
#include <cstdlib>
using namespace std;

class Time
{
    private:
        int hours;
        int minutes;
        int seconds;
        void normalize();

    public:
        Time() {hours = minutes = seconds = 0; normalize();};
        Time(int x, int y, int z);
        friend Time operator + (const Time& t1, const Time& t2);
        friend Time operator - (const Time& t1, const Time& t2);
        friend bool operator < (const Time& t1, const Time& t2);
        friend istream& operator >>(istream& ins, Time& t1);
        friend ostream& operator <<(ostream& out, Time& t1);
};

Time::Time(int x, int y, int z)
{
    hours = x;
    minutes = y;
    seconds = z;

    normalize();
}

void Time::normalize()
{
    int s = seconds;
    int m = minutes;
    int h = hours;

    while (s < 0)
    {
        s += 60;
        m--;
    }

    while (m < 0)
    {
        m += 60;
        h--;
    }

    while (h < 0)
    {
        h = h + 24;
    }

    seconds = s % 60;
    minutes = (m + s/60) % 60;
    hours = (h + m/60 + s/3600) % 24;
}

istream& operator >>(istream& ins, Time& t1)
{
    ins >> t1.hours;
    ins >> t1.minutes;
    ins >> t1.seconds;

    t1.normalize();

    return ins;
}
ostream& operator <<(ostream& out, Time& t1)
{
    if (t1.hours < 10)
        out << '0' << t1.hours << ":";
    else
        out << t1.hours << ":";
    if (t1.minutes < 10)
        out << '0' << t1.minutes << ":";
    else
        out << t1.minutes << ":";
    if (t1.seconds < 10)
        out << '0' << t1.seconds;
    else
        out << t1.seconds;

    return out;
}

int main()
{
    Time t1, t2, t3, t4;
    cin >> t1;
    cin >> t2;
    cin >> t3;

    cout << "Time1: " << t1 << endl;
    cout << "Time2: " << t2 << endl;
    cout << "Time3: " << t3 << endl;

    t4 = t1 + t2;
    cout << "Time4: " << t4 << endl;

    t1 = t3 - t4;
    cout << "Time1: " << t1 << endl;

    if (t1 < t3)
        cout << "Time1 < Time3" << endl;
    else
        cout << "Time3 >= Time1" << endl;

    Time t5 = t2 + Time(0,0,1);
    if (t5 < t2)
        cout << "Time5 < Time2" << endl;
    else
        cout << "Time5 >= Time2" << endl;

    cout << "Almost midnight: " << Time(0,0,0) - Time(0,0,1) << endl;

    return 0;
}

Time operator + (const Time& t1, const Time& t2)
{
    Time temp;
    temp.hours = t1.hours + t2.hours;
    temp.minutes = t1.minutes + t2.minutes;
    temp.seconds = t1.seconds + t2.seconds;

    return temp;
}

Time operator - (const Time& t1, const Time& t2)
{
    Time temp;

    temp.hours = t1.hours - t2.hours;
    temp.minutes = t1.minutes - t2.minutes;
    temp.seconds = t1.seconds - t2.seconds;

    temp.normalize();

    return temp;
}

bool operator < (const Time& t1, const Time& t2)
{
    if (t1.hours < t2.hours && t1.minutes < t2.minutes && t1.seconds < t2.seconds)
        return true;
    else
        return false;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
drleifz
  • 189
  • 3
  • 12
  • How about showing us the compiler error. – PaulMcKenzie Oct 25 '14 at 22:39
  • error: no match for 'operator<<' in 'std::operator<< >((* & std::cout), ((const char*)"Almost midnight: ")) << operator-((*(const Time*)(& Time(0, 0, 0))), (*(const Time*)(& Time(0, 0, 1))))'| – drleifz Oct 25 '14 at 22:39
  • 1
    The error should be obvious. How is operator << supposed to know what to do with a `Time` object? In addition, what is meant by subtracting two `Time` objects? All of these things have to be coded. – PaulMcKenzie Oct 25 '14 at 22:40
  • I guess this is homework or at least personal education. Else I would highly recommend using an already available library. Timekeeping is actually a pretty tricky thing to get right (irregularity of leap seconds and days, time zones, even `time - time = time` doesn't really make sense if you think about it). – fho Oct 25 '14 at 23:40

5 Answers5

1

The constructor is fine. What you're missing are suitable overloads for operator- and operator<<. Define them.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
0
ostream& operator <<(ostream& out, Time& t1)
{
    if(t1.hours < 10)
        out << "0" << t1.hours << ":";
    else
        out << t1.hours << ":";
    if(t1.minutes < 10)
        out << "0" << t1.minutes << ":";
    else
        out << t1.minutes << ":";
    if(t1.seconds < 10)
        out << "0" << t1.seconds;
    else
        out << t1.seconds;
}

Time operator - (const Time& t1, const Time& t2)
{
    Time temp;

    temp.hours = t1.hours - t2.hours;
    temp.minutes = t1.minutes - t2.minutes;
    temp.seconds = t1.seconds - t2.seconds;

    temp.normalize();

    return temp;
}

These are the - operator function and ostream& operator function

drleifz
  • 189
  • 3
  • 12
  • You're forgetting something important in `operator <<` -- you failed to return a value. – PaulMcKenzie Oct 25 '14 at 22:45
  • Hmmm.. what should I return? – drleifz Oct 25 '14 at 22:46
  • Return the stream object. – PaulMcKenzie Oct 25 '14 at 22:47
  • Doesn't seem to make any difference. The other aspects of my program works. The only case the program doesn't work is when I construct two objects and subtract them in the same line of code. – drleifz Oct 25 '14 at 22:48
  • It makes a heck of a lot of difference. If you don't return a value, the behavior of the program is undefined. So even though it didn't fix the observable issue, it sure did fix a lot of underlying issues. – PaulMcKenzie Oct 25 '14 at 22:50
  • I think it doesn't work because the operator - functions has to return a value and when I do something like cout << "Almost midnight: " << Time(0,0,0) - Time(0,0,1) << endl; The value gets lost and nothing comes out of the function. How can I fix that? – drleifz Oct 25 '14 at 22:59
  • What value gets lost? See here: http://ideone.com/SYSBkm This compiles without any issues. It also runs. – PaulMcKenzie Oct 25 '14 at 23:01
  • I tried the same code, but still get a compiler error :/ – drleifz Oct 25 '14 at 23:08
  • What compiler are you using? And when you say "tried the same code" -- what does that mean? Did you take the code at the site I posted, copied it verbatim, and compiled? Or did you try and change your (faulty) code and it doesn't compile? – PaulMcKenzie Oct 25 '14 at 23:08
  • @PaulMcKenzie I tried substituting my code with yours and got a compiler error. I am using CodeBlocks and the default compiler CodeBlocks use. When you say your faulty code, I feel like you are trying to insult me. I am only asking this question so I can learn how this works, so I would appreciate a little more tolerance. – drleifz Oct 26 '14 at 00:32
  • @drleifz - Since you didn't post your entire code, and the code I posted compiles with no issues, the conclusion would be that you're taking code that has other bugs and trying to fix it to look like the code I posted. That is the conclusion that anyone else would have, given that a compiler would be severely broken if it couldn't compile simple code (the code I posted) without error. Having said that, the compiler that CodeBlocks uses is gcc (should be version 4.x). The code compiles cleanly on Visual Studio 2010 and 2013, and also the online compiler I linked to. – PaulMcKenzie Oct 26 '14 at 00:48
  • @drleifz - Make sure you're using the correct version of gcc by going to your compiler's executable directory (where gcc.exe is located) going to the command prompt and run `gcc --version`. – PaulMcKenzie Oct 26 '14 at 00:58
  • @PaulMcKenzie I updated the post with the entire code posted. – drleifz Oct 26 '14 at 09:43
  • @drleifz - Well, the error is that you didn't do exactly what my code was doing in terms of `operator <<`. Note that the parameter is a const reference to `Time`, not just a reference. Change it to a const reference and the code will then compile. See here: http://ideone.com/SjyFqG – PaulMcKenzie Oct 26 '14 at 14:59
0

You have to overload the operator minus operator- and the operator << operator<<

Do it like this for operator-:

Time& Time::operator-(Time const& time){
     hours = time.getHours();
     minutes = time.getMinutes();
     seconds = time.getSeconds();
    return *this;
}
Mosa
  • 373
  • 1
  • 14
0

In this case the compiler doesn't know how to show your class in the cout, and it doesn't know how you want to subtract the 2 classes, you need to tell to the compiler how it should work, overloading the operators.

You need to define the operators << for your class to be showed properly in the ostream. and you need to overload the - operator to make your subtraction.

How to overload << for you own class: How to properly overload the << operator for an ostream?

A good documentation about operator overloading: http://en.cppreference.com/w/cpp/language/operators

Community
  • 1
  • 1
dfranca
  • 5,156
  • 2
  • 32
  • 60
0

You did not overload your operator << correctly, as you forgot to return a value.

The following program compiles and runs without error. I removed the normalize function, but still has no issues:

#include <ostream>
#include <iostream>

struct Time
{
    int hours;
    int minutes;
    int seconds;
    Time(int h=0, int m=0, int s=0) : hours(h), minutes(m), seconds(s) {}
};

std::ostream& operator <<(std::ostream& out, const Time& t1)
{
    if (t1.hours < 10)
        out << "0" << t1.hours << ":";
    else
        out << t1.hours << ":";
    if (t1.minutes < 10)
        out << "0" << t1.minutes << ":";
    else
        out << t1.minutes << ":";
    if (t1.seconds < 10)
        out << "0" << t1.seconds;
    else
        out << t1.seconds;
    return out;
}


Time operator - (const Time& t1, const Time& t2)
{
    Time temp;
    temp.hours = t1.hours - t2.hours;
    temp.minutes = t1.minutes - t2.minutes;
    temp.seconds = t1.seconds - t2.seconds;
    return temp;
}

using namespace std;

int main()
{
    cout << "Almost midnight: " << Time(0, 0, 0) - Time(0, 0, 1) << endl;
}

Output:

Almost midnight: 00:00:0-1

Now, if the output is incorrect, that is a different issue than the one you posted. Your original issue dealt with a compiler error, and the code above does not have such an error. However, it does contain the fix of not returning a value.

In addition to this, note that the parameter to operator << is a const reference, not a reference. This will allow expressions that returns temporaries to be used within operator <<.

To show how const makes a difference: If we take your original code (where Time& is used instead of const Time& in the implementation of operator <<), but instead store the value of the subtraction of the Time objects to a non-temporary object, you will see that the code will compile successfully:

   Time tSub = Time(0,0,0) - Time(0,0,1); 
   cout << "Almost midnight: " << tSub << endl;

while this will not compile successfully:

   cout << "Almost midnight: " << Time(0,0,0) - Time(0,0,1) << endl;

So the issue is that operator << in your original code only works with non-const objects. By making the parameter const Time&, you alleviate these errors.

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45