This program works fine, but I need help with the date validation. I have a regular expression that checks for dash patterns and integers and that is all. Is there some way I can add a date validation that can check for improper dates and leap year? If so, is it possible to add it to the regular expression I have already created, or will I need to create a seperate one? Here is my code:

// inventory.cpp : Defines the entry point for the console application.
//

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <regex>
using namespace std;

const int DESC_SIZE = 50;

struct Date{
    int Month;
    int Day;
    int Year;
};

struct Inventory
{
    char desc[DESC_SIZE];   
    int quantity;
    double whlCost,
           rtlCost;
    Date date;
};

void menu(std::fstream&);
bool addRecord(std::fstream&);
bool displayRecord(std::fstream&);
bool changeRecord(std::fstream&);
Date dateValidation(string);

int main()
{

    cout << fixed << showpoint << setprecision(2);
    fstream file;
    ifstream ifile("Inventory.dat");        
    if (!ifile)
    {
        Date date;
        date.Day = 1;
        date.Month = 1;
        date.Year = 1970;
        Inventory rec = {"Default", 0, 0.0, 0.0, date};
        file.open ("Inventory.dat", fstream::out | fstream::binary);
        for (int count = 0; count < 10; count++)
        {           
            file.write((char*)&rec,sizeof(rec));
        }
        cout << endl << "Warning, did not find file, so we created one.";
        cout << endl;     
        file.close();
    }   

    // Create Menu and run program
    menu(file); 
    system("pause");
    return 0;

}

Date dateValidation(string data){
    Date date;
    match_results<string::const_iterator> m;
    regex re("([0-9]+)-([0-9]+)-([0-9]*)?");    
    if (regex_match(data, m, re)) {
        date.Day = stoi(m[1].str()),
        date.Month = stoi(m[2].str()),
        date.Year = stoi(m[3].str());       
    }
    else date.Year = 0000;
    return date;
}




void menu(std::fstream& file)
{   
    int choice = 0;
    bool success;
    while(choice!= 4) {
        cout << "Auto Zone Inventory" << endl;
        cout << endl << "1. Add new records to the file" << endl;
        cout << "2. Display any record in the file" << endl;
        cout << "3. Change any record in the file" << endl;
        cout << "4. Quit the program" << endl;
        cout << endl;
        cout << "Please enter your choice (1-4): ";
        cin >> choice;

        while (choice < 1 || choice > 4)
        {
            cout << endl << "Invalid entry. Please enter a number (1-4)" << endl;
            cin >> choice;
        }
        cout << endl;

        switch(choice){
            case 1:
                    success = addRecord(file);                  
                    break;                  
            case 2:
                    success = displayRecord(file);
                    break;
            case 3:
                    success = changeRecord(file);
                    break;
            case 4: 
                    success = true;
                    cout << "Thank you for using this program. Auto Zone cares!" << endl;
                    break;
            default : 
                    cout << "Error " << choice << " is not a valid number";
                    break;
        }               
        if (!success) cout << "File IO Error reading file!";
        else {
            system("Pause");
            system("cls");
        }

    }
}

bool addRecord(std::fstream& file)
{
    cout << "Please enter new record data" << endl;
    Inventory rec;
    string dateStr;
    file.open ("Inventory.dat", fstream::out | fstream::app | fstream::binary);

    cout << endl << "Item Description:" << endl;
    cin.ignore();
    cin.getline(rec.desc, DESC_SIZE);
    cout << rec.desc << endl;
    cout << endl << "Quantity on hand:" << endl;
    cin >> rec.quantity;

    while (rec.quantity < 0)
    {
        cout <<  endl << "Invalid entry. Please enter only positive values." << endl;
        cin >> rec.quantity;
    }

    cout << endl << "Wholesale Cost" << endl;
    cin >> rec.whlCost;

    while (rec.whlCost < 0)
    {
        cout << endl << "Invalid entry. Please enter only positive values." << endl;
        cin >> rec.whlCost;
    }

    cout << endl << "Retail Cost" << endl;
    cin >> rec.rtlCost;

    while (rec.rtlCost < 0)
    {
        cout << endl << "Invalid entry. Please enter only positive values." << endl;
        cin >> rec.rtlCost;
    }

    bool loop = true;
    while (loop){ 
        cout << endl << "Date added to inventory (MM-DD-YYYY)" << endl;
        cin.ignore();
        cin >> dateStr; 
        rec.date = dateValidation(dateStr);     
        if (rec.date.Year != 0000) {            
            loop = false;
        }
        else 
            cout << endl << "Error Date Format is (MM-DD-YYYY)" <<endl;
    }
    file.write(reinterpret_cast<char *>(&rec),sizeof(rec));
    cout << endl << "Record added to inventory" << endl;
    file.close();
    return true;
}

bool displayRecord(std::fstream& file)
{
    Inventory rec;
    file.open ("Inventory.dat", fstream::in | fstream::binary);
    long num;
    //Figure out How many records exist
    long a = file.tellg();
    file.seekg(0, fstream::end);
    long b = file.tellg();
    long sizeFile = b - a;
    int c = sizeof(rec);
    int numRecords = (sizeFile / c);

    if (numRecords > 0){
        cout << "Please enter the record you would like to view (1-"<< (numRecords) <<")" << endl;
        cin >> num;
        if ((num >= 0) && (num <= (numRecords))){
            num = num -1;
            file.seekg(num * sizeof(rec), fstream::beg);
            file.read(reinterpret_cast<char *>(&rec), sizeof(rec));
            if (!file.eof())
            {
                cout << endl << "Here is your current record:" << endl;
                cout << endl << "Item Description: ";
                cout << rec.desc << endl;
                cout << "Quantity on hand: ";
                cout << rec.quantity << endl;
                cout << "Wholesale cost: ";
                cout << rec.whlCost << endl;
                cout << "Retail cost: ";
                cout << rec.rtlCost << endl;
                cout << "Date added to inventory: ";
                cout << rec.date.Day << "-" << rec.date.Month << "-" << rec.date.Year << endl;                      
            }
            file.close();
        }
        else {
            cout << "Record Outside of Database Range" << endl;
        }
    }
    else {
        cout << "No Records Found !" << endl;
        return false;
    }
    return true;
}

bool changeRecord(std::fstream& file)
{
    Inventory rec;
    Inventory* recs;
    string dateStr;
    string yn;  
    char* buffer;   

    long num;

    file.open ("Inventory.dat", fstream::in | fstream::out | fstream::binary);

    //Figure out How many records exist
    long a = file.tellg();
    file.seekg(0, fstream::end);
    long b = file.tellg();
    long sizeFile = b - a;
    int numRecords = 0;
    if (sizeFile > 4){
        int c = sizeof(rec);
        numRecords = (sizeFile / c);
    }

    if (numRecords > 0){
        cout << "Please enter the record you would like to view (1-"<< (numRecords) <<")" << endl;
        cin >> num;
        if (!file.eof()){
            num = num -1;
            file.seekg(num * sizeof(rec), fstream::beg);
            file.read(reinterpret_cast<char *>(&rec), sizeof(rec));

            cout << endl << "Here is your current record" << endl;
            cout << endl << "Item description: ";
            cout << rec.desc << endl;
            cout << "Quantity on hand: ";
            cout << rec.quantity << endl;
            cout << "Wholesale cost: ";
            cout << rec.whlCost << endl;
            cout << "Retail cost: ";
            cout << rec.rtlCost << endl;
            cout << "Date added to inventory: ";
            cout << rec.date.Day << "-" << rec.date.Month << "-" << rec.date.Year << endl;

        }

        cout << endl << "Do you want to proceed ? (Y/N)" << endl;
        cin >> yn;
        if ((yn == "Y")||(yn == "y")){
            cout << endl << "Please enter your new data to the record"<< endl;
            cout << endl << "Item description:" << endl;
            cin.ignore();
            cin.getline(rec.desc, DESC_SIZE);
            cout << endl << "Quantity on hand:" << endl;
            cin >> rec.quantity;

            while (rec.quantity < 0)
            {
                cout << endl << "Invalid entry. Please enter only positive values." << endl;
                cin >> rec.quantity;
            }

            cout << endl << "Wholesale cost:" << endl;
            cin >> rec.whlCost;

            while (rec.whlCost < 0)
            {
                cout << endl << "Invalid entry. Please enter only positive values." << endl;
                cin >> rec.whlCost;
            }

            cout << endl << "Retail cost:" << endl;
            cin >> rec.rtlCost;

            while (rec.rtlCost < 0)
            {
                cout << endl << "Invalid entry. Please enter only positve values." << endl;
                cin >> rec.rtlCost;
            }

            bool loop = true;
            while (loop){ 
                cout << endl << "Date added to inventory (MM-DD-YYYY)" << endl;
                cin.ignore();
                cin >> dateStr; 
                rec.date = dateValidation(dateStr);     
                if (rec.date.Year != 0000) {            
                    loop = false;
                }
                else 
                    cout << endl << "Error Date Format is (MM-DD-YYYY)" <<endl;


            }

            file.seekp(num * sizeof(rec), fstream::beg);
            file.write(reinterpret_cast<char *>(&rec), sizeof(rec));
            cout << endl << "The Record has been edited." << endl;
        }
    }
    else cout << endl << "File contains no records!" << endl;
    file.close();
    return true;
}

As per my thinking, There are three different formats used for dates in different parts of the world. The United States uses a month-day-year format, Japan uses a year-month-day format and most of the rest of the world uses day-month-year.

You could "outsource" validation. If your regex is working, you could use match_results to obtain the different section, create a tim structure and pass that to mktime() for validation.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.