1

How do I verify that the last four digits in a string are in the range of 1900 and 2100 inclusive? I don't even need the exact answer, but atleast how to check digits inside of a string.

string getDate()
{
    string date = "";
    cout << "\nEnter a date in military format (DDMMMYYYY) such as:\n"
         << "-- 13MAR1999 for March 13, 1999\n"
         << "-- 01APR2025 for April 1, 2025\n"
         << "-- Note: year must be between 1900-2100.\n"
         << "Entry --> ";
         cin >> date;
    while(date.length() > 9 || date.length() < 9)
    {
        cout << "\nInvalid entry, must be 9 characters.\n";
        getDate();
    }
    if (date[5] < 1 || date[5] > 2)
    {
        cout << "\nYear must be between 1900-2100.\n";
        getDate();
    }
    return date;
}
AutumnSail
  • 63
  • 1
  • 1
  • 7
  • There is a big, very big difference between the number 1 and the character '1'. They are not, I repeated, are not the same. You can start by fixing this bug in the code, so that it correctly checks for the range 1000-2999, and then once you've figured that out, figuring out how to tweak this check for 1000-2100 should be easy. – Sam Varshavchik Dec 12 '18 at 02:59
  • try single quotes around your '1' and '2' – dgrogan Dec 12 '18 at 03:02
  • @SamVarshavchik I wouldn't say it's *very* big. The difference between `'1'` and `1` is 48 :) (in ascii encoding) – Kevin Dec 12 '18 at 03:03
  • you could use entered string data to make epoch time representations, like in this post https://stackoverflow.com/questions/4137748/c-converting-a-time-string-to-seconds-from-the-epoch . Make epoch time representation for years 1900 and 2100 and then use your comparison operators – HappyKeyboard Dec 12 '18 at 03:47
  • 2
    You do here recurrent calls so lookout on that! – Gelldur Dec 12 '18 at 09:09

1 Answers1

3

Currently, your check that if (date[5] < 1 || date[5] > 2) is not exactly what you intend. Most C++ (and C) compilers encode its characters following ASCII. So the character '0' (often) has an integer value of 48, the character '1' (often) has an integer value of 49 and so on.

Another issue with your current code is with the recursion. The following piece of code will loop, print output, and recurse indefinitely. (Even if the next date entry is valid, it will continue looping.)

while(date.length() > 9 || date.length() < 9)
{
    cout << "\nInvalid entry, must be 9 characters.\n";
    getDate();
}

You can simply use an if-statement here... and remember to handle your recursion properly. (i.e. You want to make sure that the result of the new getDate() is returned. Thus, return getDate();)

Rather than using a barrage of if-statements, I'd recommend converting the string to a number first before checking whether or not it is within the range 1900 to 2100.

string getDate()
{

    std::string date = "01APR2021";  //  read date (or hard-code it)

    // perform checks


    if (date.length() != 9) // you can simplify your length check
    {
        // error message

        return getDate();  //  beware of your while-loop and recursion
    }

    std::string lastFour(date.end() - 4, date.end());  // substring of last four characters of date
    std::string::size_type noIntTrack;  // tracks the stoi finishing position

    int year = std::stoi(lastFour, &noIntTrack);  // converts the year to an integer

    if (noIntTrack != 4)  // if not 4 => unsuccessful conversion
    {                     //   e.g. maybe user entered 01APR20AA
        // error handling:
        //   noIntTrack should be 4 to signify successful conversion of all characters

        return getDate(); // recurse
    }

    if (!(1990 <= year && year <= 2100))  // check if year not in range
    {
        // handle year out of range

        return getDate();
    }

    // other checks (e.g. month/date?)
    // if (date is not good) { return getDate(); }

    // date is valid:
    // party
    return date;
}
TrebledJ
  • 8,713
  • 7
  • 26
  • 48