Operator overloading logic issues - c++

one of our assignments in the class is to create a program that uses objects to display hours, minutes and seconds. With these numbers we now have to overload various operators that will increase the seconds/minutes by 1, and decrease them using ++ and --. Im having some trouble with the -- operator as its not working as expected, if I put in 0 minutes, and it decreases the minutes it returns values like 128 minutes. As Im starting out in this I would really appreciate some help.
And then the second part is using other operators (> < >= <= == !=) to compare 2 different hours, minutes and seconds and return a bool value if one is more than the other (i.e. h:1 m:5 s:0 vs h:0 m:5 s:0 will return 'true'). I havent gotten to the second part and would appreciate some pointers on how to get this started as Im trying to wrap my head around this whole idea logically.
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!=(){
}
*/
If you spot any other mistakes, please do let me know.
So with this the minutes are not subtracting correctly. It seems that it is just taking away from 0, but not adding the necessary seconds back to it (if that makes sense).
Thank you.

Im having some trouble with the -- operator
Actually, you have quite some more trouble! Already operator++ won't work as expected. Try:
Time t(0, 59, 59);
++t;
Once you incremented seconds with overflow, next that can overflow is the minutes, so you need to check these first!
++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;
}
}
Analogously, you'd handle the operator--, just replacing every occurence of ++ with -- and adjusting the overflow detection to underflow detection. Careful with the latter: Your original code did not do proper underflow detection:
--seconds;
if(seconds == 0)
This would already decrement minutes when we actually have 1 second left, but 00:00:00 is a valid time! So you need to either check for 0 before decrementing (if(seconds-- == 0) or check for negative values afterwards (--seconds; if(seconds == -1) or if (seconds < 0)). With this fix, += 59 won't be correct any more either, you'd need either += 60 or preferrably simply = 59.
Usually, the pre-increment and -decrement operators return a reference to current object. This would allow for e. g. ++(++time):
Time& Time::operator++()
{
// increment as described
return *this;
}
The post-increment and -decrement operators are very strange... Please re-validate if it really is the task to in-/decrement minutes (if so, I can only shake heads over your teacher...). It will be a great surprise for anyone as the operators behave totally differently from what is the usual behaviour! The latter one would be:
Time operator++(int)
{
Time tmp(*this);
++*this;
return tmp;
}
If you really, really shall increment minutes (note the irony: post-X-crement operators actually behave like pre-X-crement, at least as your initial approach looks like): Just leave seconds untouched. All you then need in the post-operators is the body of the outermost if in the respective pre-variants. These then could be re-written (to avoid code duplication) as:
++seconds;
if(seconds == 60)
{
seconds = 0;
*this++; // use post-fix to adjust minutes...
}
Finally: comparison: Unfortunately, we don't yet have C++20 available, otherwise we simply could have implemented the spaceship operator (<=>)... Never mind, we still can use an ordinary function instead and use this one in the operators:
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;
}
Then all the operators to be implemented would look like:
bool Time::operator#(Time const& other) const
{
return compare(other) # 0;
}
where # stands for all of your operators needed (==, !=, <, <=, >, >=).
Bonus: remembering overflow without separate flag:
You won't need another variable any more, but it requires more complex logic.
At first, leaving the -1 (operator--) will indicate that a wrap-around occured. Correspondingly, the getter for wrap-around would return hours == -1;.
At any other place where we previously used hours directly, we'd now use the getter for, which would look like this:
int Time::getHours() const
{
return hours + (hours == -1);
}
Calculating the value for increment is slightly more complex:
hours = (getHours() + 1) % 24 - (hours == 23);

Related

The Chinese clock problem c++ (giving me time limit error)

I have been trying to solve this problem for an online judge system, which requires a time limit of 1000ms. I have tried a few variations of solutions, but I will post my best draft here. I was able to get my answers right, however, I am exceeding the time limit. The best solution I can come up with is O(n^2).
The Task problem
Once the programmer X was in China and noticed that Russian clocks “Zarya” are 10 times cheaper there than in Russia. X chose to do some shenanigans and bought a huge amount of clocks to bring it to his own country and sell them at half price (which actually means 5x times more expensive than he bought). But as soon as he came back home, he realized that many clocks go discordantly, moreover, they stop from a simple push (or start going if they were stopped before).
Obviously, the clocks were fake, just very accurate copies. To sell them really quickly, X wants to set them all to the same time (so it won’t matter if the time’s correct or not – he can say this is “the time of the manufacturer”) and just shake his bag to make them tick.
To set the time, he has to spin a winding crown that will make clock’s hands move: the hour hand moves 60 times slower than the minute hand and the minute hand is 60 times slower than the second hand. One full spin of a crown makes a full spin of the second hand; and although the spin takes just a second, it will take 6 minutes to change the time to 6 hours. It is allowed to spin a crown only clockwise to save fragile mechanism of a clock.
Help the programmer X minimize the effort put in preparing the clocks to be sold, choosing the optimal time to set all clocks to.
Input:
The first line contains a natural n (1 ≤ n ≤ 50000) – the quantity of clocks.
The next n lines contain the time of each clock in a format “h:mm:ss”, where h (1 ≤ h  ≤ 12) means hours, mm and ss (00 ≤ mm,ss ≤ 59) – minutes and seconds.
Output:
The time all clocks need to be set to in the format presented above.
Example Input
3
11:30:00
12:10:01
6:10:18
Output
12:10:01
#include<iostream>
using namespace std;
struct Clock {
int hours;
int mins;
int secs;
Clock() {
hours = mins = secs = 0;
}
};
void strtotime(string str, Clock& clock) { //converts string input to time
if (str[1] == ':') {
clock.hours = (str[0] - 48);
clock.mins = (str[2] - 48) * 10 + (str[3] - 48);
clock.secs = (str[5] - 48) * 10 + (str[6] - 48);
}
else {
clock.hours = (str[0] - 48) * 10 + (str[1] - 48);
clock.mins = (str[3] - 48) * 10 + (str[4] - 48);
clock.secs = (str[6] - 48) * 10 + (str[7] - 48);
}
}
double calctime(Clock from, Clock to) {//calculates time taken to change one clock time to other's
//calculate time for hours
double minutes;
if (from.hours > to.hours) {
minutes = 12 - (from.hours - to.hours);
}
else {
minutes = to.hours - from.hours;
}
//calculate time for mins
double seconds;
if (from.mins > to.mins) {
seconds = 60 - (from.mins - to.mins);
}
else {
seconds = to.mins - from.mins;
}
//calculate time for secs
double seconds2;
if (from.secs > to.secs) {
seconds2 = 60 - (from.secs - to.secs);
}
else {
seconds2 = to.secs - from.secs;
}
double totalTime = minutes * 60 + seconds + (seconds2 / 60);
return totalTime;
}
int main() {
int n;
string str;
cin >> n;
Clock* clock = new Clock[n];
for (int x = 0; x < n; x++) {
cin >> str;
strtotime(str, clock[x]);
}
double totaltime;
double mintime;
int loc = 0;
bool first = true;
double* timearr = new double[n];
for (int x = 0; x < n; x++) {
totaltime = 0.0;
for (int y = 0; y < n; y++) {
if (x != y) {
totaltime += calctime(clock[y], clock[x]);
}
}
if (first) {
mintime = totaltime;
first = false;
}
else {
if (totaltime < mintime) {
mintime = totaltime;
loc = x;
}
}
}
cout << clock[loc].hours;
cout << ':';
if (clock[loc].mins < 10) {
cout << 0 << clock[loc].mins;
}
else {
cout << clock[loc].mins;
}
cout << ':';
if (clock[loc].secs < 10) {
cout << 0 << clock[loc].secs;
}
else {
cout << clock[loc].secs;
}
}
Sort the times
Calculate the difference between each two neighbors and the first and last element
Find the maximum difference and remove it (the solution is the left neighbor of this difference)

Calculate how many days are required for a snail to climb up a wall

I am trying to solve this problem:
Write a program to calculate how many days are required for a snail to climb up a wall. A snail climbs on a wall, it starts at the bottom and climbs up n meters a day. Regretfully, every night it slides m meters down. Given the height of the wall H, write a program to calculate how many days required for the snail to reach the top of the wall.
If the snail will never be able to reach the top of the wall print: Fail.
This is my attempt to solve this problem:
int numDays(int wall_height, int meters_per_day, int meters_down_per_day) {
int current_height = 0;
int days = 0;
while (current_height != wall_height) {
if (current_height + (meters_per_day - meters_down_per_day) >= wall_height) {
break;
}else {
days += 1;
current_height += meters_per_day - meters_down_per_day;
}
}
return days;
}
int main()
{
int wall_height = 30;
int meters_per_day = 3;
int meters_down = 2;
if (meters_down >= meters_per_day) {
cout << "Fail" << endl;
}else {
cout << numDays(wall_height, meters_per_day, meters_down) << endl;
}
return 0;
}
My solution returns 29 days, but the answer is 28 days because once the snail has climbed 27 meters after 27 days, it will simply climb the remaining 3 meters to the top on the 28th day.
What I am doing wrong to generate the wrong output? Thanks!
Your error is that you are only checking if the snail has reached the top of the wall after it has climbed up and down. You even say this yourself. Instead you should check the height after the climb up only
Here's loop that does that.
for (;;) {
current_height += meters_per_day;
if (current_height >= wall_height) {
break;
current_height -= meters_down_per_day;
days += 1;
}
For me, here is the right implementation of your numDays function :
int numDays(int wall_height, int meters_per_day, int meters_down_per_day) {
int current_height = 0;
int days = 1;
while (current_height != wall_height) {
current_height += meters_per_day;
if(current_height >= wall_height)
break;
days += 1;
current_height -= meters_down_per_day;
}
return days;
}
the answer is 28 days because once the snail has climbed 27 meters after 27 days, it will simply climb the remaining 3 meters to the top on the 28th day
To do this, you need to increment first the current_height before testing if the snail is on the top of the wall.
I think the day counter must start at 1 because the first day of iteration is the day 1 (I don't know if the explanation is really clear).
Here's my simple Python program to solve the problem that implements the given conditions:
def num_days(h, n, m):
days = 0
position = 0
while n < h:
if m >= n:
break
days += 1
position += n
if position >= h:
return days
position -= m
if days == 0:
days = 'Fail'
return days
You can call the function num_days with h, n, and m as arguments to get the number of days required for the snail to reach the top of the wall.
For example:
num_days(11, 3, 2)
return
9
num_days(5, 3, 1)
return
2
num_days(5, 0, 1)
return
Fail

How many days between two dates C++

I have a program that uses two functions I have defined inside a class. My class works fine, but my program always returns an amount that is some amount of days off. There is more error when the dates are farther apart. My code is designed to in one function calculate the total amount of days since 1582, and another function subtracts the higher amount from the lesser. Where am I getting the error from? I know it may not be the most efficient way to do things (cpu wise) but can someone find where my logic is messed up? This accounts for leap years as well. I have been checking my program against a website http://www.timeanddate.com/date/durationresult.html
int Date::totalDays()
{
int totalDays = 0;
int daysInMonth[]={0,31,28,31,30,31,30,31,31,31,31,30,31};
totalDays += day;
for (int i = month-1; i > 0; i--)
{
totalDays += daysInMonth[i];
}
for (int i = year-1; i > 1582; i--)
{
if(year % 100 == 0)
{
if(year % 400 == 0)
totalDays += 366;
else
totalDays += 365;
}
else
{
if(year % 4 == 0)
totalDays += 366;
else
totalDays += 365;
}
}
return totalDays;
}
int Date::daysBetween(Date other)
{
if (this->totalDays() > other.totalDays())
return this->totalDays() - other.totalDays();
else
return other.totalDays() - this->totalDays();
}
Thank you.
Problem 1:
int daysInMonth[]={0,31,28,31,30,31,30,31,31,31,31,30,31};
should be
int daysInMonth[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
// ^^
Problem 2:
if the current year is a leap-year, and month is greater than 2, you'll also need to add one day to account for February 29th of the current year.

windows timestamp (C++)

I creating windows timestamp() function and I got wrong numbers checking by PHP microtime() function:
C++ = 1409802313
PHP = 1410655505
In this fallowing C++ writed code:
#include <windows.h>
#include <iostream> // <--- Console I/O
#include <cstdlib> // <--- Command Line
#include <sstream>
using namespace std;
void print(string value){cout << value;}
string parseStr(int value)
{
ostringstream stream;
stream<<value<<flush;
return stream.str();
}
// ============================================================
// TIMESTAMP
// ============================================================
string timestamp()
{
SYSTEMTIME system_time;
GetLocalTime(&system_time);
int year = system_time.wYear;
int month = system_time.wMonth;
int day = system_time.wDay;
int hour = system_time.wHour;
int minute = system_time.wMinute;
int second = system_time.wSecond;
int milliseconds = system_time.wMilliseconds;
int day_of_year = 0;
if (month > 1){day_of_year += 31;} // Sausis
if (month > 2){day_of_year += 28;} // Vasaris
if (month > 3){day_of_year += 31;} // Kovas
if (month > 4){day_of_year += 30;} // Balandis
if (month > 5){day_of_year += 31;} // Geguze
if (month > 6){day_of_year += 30;} // Birzelis
if (month > 7){day_of_year += 31;} // Liepa
if (month > 8){day_of_year += 31;} // Rugpjutis
if (month > 9){day_of_year += 30;} // Rugsejis
if (month > 10){day_of_year += 31;} // Spalis
if (month > 11){day_of_year += 30;} // Lapkritis
if (month > 12){day_of_year += 31;} // Gruodis
day_of_year += day;
int time = 0;
time += (year - 1970) * 31536000;
time += day_of_year * 86400;
time += hour * 3600;
time += minute * 60;
time += second;
string time_string;
time_string = parseStr(time);
return time_string;
}
// ============================================================
int main()
{
while(true)
{
system("cls");
string time = timestamp();
print(time);
Sleep(100);
}
return 0;
}
Does i calculating something wrong or something wrong with integer types? :(
Rather than roll your own timestamp would using this work:
time_t epochtime = time(NULL);
the variable epochtime should contain the number of seconds since the beginning of 1970.
Your code doesn't account for leap years which probably makes a difference in your computations vs PHP.
The error is here:
time += (year - 1970) * 31536000;
31536000 is the number of seconds in 365 days. But there have been 11 leap days since 1970, those years have 366 days. You need to add 86400 for each of the leap days.
The difference between your two results is 853192. This is a little less than 10 days, so I'm not sure what happened to the 11th leap day. It's also 3 hours less than 10 days (+ 8 seconds, which I guess is the time between your two tests); that's because Unix timestamps are based on GMT, not local time.

Logical error when modifying a time program in c++

This program is supposed to store time in seconds since midnight and display it in standard and universal time. It runs, but the set Time function has an error in it, as the time never changes. I'm assuming that something isn't being returned right, but I can't find the error.
Header file :
#ifndef TIME_H
#define TIME_H
class Time
{
public:
Time(); //constructor
void setTime(int, int, int );
void printUniversal(); //print time in universal-time format
void printStandard(); // print time in standard-time format
private:
int secondsSinceMidnight;
};
#endif
.cpp file
Time::Time()//constructor
{
secondsSinceMidnight = 0;
}
void Time::setTime(int h, int m, int s)
{
if ((h >= 0 && h < 24) && (m >= 0 && m < 60) && (s >= 0) && (s < 60))
{
int hoursInSecs = (h * 3600);
int minutesInSecs = (m * 60);
secondsSinceMidnight = (minutesInSecs + hoursInSecs);
}
else
throw invalid_argument(
"hour, minute and/or second was out of range");
}
void Time::printUniversal()
{
int secondsSinceMidnight = 0;
int hours = (secondsSinceMidnight / 3600);
int remainder = (secondsSinceMidnight % 3600);
int minutes = (remainder / 60);
int seconds = (remainder % 60);
cout <<setfill('0')<<setw(2)<<hours<<":"
<<setw(2)<<minutes<<":"<<setw(2)<<seconds<<endl;
}
void Time::printStandard()
{
int secondsSinceMidnight = 0;
int hours = (secondsSinceMidnight / 3600);
int remainder = (secondsSinceMidnight % 3600);
int minutes = (remainder / 60);
int seconds = (remainder % 60);
cout<<((hours == 0 || hours == 12) ? 12 : hours % 12) << ":"
<< setfill('0') <<setw(2)<<minutes<< ":"<<setw(2)
<<seconds<<(hours < 12 ? "AM" : "PM")<<"\n";
}
And the main program :
int main()
{
Time t; //instantiate object t of class Time
//output Time object t's initial values
cout<<"The initial universal time is ";
t.printUniversal();
cout<<"\nThe initial standard time is ";
t.printStandard();
int h;
int m;
int s;
cout<<"\nEnter the hours, minutes and seconds to reset the time: "<<endl;
cin>>h>>m>>s;
t.setTime(h, m, s); //change time
//output Time object t's new values
cout<<"\n\nUniversal time after setTime is ";
t.printUniversal();
cout<<"\nStandard time after setTime is ";
t.printStandard();
}
In your print functions you have a local variable with the same name as your field secondsSinceMidnight. It is shadowing it.
Why there are
int secondsSinceMidnight = 0; at the beginning of printUniversal() and printStandard(), this variable would cover member variable.
At the beginning of both of your print functions, you set secondsSinceMidnight = 0. Leave that in the constructor, but remove it from the print functions.