2
checkFormat(string &s)
{

}

string s is a string that indicate the date.

I want to compare a string s, to find whether it is in terms of "yyyy:mm::dd" or not.

What should I do?

compare it char by char? What if the string is "600:12:01" ?

Sorry for my poor English.

lpy
  • 587
  • 1
  • 6
  • 20

6 Answers6

4

Don't use regex. Use strptime(), which is designed to parse time strings (hence the name: str p time, string -> parse -> time). A regex can't figure out that 2013:2:29 is invalid.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • There is no `strptime()` in C++. It's an Open Systems (Unix) extension. Which means that it isn't portably available. – James Kanze Mar 20 '12 at 12:15
  • @JamesKanze: more the pity too, I don't understand why `strftime` would be available without counter part :x That said, the `` header contains quite a few quircks of this genre. – Matthieu M. Mar 20 '12 at 12:37
  • Fair point. [Boost DateTime](http://www.boost.org/doc/libs/1_49_0/doc/html/date_time/examples.html#date_time.examples.dates_as_strings) then? See also http://stackoverflow.com/questions/321849/strptime-equivalent-on-windows – MSalters Mar 20 '12 at 13:06
  • @MSalters Not just ``. Why does `gets()` remove the trailing `'\n'`, and `fgets()` not (and why doesn't `gets()` take the length of the buffer)? I think you can find some in just about any C header you look in. – James Kanze Mar 20 '12 at 13:23
  • (that should have been @MatthieuM. ) – MSalters Mar 20 '12 at 13:24
  • 2
    @MSalters I'm not familiar with Boost Date Time, so I can't comment. But in general, something specialized for time and dates should be preferred. Things like regular expressions are powerful tools, but there are enough quirky conventions surrounding times and dates that special handling seems in order. (While it's theoretically possible to write a regular expression that would accept `2012:02:29`, but reject `2011:02:29`, when the regular expression starts dragging out over 10 or 20 lines, it's time to consider something else. – James Kanze Mar 20 '12 at 13:27
2

Here's one idea for an algorithm:

  1. Check that the length is the expected one. This is quick.
  2. Check that the colons are in the expected places.
  3. Check that the first four characters are digits.
  4. Check that the middle two characters are digits.
  5. Check that the final two characters are digits.

If either test fails, return false. If you get through them all, return true.

Of course, this doesn't validate the ranges of the values. Also, you're not really "comparing", you are "validating".

unwind
  • 391,730
  • 64
  • 469
  • 606
  • +1 because of Jamie Zawinski's famous quote: Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems. – Matthieu M. Mar 20 '12 at 11:11
  • @MatthieuM. So you replace a one-liner with about 20 lines of code, which aren't really maintainable (and even as described, probably don't do the job correctly, since you do want to allow some liberties, e.g. `"2011:3:3"`). If you don't want to use regular expressions (1 line), you can do the job with `istringstream` in about 3 or 4; if you want to convert as well, this might be the preferred solution, since it does the conversion at the same time. – James Kanze Mar 20 '12 at 12:18
  • @JamesKanze: I am just wary of *pre-made* solutions that just don't pan out. Regular expressions are not a silver bullet, and proper engineering requires to think about alternative instead of diving head first into the first possible solution. Regular expressions *may* be the final solution, or they may not, depending on the requirements, let's just make sure we don't discard the alternatives without proper reflexion. – Matthieu M. Mar 20 '12 at 12:36
1

You can use Boost Regex to check whether the string matches your pattern.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
1

This is the job for regular expressions. Since you're using C++, Boost.Regex is one option.

teukkam
  • 4,267
  • 1
  • 26
  • 35
0

Easiest would to be slice the string into its component parts of year, month, day and compare those.

See here to split strings by delimiter.

Community
  • 1
  • 1
graham.reeds
  • 16,230
  • 17
  • 74
  • 137
0

Does your compiler support regular expressions, i.e. are you using a somewhat C++11 compliant compiler? This would make the task much easier … Otherwise you might want to resort to Boost.Regex.

Assuming that you can use C++11, the following code should do what you want (untested though):

std::regex rx("\\d{4}:\\d{2}:\\d{2}");
return regex_match(s.begin(), s.end(), rx);

John Cook has written an introduction into C++ regular expressions. Just replace every occurrence of std::tr1 by std if your compiler supports C++11.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214