Example
=======


We will implement a "diary" class which represents
an ordered list of events. Each events is identified
by a date and has an associated event.


No duplicate date is allowed.


This is the test program:



/*
 * diary: list of dates and associated events
 *
 */

#include <iostream>
#include <string>
#include "date.h"
#include "diary.h"

int main()
{
    int your_mark = 1;

    // default constructor: creates an empty list of events
    diary my_diary;

    // inserting elements done ordered by date
    my_diary.insert(2015,5,18,"C++ exam");
    my_diary.insert(2015,5,19,"Party");
    my_diary.insert(2015,5,11,"Practicing for C++ exam");

    if ( 3 == my_diary.size() )
        your_mark++;

    diary diary2 = my_diary;  // copy of diary
    diary2.insert(2015,5,17,"Reading C++ material");  // ok
    diary2.insert(2015,5,16,"Party");      // ok
    diary2.insert(2015,5,16,"More party"); // duplicated date: ignore

    if ( 3 == my_diary.size() && 5 == diary2.size() )
        your_mark++;

    diary2.replace(2015,5,16,"More practicing");  // replace "Party"

    if ( diary2.get(2015,5,16) == "More practicing")
        your_mark++;

    diary::iterator i = diary2.begin();   //  first event: 2015.05.11
    i++;                                  // second event: 2015.05.16
    i++;                                  //  third event: 2016.05.17

    if ( getDate(i) == date(2015,5,17) &&   // changed from i->getDate()
         getEvent(i) == std::string("Reading C++ material") )
        your_mark++;

    std::cout << "my_diary:" << std::endl;
    my_diary.print();
    std::cout << std::endl;

    std::cout << "diary2:" << std::endl;
    diary2.print();
    std::cout << std::endl;

    std::cout << "Your mark is " << your_mark << std::endl;
    return 0;
}




We have multiple choices to implement the diary.

1. we could use a std::list with a pair of date and std::string.
2. we could use std::map





/*
 *  diary - list of dates with associated events
 *
 *  implementation wth std::map
 *  std::map is a key-value pair with no key duplication
 *  std::map is sorted: elements are ordered by the key
 *
 */

#ifndef DIARY_H
#define DIARY_H

#include <map>
#include <string>
#include "date.h"  // we use the date we implemented earlier


class diary
{
public:
  /* for mark 5 we implement iterators */
  struct iterator : public std::map<date,std::string>::iterator
  {
     /* this constructor is needed for diary::begin() 
        to convert from std::map<>::iterator    */
     iterator(std::map<date,std::string>::iterator i) :
                std::map<date,std::string>::iterator(i) { }
  };
  /* also const_iterator for completeness */
  struct const_iterator : public std::map<date,std::string>::const_iterator
  {
     /* this constructor is needed for diary::begin() 
        to convert from std::map<>::const_iterator    */
     const_iterator(std::map<date,std::string>::const_iterator i) :
                std::map<date,std::string>::const_iterator(i) { }

     /* conversion from iterator tzo const_iterator */
     const_iterator(iterator i) :
                std::map<date,std::string>::const_iterator(i) { }
  };

  iterator       begin()        { return _entries.begin(); }
  const_iterator begin() const  { return _entries.begin(); }

  iterator       end()          { return _entries.end(); }
  const_iterator end()   const  { return _entries.end(); }

  /* for debug */
  void print() const
  {
      for ( std::map<date,std::string>::const_iterator i  = _entries.begin();
                                                   i != _entries.end(); ++i)
      {
          std::cout << i->first  << " : "
                    << i->second << std::endl;
      }
  }

  void insert( int y, int m, int d, std::string e)
  {
      date key(y,m,d);
      if ( _entries.count(key) == 0 )  // ignore duplicates
      /* the same would be: if ( _entries.find(key) == _entries.end() ) */
          _entries[key] = e;
  }

  void replace( int y, int m, int d, std::string e)
  {
      date key(y,m,d);
      if ( _entries.count(key) == 1 )  // only if exists
          _entries[key] = e;
  }

  std::string get(int y, int m, int d) const
  {
    date key(y,m,d);
    std::map<date,std::string>::const_iterator i = _entries.find(key);
    if ( _entries.end() != i )  // if found
          return i->second;
      else
          return std::string();
  }

  int size() const { return _entries.size(); }

private:
  std::map< date, std::string>  _entries;
};

/*
 * I changed these methods from i->getDate() to getDate(i)
 * the other form can be implemented too, but much more code were needed
 */
date        getDate ( diary::const_iterator i ) { return i->first; }
std::string getEvent( diary::const_iterator i ) { return i->second; }

#endif



To compile and run the code:



$ g++ -ansi -pedantic -Wall -W diarymain.cpp date.cpp
$ ./a.out
my_diary:
[ 2015.5.11 ] : Practicing for C++ exam
[ 2015.5.18 ] : C++ exam
[ 2015.5.19 ] : Party

diary2:
[ 2015.5.11 ] : Practicing for C++ exam
[ 2015.5.16 ] : More practicing
[ 2015.5.17 ] : Reading C++ material
[ 2015.5.18 ] : C++ exam
[ 2015.5.19 ] : Party

Your mark is 5
$




Further examples
================


1. Create a "complex" class with "real" and "imaginary" components.
   The components are double. Implement the basic operations: + - * /
   Create a simple calcuator working with complex numbers.


2. Create a new version of the diary. In this version each days have
   24 hours, and to every hour an event can be assigned.