I want to create a simple "date" read using sscanf
which accepts inputs as:
"dd/mm/yyyy"
Both "dd" and "mm" fields can be, as much, 2 digits longs (eg. 0, 6 or 11, but not 123). The "years" field can be either 0 or a four digits field. A value of 0 in any of these three fields means the day, month or year of the system have to be taken instead.
That format must be strict, so, if the format of the input doesn't fit the pattern, the user must be notified.
My attempt is:
int d, m, y;
char const* input = "23/7/1990";
int n = sscanf(input, "%2u/%2u/%4u", &d, &m, &y);
if (n != 3) throw InvalidDate("Invalid format");
// Fill 0 values with system date.
// Check date correctness with `mktime` and `localtime`.
The problem is this sscanf
format accepts non-allowed inputs as:
char const* invalid1 = "23/ 12/ 1990";
char const* invalid2 = "23/12/1990/123whatever......."
So, is there any tricks/modifiers to reject leading zeros before integers, to mark the end of string, or to cause a detectable failure if more input is parsed?
For the last case (invalid2; detectable failure at the end of string), a possible solution would be:
int d, m, y;
char trick;
char const* input = "23/7/1990";
int n = sscanf(input, "%2u/%2u/%4u%c", &d, &m, &y, &trick);
// If it fills four fields, means the input was too long.
if (fields != 3) throw InvalidDate("Invalid format");
// Fill 0 values with system date.
But I don't know if there is a better way to detect the end-of-string
. Even more, this "format" (with the leading '%c') causes sscanf
believes the input was wrong with valid dates (for example, "23/6/1990" provokes the last char is not fill; if scanf
were used instead of sscanf
, ferror
would be set). I have even tried with "%2u/%2u/%4u\0"
but the compiler warns me with "embedded \0 in format".
So, what is the best solution without using regular expressions or stringstream
?
By the way, is there other ways to "cheat" sscanf
?