繁体   English   中英

C++ 月、日、年验证

[英]C++ Month, day, and year validation

我目前正在为我的 C++ 编程课程介绍项目工作。 该项目要求用户使用 mm/dd/yyyy 格式输入日期。 根据给出的信息,程序必须确定日期是有效还是无效,然后显示响应。 我目前面临的问题是所有内容都在阅读“约会好!” 我不确定问题出在哪里。 任何帮助表示赞赏。 如果你能帮助我指明正确的方向,那就太棒了。

#include <iostream>
#include <conio.h>

using namespace std;

void getDate(int *month, int *day, int *year);
int checkDate(int month, int day, int year);
void displayMessage(int status);

int main()
{
    int month, day, year;
    int s = 0;

    getDate(&month, &day, &year);
    do
    {
        checkDate(month, day, year);
        displayMessage(s);
        getDate(&month, &day, &year);
    } 
    while (_getch() != EOF);
}

void getDate(int *month, int *day, int *year)
{
    char fill;
    fill = '/';
    cout << "Enter a date in mm/dd/yyyy form: ";
    cin >> *month;
    if (cin.get() != '/')
    {
        cout << "expected /" << endl;
    }
    cin >> *day;
    if (cin.get() != '/')
    {
        cout << "expected /" << endl;
    }
    cin >> *year;
    cout << *month << fill << *day << fill << *year << endl;
};

int checkDate(int month, int day, int year)
{
    if ((month = 1) || (month = 3) || (month = 5) || (month = 7) ||
        (month = 8) || (month = 10) || (month = 12))
    {
        day <= 31;
    }
    else if ((month = 4) || (month = 6) || (month = 9) || (month = 11))
    {
        day <= 30;
    }
    else if ((month = 2) && (year % 4 == 0))
    {
    day <= 29;
    }
    else if ((month = 2) && (year % 4 != 0))
    {
        day <= 28;
    };
    int status = 0;
    if ((year < 999) || (year > 10000))
    {
        status == 1;
    }
    if ((month < 1) || (month > 12))
    {
        status == 2;
    }
    else if ((day < 1) || (day > 31))
    {
        status == 3;
    }
    else if ((day < 1) || (day > 30))
    {
        status == 4;
    }
    else if ((day < 1) || (day > 29))
    {
        status == 5;
    }
    else if ((day < 1) || (day > 28))
    {
        status == 6;
    }
    return status;
};

void displayMessage(int status)
{
    if (status == 0)
    {
        cout << "Good date!" << endl;
    }
    if (status == 1)
    {
        cout << "Bad year" << endl;
    }
    if (status == 2)
    {
        cout << "Bad month" << endl;
    }
    if (status == 3)
    {
        cout << "Bad day. Not 1-31" << endl;
    }
    if (status == 4)
    {
        cout << "Bad day, not 1-30" << endl;
    }
    if (status == 5)
    {
        cout << "Bad day, not 1-29" << endl;
    }
    if (status == 6)
    {
        cout << "Bad day, not 1-28" << endl;
    }
    _getch();
}

1) 这里有几个问题,但最明显的是main()

int s=0; 
...
    checkDate(month, day, year);   // you don't store the status
    displayMessage(s);             // so s will always be 0 ! So good date !

你必须纠正这个:

    s=checkDate(month, day, year); // store the result of the check        
    displayMessage(s);             // and take it to display the message  

2) 然后在checkDate() ,你混合=== =将变量的值更改到其左侧。 ==只是进行比较,但不存储任何内容。 更正/调整时,无需任何优化,您的代码应如下所示:

int checkDate(int month, int day, int year)
{
    int status=0; 

    if ((month == 1 || month == 3 || month == 5 || month == 7 ||
        month == 8 || month == 10 || month == 12) && ( day>31 || day<1) )
    {
        status = 3; 
    }
    else if ((month == 4 || month == 6 || month == 9 || month == 11) && (day>30 || day<1) )
    {
        status = 4; 
    }
    else if ((month == 2) && (year % 4 == 0) && (day>29 || day<1))
    {
        status = 5; 
    }
    else if ((month == 2) && (year % 4 != 0) && (day>28 || day<1) )
    {
        status = 6; 
    }
    else if ((year < 999) || (year > 10000))
    {
        status = 1;
    }
    if ((month < 1) || (month > 12))
    {
        status = 2;
    }
    return status;
};

3)在此之后,您应该改进输入功能,因为:

  • 它不处理无效的分隔符。 如果缺少“/”,则会显示一条错误消息,但您可以继续输入,就好像一切正​​常一样。
  • 它不处理无效(ienon 数字)输入。 例如,如果用户输入 XI/1/2016,您的输入将失败。

所以请记住, (cin>>xxx)是一个可以在if使用的表达式,如果所有内容都被正确读取,则该表达式为真。 还要注意cin.clear()清除在失败后阻止输入的错误标志。

更紧凑和剥离的 checkDate (替换大写返回值)

int checkDate(int day, int month, int year) {
    if(day < 1 || day > 31) {
        return BADVALUE;
    } else if(month < 1 || month > 12) {
        return BADVALUE;
    } else if (year < MINYEAR || year > MAXYEAR) {
        return YEAROUTRANGE;
    }

    if ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) {
        return BADMONTHDAY; 
    } else if ((month == 2) && (year % 4 == 0) && day > 29) {
        return BADMONTHYEAR;

    } else if ((month == 2) && (year % 4 != 0) && day > 28) {
        return BADMONTHYEAR; 
    }
    return GOOD;
}

这也可以通过正则表达式来实现吗?

我知道这种方法有很多缺点,但仍然可以考虑:

#include <regex>
#include <string>

using std::regex;
using std::regex_match;
using std::string;

// for ddmmyy
regex ddmmyy("^([0-2][0-9]|(3)[0-1])(((0)[0-9])|((1)[0-2]))\\d{2}$");

/* 
   for dd/mm/yy https://regex101.com/r/IqPLBJ/1
   for dd/mm/yyyy - could start from \\d{4}$ instead of \\d{2}$ bearing 0000-case in mind
*/
regex slashed_ddmmyy("^([0-2][0-9]|(3)[0-1])\/(((0)[0-9])|((1)[0-2]))\/\\d{2}$"); 

string f1 = "111223";
bool res = regex_match(f1,ddmmyy); // true

f1 = "112223";
res = regex_match(f1,ddmmyy); // false

res = regex_match(f1, slashed_ddmmyy); // false, no slashes

您也可以使用函数mktime()

它尝试将给定的 tm 结构转换为正确的日期。 如果结构的各个成员的比较随后显示所有成员都相等,则给定的 tm 结构包含有效日期。

bool CBorrow::validateDate(tm * timestruct)
{
    struct tm copy;
    copy.tm_sec = timestruct->tm_sec;
    copy.tm_min = timestruct->tm_min;
    copy.tm_hour = timestruct->tm_hour;
    copy.tm_mday = timestruct->tm_mday;
    copy.tm_mon = timestruct->tm_mon;
    copy.tm_year = timestruct->tm_year;
    copy.tm_wday = timestruct->tm_wday;
    copy.tm_yday = timestruct->tm_yday;
    copy.tm_isdst = timestruct->tm_isdst;

    time_t res = mktime(&copy);
    if (res < 0)
    {
        return false;
    }
    if (copy.tm_mday != timestruct->tm_mday
     || copy.tm_mon != timestruct->tm_mon
     || copy.tm_year != timestruct->tm_year)
    {
        return false;
    }
    return true;
}

C++20 的更新答案:

#include <chrono>
#include <iostream>

void
displayMessage(std::chrono::year_month_day ymd)
{
    using namespace std;
    using namespace std::chrono;
    if (!ymd.year().ok())
    {
        cout << "Bad year\n";
        return;
    }
    if (!ymd.month().ok())
    {
        cout << "Bad month\n";
        return;
    }
    if (!ymd.ok())
    {
        cout << "Bad day, not 1-" << (ymd.year()/ymd.month()/last).day() << '\n';
        return;
    }
    cout << "Good date!\n";
}

int
main()
{
    using namespace std::literals;
    displayMessage(29d/2/1900);
}

输出:

Bad day, not 1-28

(1900年不是闰年)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM