Parsing string

Discussion in 'C++' started by tech, Jun 25, 2008.

  1. tech

    tech Guest

    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;
    }
     
    tech, Jun 25, 2008
    #1
    1. Advertising

  2. tech

    Mirco Wahab Guest

    tech wrote:
    > 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.
     
    Mirco Wahab, Jun 25, 2008
    #2
    1. Advertising

  3. tech

    James Kanze Guest

    On Jun 25, 2:30 pm, Mirco Wahab <-halle.de> wrote:
    > 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:
    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
     
    James Kanze, Jun 25, 2008
    #3
  4. tech

    tech Guest

    On Jun 25, 4:37 pm, James Kanze <> wrote:
    > On Jun 25, 2:30 pm, Mirco Wahab <-halle.de> wrote:
    >
    >
    >
    >
    >
    > > 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:
    > 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.
     
    tech, Jun 25, 2008
    #4
  5. tech

    Mirco Wahab Guest

    tech wrote:
    > 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.
     
    Mirco Wahab, Jun 25, 2008
    #5
  6. tech

    Mirco Wahab Guest

    James Kanze wrote:
    > On Jun 25, 2:30 pm, Mirco Wahab <-halle.de> wrote:
    >> 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.
     
    Mirco Wahab, Jun 25, 2008
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. GIMME
    Replies:
    2
    Views:
    877
    GIMME
    Feb 11, 2004
  2. Naren
    Replies:
    0
    Views:
    585
    Naren
    May 11, 2004
  3. Christopher Diggins
    Replies:
    0
    Views:
    612
    Christopher Diggins
    Jul 9, 2007
  4. Christopher Diggins
    Replies:
    0
    Views:
    437
    Christopher Diggins
    Jul 9, 2007
  5. John Levine
    Replies:
    0
    Views:
    733
    John Levine
    Feb 2, 2012
Loading...

Share This Page