Reputation: 3822
When my program starts, I want it to immediately fill the "Calendar" class with all years/months/days from 1/1/1875 until 31/12/2025. I'm having trouble creating this "Calendar" class, I don't really know what my options are with C++.
What's the best way to realize this? Should the day/month/year be a multimap, and if so; how can I efficiently use that multimap to achieve what I'm trying to do (can multimaps even hold more than 2 objects?)? Or maybe the class shouldn't be a class at all, but the whole thing should be turned into a multimap?
I made this "calendar" project up as an example, but I think my question really comes down to: "How do I design a class (or alternative) that can hold multiple layers of data that are linked and easy to control/access".
And by 'control' I mean add/delete/check-if-already-exists etc.
So maybe something like this (ignoring my example in the picture):
calendar.addYear(1998) //Add 1998 to the year stack (array?) inside the "calendar" object.
calendar.addMonth(1,0) //Add month 1 (january) to month stack (array?) keeping year-array position 0 as a reference, so we know what year this month belongs to.
calendar.addDay(1,0) //Add day 1 to day stack (array?) keeping month-array position 0 as a reference, so we know which month this day belongs to.
An example of something that I would want to programatically achieve with a class like this is:
//This is a magical GUI object I just made up ;D
myGUIofChoiceCreateSomeGUIobject GUIobject;
int i;
for(i=0; i < calendar.yearCount; i++;)
{
GUIobject.addYeartoGUIobject(calendar.year[i]); //Add current year to our GUI. The user can now select it, hooray!
addMonthsToYear(i); //Add months belonging to this year to our GUI.
}
addMonthsToYear(int theYear)
{
int i;
for(i=0; i < calendar.year[theYear].monthCount; i++;)
{
/*
Our made-up GUI will add the current month to the year we received as an
argument. As long as that year is selected in the GUI, our user can pick this month,
hooray!
*/
GUIobject.addMonthToGUIobject(calendar.year[theYear].month[i])
addDaysToMonth(i,theYear) //Add days to this month (not typing this one down, you can see where this is going)
}
}
And as if all of this wasn't complicated enough; what is a calendar without to-do items? So the "calendar.day" needs to linked to an array/multimap/whatever of objects, which could look like this:
struct stuffToDo{
std::string message;
float time;
}
after which it should be easy to add an object like that to the class:
stuffToDo newstuff;
newstuff.message = "Find a C++ tutor so you can stop bothering stackoverflow";
newstuff.time = 15.20;
calendar.year[2012].month[11].day[18].addObject(newstuff);
I'm at a loss, what are my options here?
PS. I'm sorry for the inconsistency between my examples, but it was kind of inevitable without knowing what I'm supposed to do, which is the essence of this question.
Upvotes: 1
Views: 4699
Reputation: 306
Boost library is what you need to look at..
And to help yourself you can find the calendar class you wanna to make here http://sourceforge.net/projects/c-cpp-calender/
Upvotes: 2
Reputation: 6776
I think you need to take a step back and think clearly about what you want to do. What are the key abstractions? What are the operations and actions that you want to support? Write a story about the use of your system. In this story, the important nouns generally become objects in the C++ code, and the important verbs become methods.
It looks like you want your data structure to span many years, but the fundamental object is a Day, which has a number and is a container of Tasks, each of which has a message and a time associated with it. A Day, however, belongs to a month and a year. Now months and years could be simply attributes of a Day, or they could be full-fledged objects on their own (Month and Year). In this second approach, a Month (which also has a name) is a container of Days, and a Year (which also has a number) is a container of Months.
If you have years and months be simply attributes, you might want to have a data structure in your main Calendar class mapping years to days, and one mapping year and month combinations to days. If you go with objects for Months and Years, then at the top level you will have only a list of Year objects, or perhaps a map mapping year numbers to Year objects. To get to a particular day, you simply start with the year number, month name, and day number, and navigate through the tree until you get to the day, perhaps creating objects as you go.
Of course, all this might get a little simpler if you make your fundamental object be a Task, which has day, month, and year attributes. These would be stored in a map where the key is a serialization of year, month, and day. If the map were really a multimap, then each year/month/day combination could have multiple tasks. The Task object could produce this serialized key itself, which provides good information hiding and decoupling, though it might be more flexible to have the class generate it through a static method, not a particular object. This multimap becomes the core of your Calendar object. It is also efficient because the total size of the structure grows with the number of tasks, not the amount of time spanned, provided you can gracefully handle lookups of year/month/day combinations with no associated tasks. To render your calendar, you simply iterate years, months, and days and look up Tasks in the Calendar.
All this boils down the the fact that you need to think hard about your data model. I find that once a good data model is figured out, actually coding it up is almost trivial. Not having a clear data model in mind leads to lots of false starts and messy code. Take a look at the Unified Modeling Language (UML) notations and draw some pictures with pencil and paper. I think things will get a lot clearer for you.
Upvotes: 1