Как я могу учесть даты, вводимые в разных форматах? - PullRequest
0 голосов
/ 09 ноября 2018

У меня есть программа, в которой мне нужно прочитать вводимую дату. Я могу правильно прочитать дату, если она введена в формате Д / ММ / ГГГГ. Когда дата вводится как ДД / ММ / ГГГГ, она читается неправильно, потому что подстрок не учитывает дни, в которых есть 2 цифры.

так что есть 4 разных правильных способа ввода даты:

D / M / YYYY

DD / MM / YYYY

D / MM / YYYY

DD / M / YYYY

Кроме того, если введен неправильный день / месяц, например, 100/4/2018, это затруднит правильное прочтение остальной части строки. Год и месяц.

В ходе моего собственного тестирования у меня был цикл for, ищущий первый «/», затем читающий то, что было до него, но это не сработало.

Как я могу объяснить эти разные способы ввода дат?

MYDate::MYDate(std::string date) {

//int size = date.length();




SetYear(year_ = std::atoi(date.substr(5, 4).c_str()));
SetMonth(month_ = std::atoi(date.substr(3, 2).c_str()));
SetDay(day_ = std::atoi(date.substr(0, 2).c_str()));


/*
9/9/2001
09/09/2001
9/09/2001
09/9/2001
*/
}

Ответы [ 3 ]

0 голосов
/ 09 ноября 2018

Вы можете просто использовать istringstream для простого анализа, если вы замените '/'. Как это:

std::replace( date.begin(), date.end(), '/', ' ');

std::istringstream stream(date);

stream >> day_;
stream >> month_;
stream >> year_;
0 голосов
/ 09 ноября 2018

Существуют различные способы извлечения \ разбора даты и времени из формата даты, и вот что я бы сделал:

#include <tuple>
#include <sstream>

#define IS_LEAP_YEAR(year) ((year) % 4 == 0 && (year) % 100 != 0 || (year) % 100 == 0 && (year) % 400 == 0 || (year) % 400 == 0)

std::tuple<int, int, int> GiveDateFromFormat(std::string const& format, char const delimiter = '\\')
{
    std::stringstream ss(format);
    std::string date, month, year;
    std::getline(ss, date, delimiter);
    std::getline(ss, month, delimiter);
    std::getline(ss, year, delimiter);
    auto date_num = std::stoi(date), month_num = std::stoi(month), year_num = std::stoi(year);
    if (month_num > 12 || month_num < 1 || date_num >(month_num % 2 == 0 && month_num != 2 ? 30 : 31) ||
        date_num > (IS_LEAP_YEAR(year_num) ? 29 : 28) && month_num == 2)
        throw std::invalid_argument("Date does not exist!");
    return std::make_tuple(date_num, month_num, year_num);
}

Обратите внимание, что проверка даты только для того, чтобы убедиться, что она не требуется ...

Значительно сокращено, даже может быть:

std::tuple<int, int, int> GiveDateFromFormat(std::string const& format, char const delimiter = '\\')
{
    std::stringstream ss(format);
    std::string date, month, year;
    std::getline(ss, date, delimiter);
    std::getline(ss, month, delimiter);
    std::getline(ss, year, delimiter);
    return std::make_tuple(std::stoi(date), std::stoi(month), std::stoi(year));
}

Использование:

int main()
{
    auto date_time = GiveDateFromFormat("29\\2\\2016");
    std::cout << "Date: " << std::get<0>(date_time) << std::endl
              << "Month: " << std::get<1>(date_time) << std::endl
              << "Year: " << std::get<2>(date_time) << std::endl;
    return 0;
}

Выход:

Дата: 29
Месяц: 2
Год: 2016

0 голосов
/ 09 ноября 2018

Используйте std::string::substr для разделения на токены. Вот наивный пример, которого может быть достаточно для начала работы:

#include <iostream>
#include <string>

int main () {
    std::string s = "09/09/2001";
    std::string delimiter = "/";

    size_t pos = 0;
    std::string token;
    int i = 0;
    while ((pos = s.find(delimiter)) != std::string::npos) {
        token = s.substr(0, pos);
        !i++ ? std::cout << "Day: " << token << std::endl : std::cout << "Month: " << token << std::endl;
        s.erase(0, pos + delimiter.length());
    }
    std::cout << "Year: " << s << std::endl;
    return 0;
}

Выход:

Day: 09
Month: 09
Year: 2001

Я проверил все четыре введенных вами запроса, и это работает.

PS: Вы, вероятно, хотели бы, чтобы эти токены были в числах, поэтому прочитайте Как я могу преобразовать std :: string в int?

...