我如何解释以不同格式输入的日期?

How can I account for dates being entered in different formats?

我有一个程序需要读取输入的日期。如果输入日期 D/MM/YYYY,我能够正确读取日期。当日期输入为 DD/MM/YYYY 时,它读取不正确,因为 substr 没有考虑其中有 2 位数字的天数。

所以有 4 种不同的正确日期输入方式:

D/M/YYYY

DD/MM/YYYY

D/MM/YYYY

DD/M/YYYY

此外,如果输入的 day/month 不正确,例如 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
*/
}

使用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:您可能想要这些标记的数字,所以阅读 How can I convert a std::string to int?

如果您替换“/”,您可以只使用 istringstream 进行一些简单的解析。像这样:

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

std::istringstream stream(date);

stream >> day_;
stream >> month_;
stream >> year_;

有多种方法可以extract\parse日期格式的日期和时间,我会这样做:

#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);
}

Note that the date checking is just for making sure, it is not required...

大大缩短了,甚至可以是:

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;
}

输出:

Date: 29
Month: 2
Year: 2016