Проблемы логики перегрузки операторов - PullRequest
0 голосов
/ 16 апреля 2019

одно из наших заданий в классе - создать программу, которая использует объекты для отображения часов, минут и секунд. С этими числами нам теперь приходится перегружать различные операторы, которые увеличивают секунды / минуты на 1, и уменьшать их, используя ++ и -. У меня возникли некоторые проблемы с оператором -, так как он работает не так, как ожидалось, если я вставлю 0 минут, и он уменьшит минуты, когда он возвращает значения, как 128 минут. Поскольку я начинаю в этом, я был бы очень признателен за помощь.

И затем вторая часть использует другие операторы (> <> = <= ==! =), Чтобы сравнить 2 разных часа, минуты и секунды и вернуть значение bool, если один больше другого (т. Е. H: 1) м: 5 с: 0 против ч: 0 м: 5 с: 0 вернет «истина»). Я не дошел до второй части и был бы признателен за некоторые советы о том, как это начать, так как я пытаюсь логически обдумать всю эту идею. </p>

main.cpp

#include <iostream>
#include "Time.h"

using namespace std;

int main() {

    int hour1, minute1, second1, hour2, minute2, second2;

    cout << "Enter time A (hh, mm, ss): ";
    cin >> hour1;
    cin >> minute1;
    cin >> second1;
    cout <<endl;

    /*cout << "Enter time B(hh, mm, ss): ";
    cin >> hour2;
    cin >> minute2;
    cin >> second;
    cout <<endl;*/

   Time T1(hour1, minute1, second1);

   ++T1;                    //Increases seconds by 1
   T1.displayTime();

   T1++;                    //Increases minutes by 1
   T1.displayTime();

   --T1;                    //Decreases seconds by 1
   T1.displayTime();

   T1--;                    //Decreases minutes by 1
   T1.displayTime();


   return 0;
}

time.h

#ifndef TIME_H
#define TIME_H

class Time
{
    public:
        Time();
        Time (int h, int m, int s);

        void displayTime();

        Time operator++();
        Time operator++(int);

        Time operator--();
        Time operator--(int);
        /*Time operator>();
        Time operator<();
        Time operator>=();
        Time operator<=();
        Time operator==();
        Time operator!=();*/

    private:
        int hours;
        int minutes;
        int seconds;
};

#endif // TIME_H

Time.cpp

#include <iostream>
#include "Time.h"

using namespace std;

Time::Time(){
    hours = 0;
    minutes = 0;
    seconds = 0;
}

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

void Time::displayTime(){
    cout << "Hours: " << hours <<" Minutes: " << minutes << " Seconds: " <<seconds <<endl;
}

Time Time::operator++(){ //Prefix plus seconds
    ++seconds;
    if (minutes >= 60){
        ++hours;
        minutes -= 60;
    }
    if (seconds >= 60){
        ++minutes;
        seconds -= 60;
    }
    return Time(hours, minutes, seconds);
}

Time Time::operator++(int){ //Postfix plus minutes
    Time T(hours, minutes, seconds);

    ++minutes;
    if(minutes >=60){
        ++hours;
        minutes -= 60;
    }
    if (seconds >= 60){
        ++minutes;
        seconds -= 60;
    }
    return T;
}

Time Time::operator--(){ //PREFIX MINUSS seconds
    --seconds;

    if (seconds == 0){
        --minutes;
        seconds += 59;
    }

    if (minutes == 0){
        --hours;
        minutes += 59;
    }

    return Time(hours, minutes, seconds);
}

Time Time::operator--(int){ //POSTFIX MINUSS minutes
    Time T(hours, minutes, seconds);
    --minutes;

    if (minutes == 0){
        --hours;
        minutes += 59;
    }
    if (seconds == 0){
        --minutes;
        seconds += 59;
    }
    return T;
}


/*Time Time::operator>(){

}

Time Time::operator<(){

}

Time Time::operator>=(){

}

Time Time::operator<=(){

}

Time Time::operator==(){

}

Time Time::operator!=(){

}
*/

Если вы заметите какие-либо другие ошибки, пожалуйста, дайте мне знать.

Так что с этим минуты не вычитаются правильно. Кажется, что он просто убирает из 0, но не добавляет к нему необходимые секунды (если это имеет смысл).

Спасибо.

1 Ответ

2 голосов
/ 16 апреля 2019

У меня проблемы с оператором -

На самом деле, у вас есть еще немного проблем! Уже operator++ не будет работать, как ожидалось. Попробуйте:

Time t(0, 59, 59);
++t;

Как только вы увеличиваете секунды с переполнением, следующее, которое может переполниться, - это минуты, поэтому вам нужно сначала проверить их!

++seconds;
if(seconds == 60)
{
    seconds = 0;
    ++minutes;
    // only, if minutes were incremented, they can overflow, so check only here needed
   if(minutes == 60)
   {
       minutes = 0;
       // open: how do you want to handle hours overflowing?
       // variant 1: just go on, counting 23, 24, 25, ...
       ++hours;
       // variant 2: restart at 0:
       hours = (hours + 1) % 24;
       // variant 3 (my favourite): rember in a flag that we overflowed
       // (and have a getter for so that user can check):
       isWrapAround = hours == 23; // new member variable of type bool
       hours = (hours + 1) % 24;
   }
}

Аналогично, вы бы обработали operator--, просто заменив каждый случай ++ на -- и настроив обнаружение переполнения на обнаружение переполнения. Осторожнее с последним: ваш исходный код не смог правильно определить недостаточное количество:

--seconds;
if(seconds == 0)

Это уже уменьшит минуты, когда у нас фактически останется 1 секунда, но 00:00:00 - правильное время! Поэтому вам нужно либо проверить 0 перед уменьшением (if(seconds-- == 0), либо проверить отрицательные значения впоследствии (--seconds; if(seconds == -1) или if (seconds < 0)). С этим исправлением += 59 больше не будет корректным либо вам понадобится либо += 60, либо, предпочтительно, = 59.

Обычно , операторы предварительного увеличения и -decrement возвращают ссылку на текущий объект. Это позволило бы е. г. ++(++time):

Time& Time::operator++()
{
    // increment as described
    return *this;
}

Операторы пост-инкремента и -декремента очень странные ... Пожалуйста, подтвердите, если это действительно задача - увеличивать / уменьшать минуты (если так, я могу только трясти головой учитель ...). Это будет большим сюрпризом для всех, так как операторы ведут себя совершенно иначе, чем обычно! Последний будет:

Time operator++(int)
{
    Time tmp(*this);
    ++*this;
    return tmp;
}

Если вы действительно, действительно увеличите минуты (обратите внимание на иронию: операторы после X-кремации на самом деле ведут себя как до-X-кремация, по крайней мере, так выглядит ваш первоначальный подход): просто оставьте секунды нетронутым. Все, что вам тогда нужно в постоператорах, это body самого внешнего, если в соответствующих предварительных вариантах. Затем они могут быть переписаны (чтобы избежать дублирования кода) как:

++seconds;
if(seconds == 60)
{
    seconds = 0;
    *this++; // use post-fix to adjust minutes...
}

Наконец: сравнение: К сожалению, у нас еще нет C ++ 20, в противном случае мы просто могли бы реализовать оператор космического корабля (<=>) ... Неважно, мы все равно можем вместо этого использовать обычную функцию и используйте это в операторах:

int Time::compare(Time const& other) const
{
    // most relevant are hours, if these differ, values of minutes or
    // seconds don't matter any more...
    int result = hours - other.hours;
    if(result == 0)
    {
        // so hours are the same...
        // minutes then are relevant next
        result = minutes - other.minutes;
        if(result == 0)
            result = seconds - other.seconds;
    }
    return result;
}

Тогда все операторов, которые будут реализованы, будут выглядеть так:

bool Time::operator@(Time const& other) const
{
    return compare(other) @ 0;
}

, где @ обозначает всех ваших необходимых операторов (==, !=, <, <=, >, >=).


Бонус: запоминание переполнения без отдельного флага:

Вам больше не понадобится другая переменная, но она требует более сложной логики.

Сначала, если оставить значение -1 (operator--), это будет означать, что произошел переход. Соответственно, геттер для циклического преобразования будет return hours == -1;.

В любом другом месте, где мы ранее использовали hours напрямую, мы теперь использовали бы метод получения, который будет выглядеть следующим образом:

int Time::getHours() const
{
    return hours + (hours == -1);
}

Вычислить значение для приращения немного сложнее:

hours = (getHours() + 1) % 24 - (hours == 23);
...