簡體   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