Parsing string

T

tech

Hi, I need to parse a string used to represent a time and then
populate
a simple time struct. The time string will always be this format

23:45.45 ie hours separated from mins by ':' and minutes separated
from seconds by '.'
The string will be 8 chars in len. I've come up with some simple code
below
but am wondering do i really need a wstringstream and a string to do
this. Can
the parsing just be done with a wstringstream.

struct TIMESTRUCT
{
unsigned short Hour;
unsigned short Minute;
unsigned short Second;
}

bool TimeParser(const std::wstring& time, TIMESTRUCT& st)
{
std::wistringstream tmp;
// a time string must be 8 chars in len
assert(time.size() == 8);

tmp.str(time.substr(0, 2));
tmp >> st.Hour;
if (time[2] != ':') return false;
tmp.clear();
tmp.str(time.substr(3, 2));
tmp >> st.Minute;
if (time[5] != '.') return false;
tmp.clear();
tmp.str(time.substr(6, 2));
tmp >> st.Second;
return true;
}

int main()
{
TIMESTRUCT st;
std::wstring t(L"23:34.45");
TimeParser(t, st);
return 0;
}
 
M

Mirco Wahab

tech said:
Hi, I need to parse a string used to represent a time and then
populate a simple time struct. The time string will always be
this format 23:45.45 ie hours separated from mins by ':' and
minutes separated from seconds by '.'
The string will be 8 chars in len. I've come up with some simple code
below but am wondering do i really need a wstringstream and a
string to do this. Can
the parsing just be done with a wstringstream.

This would work with istringstream if you change
its formal argument from
bool TimeParser(const std::wstring& time, TIMESTRUCT& st)

to bool TimeParser(const std::string& time, TIMESTRUCT& st)

and the actual data from
int main()
{
TIMESTRUCT st;
std::wstring t(L"23:34.45");

to std::string t("23:34.45");


BTW, some people tend to do almost everythin
in regular expressions (which will be there
soon and are long available via boost).

Your TimeParser would be much simpler, like:

...
#include <boost/regex.hpp>
using namespace boost;
...

bool TimeParser(const std::string& time, TIMESTRUCT& st)
{
cmatch m;
if(regex_match(time.c_str(), m, regex("^(\\d{2}):(\\d{2})\\.(\\d{2})$"))) {
st.Hour = atoi(m[1].first);
st.Minute = atoi(m[2].first);
st.Second = atoi(m[3].first);
return true;
}
return false;
}

The required format "dd:dd.dd" would be checked by
the regular expression and all would be fine.

Regards

M.
 
J

James Kanze

tech wrote:
BTW, some people tend to do almost everythin
in regular expressions (which will be there
soon and are long available via boost).
Your TimeParser would be much simpler, like:
...
#include <boost/regex.hpp>
using namespace boost;
...
bool TimeParser(const std::string& time, TIMESTRUCT& st)
{
cmatch m;
if(regex_match(time.c_str(), m, regex("^(\\d{2}):(\\d{2})\\.(\\d{2})$"))) {
st.Hour = atoi(m[1].first);
st.Minute = atoi(m[2].first);
st.Second = atoi(m[3].first);
return true;
}
return false;
}
The required format "dd:dd.dd" would be checked by
the regular expression and all would be fine.

Two small nits: first, regex_match can take iterators, so you
can just write:
if ( regex_match( time.begin(), time.end(), m, expr ) ) ...
And since the expression is a constant, that's how I'd write it:
static regex const expr( "^(\\d{2}):(\\d{2})\\.(\\d{2})$" ) ;
(at the start of the function, before the if).
 
T

tech

tech wrote:
BTW, some people tend to do almost everythin
in regular expressions (which will be there
soon and are long available via boost).
Your TimeParser would be much simpler, like:
   ...
   #include <boost/regex.hpp>
   using namespace boost;
   ...
   bool TimeParser(const std::string& time, TIMESTRUCT& st)
  {
   cmatch m;
   if(regex_match(time.c_str(), m, regex("^(\\d{2}):(\\d{2})\\.(\\d{2})$"))) {
      st.Hour   = atoi(m[1].first);
      st.Minute = atoi(m[2].first);
      st.Second = atoi(m[3].first);
      return true;
   }
   return false;
  }
The required format "dd:dd.dd" would be checked by
the regular expression and all would be fine.

Two small nits: first, regex_match can take iterators, so you
can just write:
    if ( regex_match( time.begin(), time.end(), m, expr ) ) ...
And since the expression is a constant, that's how I'd write it:
    static regex const expr( "^(\\d{2}):(\\d{2})\\.(\\d{2})$" ) ;
(at the start of the function, before the if).

--
James Kanze (GABI Software)             email:[email protected]
Conseils en informatique orientée objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34- Hide quoted text -

- Show quoted text -

Thanks guys but i was wondering whether i could do my simple function
with just
a stringstream rather with a string aswell.
 
M

Mirco Wahab

tech said:
Thanks guys but i was wondering whether i could do my simple function
with just a stringstream rather with a string aswell.

I don't completely understand what you
want and what you are trying to
accomplish. What means:
/with just a stringstream rather with a string aswell/

If you only want to get rid of the w_ functions, just
don't use them:

bool TimeParser(const std::string& time, TIMESTRUCT& st)
{
assert(time.size() == 8); // a time string must be 8 chars
char a ,b;
std::istringstream tmp(time);
tmp >> st.Hour >> a >> st.Minute >> b >> st.Second;
return a == ':' && b == '.' ? true : false;
}

int main()
{
TIMESTRUCT st;
std::string t("03:34.45");
TimeParser(t, st);
return 0;
}

But maybe there's something else?

Regards

M.
 
M

Mirco Wahab

James said:
bool TimeParser(const std::string& time, TIMESTRUCT& st)
{
cmatch m;
if(regex_match(time.c_str(), m, regex("^(\\d{2}):(\\d{2})\\.(\\d{2})$"))) {
st.Hour = atoi(m[1].first);
st.Minute = atoi(m[2].first);
st.Second = atoi(m[3].first);
return true;
}
return false;
}

Two small nits: first, regex_match can take iterators, so you
can just write:
if ( regex_match( time.begin(), time.end(), m, expr ) ) ...

This would require the smatch overloaded 'regex_match',
which returns std::string objects in matches and does,
in this case, also provide a version that uses the
plain std::string:

bool TimeParser(const std::string& time, TIMESTRUCT& st)
{
using namespace boost;
smatch m;
static regex r("^(\\d{2}):(\\d{2})\\.(\\d{2})$");
if(regex_match(time, m, r)) {
st.Hour = atoi(m[1].str().c_str());
st.Minute = atoi(m[2].str().c_str());
st.Second = atoi(m[3].str().c_str());
return true;
}
return false;
}

The use of the smatch-overloaded regex_... requires
an additional step to extract the resulting values,
compare it to the original version:

bool TimeParser(const std::string& time, TIMESTRUCT& st)
{
using namespace boost;
cmatch m;
if(regex_match(time.c_str(), m, regex("^(\\d{2}):(\\d{2})\\.(\\d{2})$"))) {
st.Hour = atoi(m[1].first);
st.Minute = atoi(m[2].first);
st.Second = atoi(m[3].first);
return true;
}
return false;
}

Which looks (imho) less cluttered.
And since the expression is a constant, that's how I'd write it:
static regex const expr( "^(\\d{2}):(\\d{2})\\.(\\d{2})$" ) ;
(at the start of the function, before the if).

This would, of course, be better from a technical point of view
but it costs one additional line ;-) But if you are paid for
LOCaday ...

Regards & thanks

M.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top