Classes and Constructors

Hello, I'm still new at classes and I was wondering how I would go about this program. I have most of the getters and setters so far but I don't have the getDate, getStandardTime, helper functions militaryToStandard, standardToMilitary, bool operator ==(const Appointment &first,
const Appointment &second)

Parameters:
• Appointment(); Default constructor
It should initialize the title to "N/A". The date should be initialized to 1, 1, and 1. The
time should be initialized to 0, and duration to 1.
• Appointment(string appData);
Add an appointment from a string in the format
"title|year|month|day|time|duration". Time is given in standard time
and duration is given in minutes. Leading and trailing spaces must be removed.
Example: " Meeting with Bob | 2021 |11 |23 |8:30 aM | 15 "
• string getTitle();
• int getYear();
• int getMonth();
• int getDay();
• int getTime(); //military time
• int getDuration();
• string getDate(); //return a date in the format 2021-11-23
• string getStandardTime();
• void setTitle(string newTitle);
• void setYear(int newYear);
• void setMonth(int newMonth);
• void setDay(int newDay);
• void setTime(int newTime); //military time
• void setDuration(int newDuration);
• void setDate(int newYear, int newMonth, int newDay);

In addition, the class must include the following helper functions:
• string militaryToStandard(int time);
Converts time from military (1830) to standard time ("6:30PM")
• int standardToMilitary(string time);
Converts standard time ("8:30PM") to military time (2030). It should handle lowerand upper-case letters.
returns the time in military time format (2030).
• bool operator ==(const Appointment &first,
const Appointment &second);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
 /**
 *   @file: appointment_main.cc
 * @author: Enter your name
 *   @date: Enter the date
 *  @brief: Add Description
 */

#include <iostream>
#include <iomanip>
#include <cstdlib>

using namespace std;

class Appointment
{
public:
    Appointment();

    // Getters
    string getTitle();
    int getYear();
    int getMonth();
    int getDay();
    int getTime(); // military time
    int getDuration();
    string getDate();
    string getStandardTime();

    // Setters
    void setTitle(string newTitle);
    void setYear(int newYear);
    void setMonth(int newMonth);
    void setDay(int newDay);
    void setTime(int newTime); // military time
    void setDuration(int newDuration);
    void setDate(int newYear, int newMonth, int newDay);

private:
    string title;
    int year;
    int month;
    int day;
    int time;
    int duration;
} /// Appointment class

Appointment::Appointment()
{
    title = "N/A";
    time = 0;
    duration = 1;
    day = 1;
    month = 1;
    year = 1;
};
// Appointment C-tor

// function prototypes

int main(int argc, char const *argv[])
{
    // test your class here

    return 0;
} // main

// Add class functions here

void Appointment::setTitle(string newTitle)
{
    if (newTitle = !"")
    {
        title = newTitle;
    }
}

void Appointment::setYear(int newYear)
{
    if (newYear > 1970)
    {
        year = newYear;
    }
}

void Appointment::setMonth(int newMonth)
{
    if (newMonth > 0 && newMonth <= 12)
    {
        newMonth = month;
    }
}

void Appointment::setDay(int newDay)
{
    if (newDay > 0 && newDay <= 31)
    {
        newDay = day;
    }
}

void Appointment::setTime(int newTime)
{
    if (newTime >= 0 && newTime < 2400)
    {
        newTime = time;
    }
}

void Appointment::setDuration(int newDuration)
{
    if (newDuration > 0)
    {
        newDuration = duration;
    }
}

void Appointment::setDate(int newYear, int newMonth, int newDay)
{
    newYear = year;
    newMonth = month;
    newDay = day;
}

string Appointment::getTitle()
{
    return title;
}

int Appointment::getYear()
{
    return year;
}

int Appointment::getMonth()
{
    return month;
}

int Appointment::getDay()
{
    return day;
}

int Appointment::getTime()
{
    return time;
}

int Appointment::getDuration()
{
    return duration;
}

string Appointment::getDate()
{
}

string Appointment::getStandardTime()
{
}
Last edited on
GetDate() - this function should construct a string using the year, month and day, and return the string.

getStandardTime() - similarly, construct a string containing the time, and return it.

militaryToStandard() - assume that the first 2 digits of the int are the hour, and the last two are minutes, and construct a string containing the time in a standard format. You'll have to think a bit about how to deal with the first 9h 59min of the day, and the first 59 min of the day.

standardToMilitary() - this is the reverse of the above. Parse the string to find the hour and minutes components of the time, and construct an integer value from them.

operator == - you will need to write code to determine if the two Appointment objects are identical. If they are, return true. If they're not, return false.
Last edited on
So basically the idea here is to have one giant string
" Meeting with Bob | 2021 |11 |23 |8:30 aM | 15 "
Remove the whitespaces, separate the string into multiple data types, and test them. For the constructor I am terrible at using find/substring to figure out how to separate the strings and make them their own data types.

I have this so far:
The blank functions are the ones I've tried but failed to do.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <string>

using namespace std;

class Appointment
{
public:
    Appointment();
    Appointment(string appData);

    // Getters
    string getTitle();
    int getYear();
    int getMonth();
    int getDay();
    int getTime(); // military time
    int getDuration();
    string getDate();
    string getStandardTime();


    // Setters
    void setTitle(string newTitle);
    void setYear(int newYear);
    void setMonth(int newMonth);
    void setDay(int newDay);
    void setTime(int newTime); // military time
    void setDuration(int newDuration);
    void setDate(int newYear, int newMonth, int newDay);
    
    //Helpers
    string militaryToStandard(int time);
    int standardToMilitary(string time);
    bool operator==(const Appointment &first, const Appointment &second);

private:
    string title;
    int year;
    int month;
    int day;
    int time;
    int duration;
}; /// Appointment class

Appointment::Appointment()
{
    title = "N/A";
    time = 0;
    duration = 1;
    day = 1;
    month = 1;
    year = 1;
}

Appointment::Appointment(string appData)
{

}
// Appointment C-tor

// function prototypes

int main(int argc, char const *argv[])
{
    // test your class here

    return 0;
} // main

// Add class functions here

void Appointment::setTitle(string newTitle)
{
    if (newTitle != "")
    {
        title = newTitle;
    }
}

void Appointment::setYear(int newYear)
{
    if (newYear > 1970)
    {
        year = newYear;
    }
}

void Appointment::setMonth(int newMonth)
{
    if (newMonth > 0 && newMonth <= 12)
    {
        newMonth = month;
    }
}

void Appointment::setDay(int newDay)
{
    if (newDay > 0 && newDay <= 31)
    {
        newDay = day;
    }
}

void Appointment::setTime(int newTime)
{
    if (newTime >= 0 && newTime < 2400)
    {
        newTime = time;
    }
}

void Appointment::setDuration(int newDuration)
{
    if (newDuration > 0)
    {
        newDuration = duration;
    }
}

void Appointment::setDate(int newYear, int newMonth, int newDay)
{
    newYear = year;
    newMonth = month;
    newDay = day;
}

string Appointment::getTitle()
{
    return title;
}

int Appointment::getYear()
{
    return year;
}

int Appointment::getMonth()
{
    return month;
}

int Appointment::getDay()
{
    return day;
}

int Appointment::getTime()
{
    return time;
}

int Appointment::getDuration()
{
    return duration;
}

string Appointment::getDate()
{
    string y = to_string(year);
    string m = to_string(month);
    string d = to_string(day);

    string date = y + "-" + m + "-" + d;
    return date;
}

string Appointment::getStandardTime()
{
    
}

int Appointment::standardToMilitary(string time){

}

int Appointment::militaryToStandard(int time) {

}

bool Appointment::operator==(const Appointment &first, const Appointment &second) {

}

Last edited on
You can operate on the text or you can read data from stream. Some hints:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <sstream>

int main()
{
    std::string input = " Meeting with Bob | 2021 |11 |23 |8:30 aM | 15 ";
    std::istringstream in( input );
    std::string line;
    while ( getline( in >> std::ws, line, '|' ) ) {
        std::cout << '#' << line << "#\n";
    }
}
// http://www.cplusplus.com/reference/sstream/istringstream/
// http://www.cplusplus.com/reference/string/string/getline/
// https://www.cplusplus.com/reference/istream/ws/
// http://www.cplusplus.com/reference/string/stoi/ 
Is there a way to achieve it without sstream?
of course.
This is about the most simple way to do it, and not at all the cleanest, shortest, or the best, but it should be very easy to follow.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main()
{
   std::string input = " Meeting with Bob | 2021 |11 |23 |8:30 aM | 15 ";
   string token{};
   vector<string>vs;
   for(int i{}; i < input.length(); i++) //for all the letters in input
	   {
		  if(input[i] != '|')     //make a substring of letters until you hit the delimiter
		   token += input[i];
	       else
		   {
			vs.push_back(token); //save the substring for later
			token = "";  //reset substring
		   }
	   }
	   if(token.length())  //there is no ending delimiter, so don't forget to grab the last token
		   vs.push_back(token);
	   for(auto &a:vs)  //print what we found. 
		   cout << a << endl;
}
Last edited on
What's wrong with using sstream?

Note that getter class functions should be marked const eg.

1
2
3
4
5
6
7
...
int getYear() const;
...
int Appointment::getYear() const
{
    return year;
}


Unless a function requires a copy, std::string should be passed by const ref to avoid an unnecessary copy eg

1
2
3
4
5
6
7
8
...
void setTitle(const string& newTitle);
...
void Appointment::setTitle(const string& newTitle)
{
    if (!newTitle.empty())
        title = newTitle;
}


The class variable can be initialised when defined - so the default constructor can be the default:

1
2
3
4
5
6
7
8
9
10
...
Appointment() = default;
...
private:
    string title {"N/A"};
    int year {1};
    int month {1};
    int day {1};
    int time {};
    int duration {1};


Why not just for main()

1
2
3
int main() {
...
}

Last edited on
I will be separating the program into three separate compilations

appointment-main.cc (Main program for testing the class and it's functions)
appointment.cc (class implementation)
appointment.h (Class definition)


Truthfully the functions are proving to be hard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
string Appointment::getStandardTime()
{
    
}

int Appointment::standardToMilitary(string time){

}

int Appointment::militaryToStandard(int time) {

}

bool Appointment::operator==(const Appointment &first, const Appointment &second) {

}


Last edited on
Truthfully the functions are proving to be hard

Write out in words on paper the steps you would do mentally/manually to get the results for each function. In detail.

The steps you write then should be easy to craft as code.
For operator==(), what is considered equal for two appointments? The same year. month, day, time and duration? Also, is operator==() to be a member function or a stand-alone function? This determines it's definition format. If it's a member function then:

1
2
3
bool Appointment::operator==(const Appointment &second) {
    // can use private members here
}


but as a stand-alone function then:

1
2
3
bool operator==(const Appointment &first, const Appointment &second) {
    // cannot use private member functions - but can use public getters
}


but the stand-alone function could be a friend function so that it could use the private variables - but as getters are available it needed be.

As a stand-alone function, then possibly:

1
2
3
4
5
bool operator==(const Appointment &first, const Appointment &second) {
    return first.getYear() == second.getYear() && first.getMonth() == second.getMonth() && 
    first.getDay() == second.getDay() && first.getTime() == second.getTime() && 
    first.getDuration() == second.getDuration();
}


What is getStandardTime() supposed to do? What are the other time functions supposed to do? Before you can code, you have to know what is required and be able to state this as a design/algorithm. Then when you know, then code what is required from the design.
Last edited on
The complete outline for the program:

Designing a class called Appointment that stores the properties of a calendar appointment.
Properties include the appointment title, date (year, month, day), starting time (military time),
and duration. Your class must check for invalid values for year, month, day, time, and duration.
The class must include the following getters and setters for all member data (
function names and prototypes must match exactly):
• Appointment(); Default constructor
It should initialize the title to "N/A". The date should be initialized to 1, 1, and 1. The
time should be initialized to 0, and duration to 1.
• Appointment(string appData);
Add an appointment from a string in the format
"title|year|month|day|time|duration". Time is given in standard time
and duration is given in minutes. Leading and trailing spaces must be removed.
Example: " Meeting with Bob | 2021 |11 |23 |8:30 aM | 15 "
• string getTitle();
• int getYear();
• int getMonth();
• int getDay();
• int getTime(); //military time
• int getDuration();
• string getDate(); //return a date in the format 2021-11-23
• string getStandardTime();
• void setTitle(string newTitle);
• void setYear(int newYear);
• void setMonth(int newMonth);
• void setDay(int newDay);
• void setTime(int newTime); //military time
• void setDuration(int newDuration);
• void setDate(int newYear, int newMonth, int newDay);

The class must also include the following helper functions:
• string militaryToStandard(int time);
Converts time from military (1830) to standard time ("6:30PM")
• int standardToMilitary(string time);
Converts standard time ("8:30PM") to military time (2030). It should handle lowerand upper-case letters.
returns the time in military time format (2030).
• bool operator ==(const Appointment &first,
const Appointment &second);
The main program will test all the functions above. Check for invalid values.
Separate your program into three files: (appointment.h, appointment.cc, and
appointment_main.cc)

• Write an output function to print all the values in an object
• For the second constructor, I'll be using the find and the substr string member functions.

Yes - this was as per the first post. So I'll ask again - what are these time functions supposed to do (NOT what the exercise description says). So the time is stored as military time (ie as 24 hour time). So to convert a 'standard' time to military time, what steps are required? What instructions would you give someone to do this? What is the design/algorithm for this? When you have designed this, then you can code from the design. But the first step is the design.

What are the possible variations for standard time? Must AM/PM always be present? If not, then is the time assumed to be AM? Are space(s) before AM/PM allowed?

Similar questions for converting military to standard (although this is somewhat simpler).

Design then code.

As a starter, for standard time extraction one simple way (without any error detection) using say a istringstream then the hour can be extracted using getline() followed by a string/int conversion (or simple extraction followed by char extraction for the :). The minute by a simple extraction and then the AM/PM by a string extraction...
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int Appointment::militaryToStandard(int time)
{
    int minute;
    int hour;
    minute = time % 100;
    hour = time / 100;

    if (hour >= 12)
    {
        hour = hour - 12;
        string toTime = to_string(hour) + ":" + to_string(minute) + "pm";
        cout << toTime;
    }
    else if (hour < 12 && hour >= 0)
    {
        if (hour == 0)
        {
            hour = hour + 12;
        }
        string toTime = to_string(hour) + ":" + to_string(minute) + "am";
        cout << toTime;
    }
}


I have this for the function however it displays the hour perfectly but doesn't display 0's for the minutes properly.

12:1pm


Should be
12:10pm


or

12:01pm


Also if it were exactly 12:00am/pm

this would display
12:0pm
Last edited on
1. Create a blank string for containing the entire time string.

2. Calculate the hour, convert that to a temp string and append that temp string to the time string.

3. Calculate the minutes, convert to a temp string. Check if the minutes less than 10 and add a zero "0" to the beginning of the temp string.

Append that string to the time string.

4. Append "AM" or "PM" to the time string as needed.
Possibly:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>

std::string militaryToStandard(unsigned time) {
	const unsigned minute {time % 100};
	unsigned hour {time / 100 % 24};
	bool PM {};

	if (hour == 0)
		hour += 12;
	else
		if (hour >= 12) {
			hour -= 12 * (hour > 12);
			PM = true;
		}

	std::ostringstream out;

	out << hour << ':' << std::setw(2) << std::setfill('0') << minute << (PM ? "pm" : "am");

	return out.str();
}

int main() {
	unsigned mil;

	while (true) {
		std::cin >> mil;
		std::cout << militaryToStandard(mil) << '\n';
	}
}



2359
11:59pm
2400
12:00am
2401
12:01am
0001
12:01am
0002
12:02am
0202
2:02am
0220
2:20am
1159
11:59am
1200
12:00pm
0
12:00am
1201
12:01pm
1301
1:01pm
2034
8:34pm

code so far however it doesn't work. I'm completely fried as I have tried to work on this for several days now

If ANYONE is kind enough I still need the bool operator==(const Appointment &first, const Appointment &second), int standardToMilitary(string time), int militaryToStandard(int time), string Appointment::getStandardTime(), and Appointment::Appointment(string appData) functions


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <vector>

using namespace std;

class Appointment
{
public:
    Appointment();
    Appointment(string appData);

    // Getters
    string getTitle();
    int getYear();
    int getMonth();
    int getDay();
    int getTime(); // military time
    int getDuration();
    string getDate();
    string getStandardTime();

    // Setters
    void setTitle(string newTitle);
    void setYear(int newYear);
    void setMonth(int newMonth);
    void setDay(int newDay);
    void setTime(int newTime); // military time
    void setDuration(int newDuration);
    void setDate(int newYear, int newMonth, int newDay);

    // Helpers
    friend string militaryToStandard(int time);
    friend int standardToMilitary(string time);
    friend bool operator==(const Appointment &first, const Appointment &second);

private:
    string title;
    int year;
    int month;
    int day;
    int time;
    int duration;
}; /// Appointment class

Appointment::Appointment()
{
    title = "N/A";
    time = 0;
    duration = 1;
    day = 1;
    month = 1;
    year = 1;
}

Appointment::Appointment(string appData)
{
    appData = " Meeting with Bob | 2021 | 11 | 23 | 8 : 30 aM | 15 ";
    string token{};
    vector<string> vs;
    for (int i{}; i < appData.length(); i++) // for all the letters in input
    {
        if (appData[i] != '|') // make a substring of letters until you hit the delimiter
            token += appData[i];
        else
        {
            vs.push_back(token); // save the substring for later
            token = "";          // reset substring
        }
    }
    if (token.length()) // there is no ending delimiter, so don't forget to grab the last token
        vs.push_back(token);
    for (auto &a : vs) // print what we found.
        cout << a << endl;
}
// Appointment C-tor

// function prototypes

int main(int argc, char const *argv[])
{
    // test your class here

    return 0;
} // main

// Add class functions here

void Appointment::setTitle(const string newTitle)
{
    if (newTitle != "")
    {
        title = newTitle;
    }
}

void Appointment::setYear(int newYear)
{
    if (newYear > 1970)
    {
        year = newYear;
    }
}

void Appointment::setMonth(int newMonth)
{
    if (newMonth > 0 && newMonth <= 12)
    {
        newMonth = month;
    }
}

void Appointment::setDay(int newDay)
{
    if (newDay > 0 && newDay <= 31)
    {
        newDay = day;
    }
}

void Appointment::setTime(int newTime)
{
    if (newTime >= 0 && newTime < 2400)
    {
        newTime = time;
    }
}

void Appointment::setDuration(int newDuration)
{
    if (newDuration > 0)
    {
        newDuration = duration;
    }
}

void Appointment::setDate(int newYear, int newMonth, int newDay)
{
    newYear = year;
    newMonth = month;
    newDay = day;
}

string Appointment::getTitle()
{
    return title;
}

int Appointment::getYear()
{
    return year;
}

int Appointment::getMonth()
{
    return month;
}

int Appointment::getDay()
{
    return day;
}

int Appointment::getTime()
{
    return time;
}

int Appointment::getDuration()
{
    return duration;
}

string Appointment::getDate()
{
    string y = to_string(year);
    string m = to_string(month);
    string d = to_string(day);

    string date = y + "-" + m + "-" + d;
    return date;
}

string Appointment::getStandardTime()
{
    string stime = militaryToStandard(time);
    return stime;
}

int militaryToStandard(int time)
{
    int minute{time % 100};
    int hour{time / 100 % 24};
    bool PM{};

    if (hour == 0)
        hour += 12;
    else if (hour >= 12)
    {
        hour -= 12 * (hour > 12);
        PM = true;
    }

    string stime = hour + ":" + setw(2) + setfill('0') + minute + (PM ? "pm" : "am");
    return stime;
}

int standardToMilitary(string time)
{

}

bool operator==(const Appointment &first, const Appointment &second)
{

}

Last edited on
the bool operator goes with the class, IMHO? Is there a need to friend it ? Maybe so you can provide both parameters instead of using 'this' but I don't see any reason to externalize it. /shrug

bool Appointment::operator==(...
JUST LIKE the other methods if you want to do this & 1 param
or as you have if you need a 2 param model.

either way:

it is simply going to be a long boolean expression that looks like:

return (first.title== second.title && first.year==second.year && first.month==second.month && ....); //finish for all the fields
Last edited on
The op== can be standalone and does not need to be a friend at all, because it can use the public interface of Appointment:
first.getTitle()== second.getTitle() && first.getYear()==second.getYear() && ...

Some recommend non-member non-friend over member. Both of those are "better" options than friends.
Try this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <sstream>
#include <cctype>

class Appointment {
public:
	Appointment();
	Appointment(const std::string& appData);

	// Getters
	std::string getTitle() const;
	unsigned getYear() const;
	unsigned getMonth() const;
	unsigned getDay() const;
	unsigned getTime() const; // military time
	unsigned getDuration() const;
	std::string getDate() const;
	std::string getStandardTime() const;

	// Setters
	bool setTitle(const std::string& newTitle);
	bool setYear(unsigned newYear);
	bool setMonth(unsigned newMonth);
	bool setDay(unsigned newDay);
	bool setTime(unsigned newTime); // military time
	bool setDuration(unsigned newDuration);
	bool setDate(unsigned newYear, unsigned newMonth, unsigned newDay);

	// Helpers
	static std::string militaryToStandard(unsigned time);
	static unsigned standardToMilitary(const std::string& time);

private:
	std::string title {"N/A"};
	unsigned year {1};
	unsigned month {1};
	unsigned day {1};
	unsigned time {};
	unsigned duration {1};
};

std::ostream& operator<<(std::ostream& os, const Appointment& app) {
	return os << app.getTitle() << "  " << app.getDate() << "  " << app.getStandardTime() << "  " << app.getDuration();
}

Appointment::Appointment() {}

Appointment::Appointment(const std::string& appData) {
	//appData = " Meeting with Bob | 2021 | 11 | 23 | 8 : 30 aM | 15 ";
	std::string token {};
	std::vector<std::string> vs;

	for (const auto& ch : appData)
		if (ch != '|')
			token += ch;
		else {
			auto itr {token.begin()};
			auto itb {token.rbegin()};

			for (; itr != token.end() && *itr == ' '; ++itr);
			for (; itb != token.rend() && *itb == ' '; ++itb);
			vs.emplace_back(itr, itb.base());
			token.clear();
		}

	if (token.length())
		vs.push_back(token);

	//for (const auto& a : vs)
		//std::cout << a << '\n';

	if (vs.size() != 6) {
		std::cout << "Invalid appointment format!\n";
		return;
	}

	if (!setTitle(vs[0]))
		std::cout << "No title\n";

	if (!setYear(stoul(vs[1])))
		std::cout << "Invalid year " << vs[1] << '\n';

	if (!setMonth(stoul(vs[2])))
		std::cout << "Invalid month " << vs[2] << '\n';

	if (!setDay(stoul(vs[3])))
		std::cout << "Invalid day " << vs[3] << '\n';

	if (!setTime(standardToMilitary(vs[4])))
		std::cout << "Invalid time " << vs[4] << '\n';

	if (!setDuration(stoul(vs[5])))
		std::cout << "Invalid duration " << vs[5] << '\n';
}

bool Appointment::setTitle(const std::string& newTitle) {
	if (!newTitle.empty()) {
		title = newTitle;
		return true;
	}

	return false;
}

bool Appointment::setYear(unsigned newYear) {
	if (newYear > 1970) {
		year = newYear;
		return true;
	}

	return false;
}

bool Appointment::setMonth(unsigned newMonth) {
	if (newMonth > 0 && newMonth <= 12) {
		month = newMonth;
		return true;
	}

	return false;
}

bool Appointment::setDay(unsigned newDay) {
	if (newDay > 0 && newDay <= 31) {
		day = newDay;
		return true;
	}

	return false;
}

bool Appointment::setTime(unsigned newTime) {
	if (newTime < 2400) {
		time = newTime;
		return true;
	}

	return false;
}

bool Appointment::setDuration(unsigned newDuration) {
	if (newDuration > 0) {
		duration = newDuration;
		return true;
	}

	return false;
}

bool Appointment::setDate(unsigned newYear, unsigned newMonth, unsigned newDay) {
	return setYear(newYear) && setMonth(newMonth) && setDay(newDay);
}

std::string Appointment::getTitle() const {
	return title;
}

unsigned Appointment::getYear() const {
	return year;
}

unsigned Appointment::getMonth() const {
	return month;
}

unsigned Appointment::getDay() const {
	return day;
}

unsigned Appointment::getTime() const {
	return time;
}

unsigned Appointment::getDuration() const {
	return duration;
}

std::string Appointment::getDate() const {
	std::ostringstream oss;

	oss << year << '-' << month << '-' << day;
	return oss.str();
}

std::string Appointment::getStandardTime() const {
	return militaryToStandard(getTime());
}

std::string Appointment::militaryToStandard(unsigned miltime) {
	unsigned minute {miltime % 100};
	unsigned hour {miltime / 100 % 24};
	bool PM {};

	if (hour == 0)
		hour += 12;
	else if (hour >= 12) {
		hour -= 12 * (hour > 12);
		PM = true;
	}

	std::ostringstream out;

	out << hour << ':' << std::setw(2) << std::setfill('0') << minute << (PM ? "pm" : "am");
	return out.str();
}

unsigned Appointment::standardToMilitary(const std::string& stdtime) {
	std::istringstream iss(stdtime);
	unsigned hour {}, minute {};
	char del {};
	std::string ampm;

	// NOTE - no error checking!
	iss >> hour >> del >> minute >> ampm;

	ampm[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(ampm[0])));
	ampm[1] = static_cast<char>(std::toupper(static_cast<unsigned char>(ampm[1])));

	const bool pm {ampm == "PM"};

	return ((hour == 12 && minute == 0 && !pm) ? 0 : hour += 12 * (pm == true)) * 100 + minute;
}

bool operator==(const Appointment& first, const Appointment& second) {
	return first.getYear() == second.getYear() && first.getMonth() == second.getMonth() &&
		first.getDay() == second.getDay() && first.getTime() == second.getTime() &&
		first.getDuration() == second.getDuration();
}

int main() {
	const Appointment myApp {" Meeting with Bob | 2021 | 11 | 23 | 8 : 30 aM | 15 "};

	std::cout << myApp << '\n';
}



Meeting with Bob  2021-11-23  8:30am  15

Topic archived. No new replies allowed.