Project 1 || Wong Edition || C++ Project || B.Tech Diaries

Project #1 - Sorted Date List

  • Read a sequence of dates from file input.
  • Permissible formats for dates include
    dd/mm/yyyy e.g. 01/01/1970
    
    d MMM yyyy e.g. 1 JAN 1970
    
    MMM d, 1970 e.g. JAN 1, 1970
    
    MMMM d, yyyy e.g. January 1, 1970.
    
  • Sort and output the dates such that the later dates come first.
  • Use functions from the STL's: `<string>`, `<algorithm>`, `<regex>`, `<iterator>`, `<array>`.
  • Create your customised MyDate class.

Solution:


#include <iostream>
#include <string>
#include <algorithm>
#include <regex>
#include <iterator>
#include <array>
#include <fstream>
#include <iomanip>

#define N 25

class Date
{
private:
    int day;
    int month;
    int year;
    std::array<std::string, 12> _months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};

public:
    Date()
    {
        day = 9999;
        month = 9999;
        year = 9999;
    }
    Date(std::string str_date)
    {
        day = 1;
        month = 1;
        year = 1970;
        _date_parser(str_date);
    }
    ~Date() {}
    bool is_valid()
    {
        if (day > 31 || day < 1)
            return false;
        if (month > 12 || month < 1)
            return false;
        if (year > 9999 || year < 1000)
            return false;
        return true;
    }
    void _date_parser(std::string str_date)
    {
        std::string _months_abbr_pattern = "", _months_pattern = "";
        for (size_t i = 0; i < _months.size(); i++)
        {
            _months_abbr_pattern += _months[i].substr(0, 3);
            if (_months.size() - 1 != i)
            {
                _months_abbr_pattern += "|";
            }
        }
        for (size_t i = 0; i < _months.size(); i++)
        {
            _months_pattern += _months[i];
            if (_months.size() - 1 != i)
            {
                _months_pattern += "|";
            }
        }

        std::array<std::regex, 10> patterns({
            std::regex("([0-2][1-9]|3[0-1])\\s*[, /\\-]\\s*(0[1-9]|1[0-2])\\s*[, /\\-]\\s*([1-5]\\d{3})"),
            std::regex("([1-9]|[1-2][1-9]|3[0-1])\\s*[, /\\-]\\s*(" + _months_abbr_pattern + ")\\s*[, /\\-]\\s*([1-5]\\d{3})", std::regex::icase),
            std::regex("(" + _months_abbr_pattern + ")\\s*[, /\\-]\\s*([1-9]|[1-2][1-9]|3[0-1])\\s*[, /\\-]\\s*([1-5]\\d{3})", std::regex::icase),
            std::regex("(" + _months_pattern + ")\\s*[, /\\-]\\s*([1-9]|[1-2][1-9]|3[0-1])\\s*[, /\\-]\\s*([1-5]\\d{3})", std::regex::icase),
        });

        std::smatch match;
        bool check = false;
        for (size_t i = 0; i < patterns.size(); i++)
        {
            if (std::regex_match(str_date, patterns[i]))
            {
                std::regex_search(str_date, match, patterns[i]);
                switch (i)
                {
                case 0:
                    day = std::stoi(match[1].str());
                    month = std::stoi(match[2].str());
                    year = std::stoi(match[3]);
                    break;
                case 1:
                    day = std::stoi(match[1].str());
                    month = _months.size();
                    for (size_t i = 0; i < _months.size(); i++)
                    {
                        if (_months[i].substr(0, 3) == match[2].str())
                        {
                            month = i + 1;
                            break;
                        }
                    }
                    year = std::stoi(match[3]);
                    break;
                case 2:
                    day = std::stoi(match[2].str());
                    month = _months.size();
                    for (size_t i = 0; i < _months.size(); i++)
                    {
                        if (_months[i].substr(0, 3) == match[1].str())
                        {
                            month = i + 1;
                            break;
                        }
                    }
                    year = std::stoi(match[3]);
                    break;
                case 3:
                    day = std::stoi(match[2].str());
                    month = _months.size();
                    for (size_t i = 0; i < _months.size(); i++)
                    {
                        if (_months[i] == match[1].str())
                        {
                            month = i + 1;
                            break;
                        }
                    }
                    year = std::stoi(match[3]);
                    break;
                }
                check = true;
                break;
            }
        }
        if (!check)
            std::cout << "Invalid Format" << std::endl;
    }

    bool operator>(Date d)
    {
        if (year > d.year)
            return true;
        else if (year == d.year)
        {
            if (month > d.month)
                return true;
            else if (month == d.month)
            {
                if (day > d.day)
                    return true;
                else
                    return false;
            }
            else
                return false;
        }
        return false;
    }

    bool operator<(Date d)
    {
        if (year < d.year)
            return true;
        else if (year == d.year)
        {
            if (month < d.month)
                return true;
            else if (month == d.month)
            {
                if (day < d.day)
                    return true;
                else
                    return false;
            }
            else
                return false;
        }
        return false;
    }

    std::string _str()
    {
        std::string str_date = "";
        str_date += std::to_string(day) + " ";
        str_date += _months[month - 1] + " ";
        str_date += std::to_string(year);
        return str_date;
    }

    friend std::ostream &operator<<(std::ostream &os, Date &date)
    {
        os << date._str();
        return os;
    }
};

std::array<Date, N> get_dates(std::string filename)
{
    std::ifstream infile;
    std::string str_date;

    std::array<Date, N> date_array;
    std::cout << "Get Dates from " << filename << " ... " << std::endl;
    int i = 0;
    infile.open(filename);
    while (std::getline(infile, str_date))
    {
        if (str_date != "")
            date_array[i++] = Date(str_date);
    }
    infile.close();

    return date_array;
}

int main(int argc, char const *argv[])
{
    std::array<Date, N> dates = get_dates("date_list.txt");

    std::cout << "Sorting Dates ... " << std::endl;
    std::sort(dates.begin(), dates.end());

    std::array<Date, N>::iterator it;
    for (it = dates.begin(); it != dates.end(); it++)
    {
        if (it->is_valid())
            std::cout << *it << std::endl;
    }

    return 0;
}

Input (date_list.txt):


30/01/3055
30-02-4849
30 01, 3459
16/11/5509
30-06/1571
13-Aug-1768
30/ Apr/1002
2 May 2668
29 JAN, 5802
31 Jul 2224
Jan 7 3106
Apr 31 1632
Mar 6 ,3214
Feb 19, 5063
Sep 6-3652
April 30, 5889
January 13 ,4035
May 21 2671
June 30, 4785
JANUARY 4 2324

Output:


Get Dates from date_list.txt ... 
Sorting Dates ...
30 April 1002
30 June 1571
31 April 1632
13 August 1768
31 July 2224
4 December 2324
2 May 2668
21 May 2671
30 January 3055
7 January 3106
6 March 3214
30 January 3459
6 September 3652
13 January 4035
30 June 4785
30 February 4849
19 February 5063
16 November 5509
29 December 5802
30 April 5889

Share:

0 comments:

Post a Comment