0

Related to Regex pattern for HH:MM:SS time string I am trying to validate user time input.

int main(int argc, char *argv[]){
        regex_t regex;
        int reti;
        char msgbuf[100];
        char inputStr2[100]="12:34:04";
        char inputStr[100]="12:34";

/* Compile regular expression */
        reti = regcomp(&regex, "^((([01]?[0-9]|2[0-3]):)?([0-5]?[0-9]):)?([0-5]?[0-9])$", 0);
        if( reti ){
        fprintf(stderr, "Could not compile regex\n");
        }

/* Execute regular expression */
           printf("%s is the string\n",inputStr);
        reti = regexec(&regex, inputStr, 0, NULL, 0);
        if( !reti ){
                puts("Match");
        }
        else if( reti == REG_NOMATCH ){
                puts("No match");
        }
        else{
                regerror(reti, &regex, msgbuf, sizeof(msgbuf));
                fprintf(stderr, "Regex match failed: %s\n", msgbuf);
        }
         printf("%s is the string\n",inputStr2);
        reti = regexec(&regex, inputStr2, 0, NULL, 0);
        if( !reti ){
                puts("Match");
        }
        else if( reti == REG_NOMATCH ){
                puts("No match");
        }
        else{
                regerror(reti, &regex, msgbuf, sizeof(msgbuf));
                fprintf(stderr, "Regex match failed: %s\n", msgbuf);
        }
/* Free compiled regular expression if you want to use the regex_t again */
    regfree(&regex);

        return 0;
}
  1. i get the error unknown escape sequence '\d'.

whats wrong here? Is this the best way to go about validating user time input?. Edit: Tried with "^(?:(?:([01]?\\d|2[0-3]):)?([0-5]?\\d):)?([0-5]?\\d)$" and i get a no match. Also with

Community
  • 1
  • 1
Aditya P
  • 1,862
  • 5
  • 28
  • 39
  • 1
    This does not handle the case of `24:00:00` ([midnight at the end of the day](http://en.wikipedia.org/wiki/ISO_8601#Times)), or `23:59:60` ([leap second](http://en.wikipedia.org/wiki/Leap_second)). And that's assuming that you only want to support times down to second precision. – user Feb 24 '12 at 10:05
  • @MichaelKjörling how would you do it then? – Aditya P Feb 24 '12 at 11:13
  • 2
    use [`strptime(%T)`](http://pubs.opengroup.org/onlinepubs/009695399/functions/strptime.html) – jfs Feb 24 '12 at 11:25
  • @J.F.Sebastian nice its simpler . but what do you figure is wrong above involving the usage of regexec ? – Aditya P Feb 24 '12 at 12:45
  • Your regex (in the edited post) doesn't contain a `\d` anymore, so I guess the error message you posted is not the actual error message you're currently getting. Can you tell us the real problem? – Tim Pietzcker Feb 28 '12 at 12:04
  • @TimPietzcker the expression does not evaluate the string to match. There is no error message. – Aditya P Feb 28 '12 at 12:08

4 Answers4

3

You could try strptime(), for example

struct tm t;
char p;

p = strptime(inputStr, "%H:%M:%S", &t);

if (p == NULL || *p != '\0') {
    abort();
}
Yann Droneaud
  • 5,277
  • 1
  • 23
  • 39
1

A POSIX regular expression engine does not support non-capturing groups (?:...). Use normal groups instead:

^((([01]?[0-9]|2[0-3]):)?([0-5]?[0-9]):)?([0-5]?[0-9])$

I don't have gcc installed. If the underlying regex engine is a POSIX BRE instead of a POSIX ERE (as I thought), then a different syntax is needed (because parentheses are treated as literals unless escaped, and POSIX BREs don't know the ? quantifier:

^\(\(\([01]\{0,1\}[0-9]|2[0-3]\):\)\{0,1\}\([0-5]\{0,1\}[0-9]\):\)\{0,1\}\([0-5]\{0,1\}[0-9]\)$

or, as a string:

"^\\(\\(\\([01]\\{0,1\\}[0-9]|2[0-3]\\):\\)\\{0,1\\}\\([0-5]\\{0,1\\}[0-9]\\):\\)\\{0,1\\}\\([0-5]\\{0,1\\}[0-9]\\)$"
Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
  • 1
    Are you aware that the regex is designed to match `HH:MM:SS` or `MM:SS` or `SS`? So `59:59` is a valid match. If that's OK for your requirements, fine. – Tim Pietzcker Feb 28 '12 at 12:17
  • sorry but i still get a no match, I am aware what the regex is desined to match. have you run the code gcc ? thats the entire program. – Aditya P Feb 28 '12 at 12:27
  • @AdityaGameProgrammer: Perhaps the underlying regex engine is only a POSIX BRE? I've edited my answer accordingly. – Tim Pietzcker Feb 28 '12 at 12:42
  • @AdityaGameProgrammer: I missed something: `?` doesn't exist in POSIX BREs, so it needs to be changed to `\{0,1\}`. With this, your program works, at least for match no. 1 - no idea why ideone says it fails for match no. 2. – Tim Pietzcker Feb 28 '12 at 15:26
  • +1 Its the same at my side posix gcc version 4.3.2 (Debian 4.3.2-1.1) . At least this is partially working. – Aditya P Feb 29 '12 at 05:34
0

Because when you write \ and then a letter compiler thinks it's a special character like \n (new line symbol) or \t (tab symbol). And there is no \d symbol that's why you're getting an error. You should write \\d if you mean "a digit". Actually you just need to escape the backslash (\ is the escape character in C, C++, Java, C# and many other languages).
For example this stirng "abc\n\\d" actually is "abc[enter]\d" in memory. So when you right \\d in pattern in fact it's kept in memory as \d, actually what you need.

shift66
  • 11,760
  • 13
  • 50
  • 83
0

In C, \ is an escape character in a string, you have to double it to get the escape character in a regex ie \\.

Try this:

"^(?:(?:([01]?\\d|2[0-3]):)?([0-5]?\\d):)?([0-5]?\\d)$"
sinsedrix
  • 4,336
  • 4
  • 29
  • 53