1
votes

I want to be able to throw an exception in case the user has not typed the month names correctly... So I came uip with the idea of storing the names in a static array in a class called Data...

Here is the static array I am talking about: string Data::nomes_meses[12]{"Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"}; You can see it in the file data.cpp.

The code which is bugging my application is the following:

int mes{};
auto itr = find(Data::nomes_meses, Data::nomes_meses + 12, date_parts[1]);

if (itr == end(Data::nomes_meses))
{
    throw("Você deve informar uma data válida");
}

mes = distance(Data::nomes_meses, itr);

If we try, as for instance "Jan" in the find function we can see the exception being thrown terminate called after throwing an instance of 'char const*' ...

auto itr = find(Data::nomes_meses, Data::nomes_meses + 12, "Jan");

Alhough it will work just fine for some months, for instance: Fev, Mar, Abr, Jun, Ago...

Does someone out there know what the heck is this issue I am facing??

data.h

#ifndef DOMINIOS_H_INCLUDED
#define DOMINIOS_H_INCLUDED

#include <stdexcept>
#include <vector>    
class Data
{
private:
    string data;
    void validar(string);

    static const int ANO_MAX_VALIDO = 9999;
    static const int ANO_MIN_VALIDO = 2000;
    bool ehAnoBissexto(int);

public:
    static string nomes_meses[12];
    inline string getData() { return data; }
    void setData(string data);

    Data(string data);
    Data(const Data &src);
    Data(Data &&src);
    ~Data();
};

#endif // DOMINIOS_H_INCLUDED

data.cpp

#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sstream>
#include <regex>

#include "data.h"    
string Data::nomes_meses[12]{"Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"};

void Data::validar(string data)
{
    stringstream ss, ss_dia;

    string date_parts[3]{};
    regex str_expr("^(?:(\\d\\d)\\/([A-Z][a-z]{2})\\/(\\d{4})|([a-z]{3})\\/(\\d\\d)\\/(\\d{4}))$");
    if (!regex_match(data, str_expr))
    {
        throw("Informe uma data válida");
    }

    string s = data;
    string delimiter = "/";

    size_t pos = 0;
    string token;
    int i{0};

    while ((pos = s.find(delimiter)) != string::npos)
    {
        token = s.substr(0, pos);
        date_parts[i] = token;
        cout << token << endl;
        s.erase(0, pos + delimiter.length());
        ++i;
    }

    date_parts[i] = s;
    int ano{};
    ss << date_parts[2];
    ss >> ano;

    int mes{};
    auto itr = find(Data::nomes_meses, Data::nomes_meses + 12, date_parts[1]);

    if (itr == end(Data::nomes_meses))
    {
        throw("Você deve informar uma data válida");
    }

    mes = distance(Data::nomes_meses, itr);

    int dia{};
    ss_dia << date_parts[0];
    ss_dia >> dia;
    if (ano > ANO_MAX_VALIDO ||
        ano < ANO_MIN_VALIDO)
        throw("Informe uma data válida");
    if (mes < 1 || mes > 12)
        throw("Você deve informar um mês válido");
    if (dia < 1 || dia > 31)
        throw("Você deve informar um dia válido");

    if (mes == 2)
    {
        if (ehAnoBissexto(ano))
            if (!dia <= 29)
                throw("Informe uma data válida");
            else if (!dia <= 28)
                throw("Informe uma data válida");
    }

    if ((mes == 4 || mes == 6 ||
         mes == 9 || mes == 11) &&
        (!dia <= 30))
        throw("Informe uma data válida");
}

bool Data::ehAnoBissexto(int ano)
{
    return (((ano % 4 == 0) &&
             (ano % 100 != 0)) ||
            (ano % 400 == 0));
}

void Data::setData(string data)
{
    this->data = data;
}

Data::Data(string data) : data{data}
{
    validar(data);
}
Data::~Data() {}

main.cpp

#include <iostream>
#include <ctime>
#include <vector>
#include "data.h"


using namespace std;

vector<string> Cidade::cidades;
vector<Codigo *> Codigo::codigos;
void display_cities()
{
     vector<string> cities = Cidade::getCidades();
     cout << cities.size() << endl;
     for (size_t i = 0; i < cities.size(); i++)
     {
          cout << cities[i] << endl;
     }
}

int main()
{
     Data newDate2{"12/Fev/2022"};
     Data newDate3{"12/Mar/2022"};
     Data newDate4{"12/Abr/2022"};
     Data newDate5{"12/Mai/2022"};
     Data newDate1{"12/Jan/2022"};
     Data newDate6{"12/Jun/2022"};
     Data newDate7{"15/Jul/2022"};
     Data newDate8{"15/Ago/2022"};
     Data newDate9{"28/Set/2022"};
     Data newDate10{"15/Out/2022"};
     Data newDate11{"28/Nov/2022"};
     Data newDate12{"28/Dez/2022"};
}
That's far from a minimal reproducible example as you're required to post here! - πάντα ῥεῖ
You can test everything out there only checking the description - Breno
If we try, as for instance "Jan" in the find function we can see the exception being thrown terminate called after throwing an instance of 'char const*' ... auto itr = find(Data::nomes_meses, Data::nomes_meses + 12, "Jan"); Alhough it will work just fine for some months, for instance: Fev, Mar, Abr, Jun, Ago... Does someone out there know what the heck is this issue I am facing?? - Breno
No clear error messages, tons of completely unrelated code?? Are you serious? Go edit your question please! - πάντα ῥεῖ
terminate called after throwing an instance of 'char const*' that's the only exception I can see - Breno